/*
 *      wlan.c from Access Point SNMP Utils for Linux
 *
 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 from
 * June 1991 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */
#include <string.h>
#include <stdlib.h>
#include <menu.h>
#include <unistd.h>
#include <sys/types.h>
#include "ap-utils.h"

#define ESSID _("[E] ESSID: ")
#define AP_NAME _("[N] AP name: ")

#define CONTACT _("[K] AP contact: ")
#define LOCATION _("[L] AP location: ")

#define RTS_TR _("[R] RTS threshold: ")
#define FRG_TR _("[F] Fragmentation threshold: ")
#define PREAMBULE _("[P] Preambule type: ")
#define AUTH _("[A] Auth type: ")
#define   OSYS _("Open system")
#define   SH_KEY _("Shared key")
#define   BOTH_TYPE _("Both types")
#define RETRAIN _("[U] Auto rate fallback: ")
#define HIDE_ESSID _("[S] Insert ESSID in broadcast packets: ")
#define RATES _("Basic and Supported rates:")
#define RATES_HEAD _("Key   Rate  Status")
#define   RATES_RECORD "[%d]  %4.1fM   "
#define INT_ROAMING _("[I] International roaming: ")
#define BEACON_PER _("[B] Beacon period (msec): ")
#define DTIM_I _("[D] DTIM sending interval (beacons): ")
#define SIFS_T _("[T] SIFS time (2nd+ interframe spacing, usec): ")
#define WLAN_HELP _("[key] - set option; W - write conf; Q - quit to menu")

extern short ap_type, ap_vendorext;

void atmel_wireless()
{
    char sysDeviceInfo[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x05, 0x00
    };

    char operChannelID[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x01, 0x00
    };
    char operESSIDLength[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x02, 0x00
    };
    char operESSID[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x03, 0x00
    };
    char operRTSThreshold[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x04, 0x00
    };
    char operFragmentationThreshold[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x05, 0x00
    };
    char operPreambleType[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x06, 0x00
    };
    char operAuthenticationType[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x07, 0x00
    };
    char operBasicRates[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x08, 0x00
    };
    char operAutoRateFallBack[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x09, 0x00
    };
    char operAccessPointName[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x0A, 0x00
    };
    char operSSIDBroadcasting[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x0B, 0x00
    };

    /* This one is ATMEL12350 MIB specific. */
    char operInterRoaming[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x01, 0x0D, 0x00
    };
    /* These two are ATMEL12350 GEMTEK MIB specific. */
    char operBeaconPeriod[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x01, 0x0E, 0x00
    };
    char operDTIM[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x01, 0x0F, 0x00
    };
    /* This one is ATMEL12350 EZYNET MIB specific. */
    char operSIFSTIME[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x01, 0x10, 0x00
    };

    extern WINDOW *main_sub;
    extern rdprops regdom_types[];
    extern char *channels[];
    varbind varbinds[16];
    unsigned short int RTSThreshold, FragmentationThreshold,
	InterRoaming, m_basic_rates = 0, BeaconPeriod = 0, sifs = 0;
    unsigned char dtim, ch;
    char *AuthenticationTypes[3] = { OSYS, SH_KEY, BOTH_TYPE },
	message[1024];
    char domain[33], basic_rates[4], AutoRateFallBack, SSIDBroadcasting,
	ap_name[33], PreambleType, AuthenticationType, channel;
    char m_channel = 0, m_essid = 0, m_broadcast = 0, m_rts = 0,
	m_fragment = 0, m_auth = 0, m_ap_name = 0, m_preambule = 0,
	m_auto_rate = 0, m_inter_roaming = 0, m_beacon = 0, m_dtim = 0,
	m_sifs = 0;
    char *rates[3] = { ON, OFF, BASIC }, *preambules[2] = {
    _("Short"), _("Long")};
    short __rates[4] = { 2, 4, 11, 22 };
    int i, c = 0, rd_idx;
    unsigned short ap_regdomain;
    struct sysDeviceInfo_128 str128;
    struct sysDeviceInfo_160 str160;


    if (ap_type == ATMEL12350) {
	sysDeviceInfo[5] = 0xE0;
	sysDeviceInfo[6] = 0x3E;
	operChannelID[5] = 0xE0;
	operChannelID[6] = 0x3E;
	operESSIDLength[5] = 0xE0;
	operESSIDLength[6] = 0x3E;
	operESSID[5] = 0xE0;
	operESSID[6] = 0x3E;
	operRTSThreshold[5] = 0xE0;
	operRTSThreshold[6] = 0x3E;
	operFragmentationThreshold[5] = 0xE0;
	operFragmentationThreshold[6] = 0x3E;
	operPreambleType[5] = 0xE0;
	operPreambleType[6] = 0x3E;
	operAuthenticationType[5] = 0xE0;
	operAuthenticationType[6] = 0x3E;
	operBasicRates[5] = 0xE0;
	operBasicRates[6] = 0x3E;
	operAutoRateFallBack[5] = 0xE0;
	operAutoRateFallBack[6] = 0x3E;
	operAccessPointName[5] = 0xE0;
	operAccessPointName[6] = 0x3E;
	operSSIDBroadcasting[5] = 0xE0;
	operSSIDBroadcasting[6] = 0x3E;
    }

    for (i = 0; i < 16; i++) {
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	varbinds[i].len_oid = sizeof(operChannelID);
    }

    i = 0;

    varbinds[i++].oid = operChannelID;
    varbinds[i++].oid = operESSIDLength;
    varbinds[i++].oid = operESSID;
    varbinds[i++].oid = operSSIDBroadcasting;
    varbinds[i++].oid = operBasicRates;
    varbinds[i++].oid = operAutoRateFallBack;
    varbinds[i++].oid = operRTSThreshold;
    varbinds[i++].oid = operFragmentationThreshold;
    varbinds[i++].oid = operPreambleType;
    varbinds[i++].oid = operAuthenticationType;
    varbinds[i++].oid = operAccessPointName;
    varbinds[i++].oid = sysDeviceInfo;
    if (ap_type == ATMEL12350) {
	varbinds[i++].oid = operInterRoaming;
	if (ap_vendorext == GEMTEK || ap_vendorext == EZYNET) {
	    varbinds[i++].oid = operBeaconPeriod;
	    varbinds[i++].oid = operDTIM;
	}
	if (ap_vendorext == EZYNET)
	    varbinds[i++].oid = operSIFSTIME;
    }

    print_help(WAIT_RET);
    if (snmp(varbinds, i, GET) < i) {
	print_helperr(ERR_RET);
	goto exit;
    }

    channel = *(varbinds[0].value);
    c = *(varbinds[1].value);
    memcpy(domain, varbinds[2].value, 32);
    domain[32] = '\0';
    SSIDBroadcasting = *(varbinds[3].value);
    memcpy(basic_rates, varbinds[4].value, 4);
    AutoRateFallBack = *(varbinds[5].value);
    memcpy(&RTSThreshold, varbinds[6].value, 2);
    RTSThreshold = ntohs(RTSThreshold);
    memcpy(&FragmentationThreshold, varbinds[7].value, 2);
    FragmentationThreshold = ntohs(FragmentationThreshold);
    PreambleType = *(varbinds[8].value);
    AuthenticationType = *(varbinds[9].value);
    memcpy(ap_name, varbinds[10].value, 32);
    ap_name[32] = '\0';
    if (ap_type == ATMEL12350) {
	InterRoaming = *(varbinds[12].value);
	if (ap_vendorext == GEMTEK || ap_vendorext == EZYNET) {
	    BeaconPeriod = varbinds[13].len_val == 2 ?
		(varbinds[13].value[0] << 8) | varbinds[13].value[1] :
		varbinds[13].value[0] < 0x80 ?
		varbinds[13].value[0] : 0xff00 | varbinds[13].value[0];
	    dtim = *(varbinds[14].value);
	}
	if (ap_vendorext == EZYNET)
	    sifs = varbinds[15].len_val == 2 ?
		(varbinds[15].value[0] << 8) | varbinds[15].value[1] :
		varbinds[15].value[0] < 0x80 ?
		varbinds[15].value[0] : 0xff00 | varbinds[15].value[0];
    }

    if (varbinds[11].len_val == 160) {
	memcpy(&str160, varbinds[11].value,
	    sizeof(struct sysDeviceInfo_160));
	ap_regdomain = str160.RegulatoryDomain;
    } else { /* varbinds[11].len_val == 92 || varbinds[11].len_val == 128 */
	memcpy(&str128, varbinds[11].value,
	    sizeof(struct sysDeviceInfo_128));
	ap_regdomain = swap4(str128.RegulatoryDomain);
    }

    rd_idx = regdom_idx(ap_regdomain);

    print_top(NULL, _("Wireless Settings"));

    sprintf(message, "%s%02u (%u MHz)", CHANNEL, channel, 2407 + 5 * channel);
    mvwaddstr(main_sub, 0, 0, message);
    mvwaddstr(main_sub, 1, 0, ESSID);
    waddnstr(main_sub, domain, c);
    mvwaddstr(main_sub, 2, 0, AP_NAME);
    for (i = 0; i < 32 && ap_name[i]; i++)
	mvwaddch(main_sub, 2, strlen(AP_NAME) + i, ap_name[i]);
    sprintf(message, "%s%d", RTS_TR, RTSThreshold);
    mvwaddstr(main_sub, 3, 0, message);
    sprintf(message, "%s%d", FRG_TR, FragmentationThreshold);
    mvwaddstr(main_sub, 4, 0, message);
    sprintf(message, "%s%s", PREAMBULE, preambules[PreambleType - 1]);
    mvwaddstr(main_sub, 5, 0, message);
    sprintf(message, "%s%s", AUTH, AuthenticationTypes[AuthenticationType - 1]);
    mvwaddstr(main_sub, 6, 0, message);
    sprintf(message, "%s%s", RETRAIN, (AutoRateFallBack == 1) ? ON : OFF);
    mvwaddstr(main_sub, 7, 0, message);
    sprintf(message, "%s%s", HIDE_ESSID, (SSIDBroadcasting == 1) ? ON : OFF);
    mvwaddstr(main_sub, 8, 0, message);
    mvwaddstr(main_sub, 9, 0, RATES);
    mvwaddstr(main_sub, 10, 2, RATES_HEAD);
    for (i = 0; i < 4; i++) {
	sprintf(message, RATES_RECORD "%s", i + 1, (float) __rates[i] / 2,
		basic(basic_rates[i]));
	mvwaddstr(main_sub, 11 + i, 2, message);
    }
    if (ap_type == ATMEL12350) {
	sprintf(message, "%s%s", INT_ROAMING, (InterRoaming == 1) ? ON : OFF);
	mvwaddstr(main_sub, 15, 0, message);
	if (ap_vendorext == GEMTEK || ap_vendorext == EZYNET) {
	    sprintf(message, "%s%u", BEACON_PER, BeaconPeriod);
	    mvwaddstr(main_sub, 16, 0, message);
	    sprintf(message, "%s%u", DTIM_I, dtim);
	    mvwaddstr(main_sub, 17, 0, message);
	}
	if (ap_vendorext == EZYNET) {
	    sprintf(message, "%s%u", SIFS_T, sifs);
	    mvwaddstr(main_sub, 18, 0, message);
	}
    }

    wrefresh(main_sub);
    noecho();
    print_help(WLAN_HELP);

    while (1) {
	c = getch();
	switch (c) {
	case 'Q':
	case 'q':
	    goto quit;
	case '1':
	case '2':
	case '3':
	case '4':
	    message[0] = c;
	    message[1] = '\0';
	    i = atoi(message);
	    switch (menu_choose(10 + i, 15, rates, 3)) {
	    case 0:
		basic_rates[i - 1] = __rates[i - 1];
		break;
	    case 1:
		basic_rates[i - 1] = 0;
		break;
	    case 2:
		basic_rates[i - 1] = __rates[i - 1] + 0x80;
	    }
	    clear_main_new(10 + i, 11 + i);
	    sprintf(message, RATES_RECORD, i, (float) __rates[i - 1] / 2);
	    print_menusel(10 + i, 2, message, basic(basic_rates[i - 1]));
	    m_basic_rates = 1;
	    break;
	case 'C':
	case 'c':
	    channel = menu_choose(0, strlen(CHANNEL),
#ifndef NO_REG_DOMAIN
		channels + regdom_types[rd_idx].first_ch - 1,
		regdom_types[rd_idx].chans) + regdom_types[rd_idx].first_ch;
#else
		channels, 14) + 1;
#endif
	    sprintf(message, "%02u (%u MHz)", channel, 2407 + 5 * channel);
	    print_menusel(0, 0, CHANNEL, message);
	    m_channel = 1;
	    continue;
	case 'A':
	case 'a':
	    AuthenticationType =
		menu_choose(6, strlen(AUTH), AuthenticationTypes, 3) + 1;
	    clear_main_new(6, 7);
	    print_menusel(6, 0, AUTH,
		    AuthenticationTypes[AuthenticationType - 1]);
	    m_auth = 1;
	    continue;
	case 'P':
	case 'p':
	    PreambleType = menu_choose(5, strlen(PREAMBULE), preambules, 2) + 1;
	    clear_main_new(5, 6);
	    print_menusel(5, 0, PREAMBULE, preambules[PreambleType - 1]);
	    m_preambule = 1;
	    continue;
	case 'U':
	case 'u':
	    AutoRateFallBack = on_off(7, strlen(RETRAIN));
	    clear_main_new(7, 8);
	    print_menusel(7, 0, RETRAIN, (AutoRateFallBack == 1) ? ON : OFF);
	    m_auto_rate = 1;
	    continue;
	case 'S':
	case 's':
	    SSIDBroadcasting = on_off(8, strlen(HIDE_ESSID));
	    clear_main_new(8, 9);
	    print_menusel(8, 0, HIDE_ESSID, (SSIDBroadcasting == 1) ? ON : OFF);
	    m_broadcast = 1;
	    continue;
	case 'N':
	case 'n':
//          make_field(2, strlen(AP_NAME), 33);
	    get_value(ap_name, 2, strlen(AP_NAME), -33, ANY_STRING, 0, 0, NULL);
	    m_ap_name = 1;
	    continue;
	case 'E':
	case 'e':
//          make_field(1, strlen(ESSID), 33);
	    get_value(domain, 1, strlen(ESSID), 33, ANY_STRING, 0, 0, NULL);
	    m_essid = 1;
	    continue;
	case 'F':
	case 'f':
//          make_field(4, strlen(FRG_TR), 6);
	    get_value(message, 4, strlen(FRG_TR), 5, INT_STRING, 256, 2346,
		WLAN_HELP);
	    FragmentationThreshold = atoi(message);
	    m_fragment = 1;
	    continue;
	case 'R':
	case 'r':
//          make_field(3, strlen(RTS_TR), 6);
	    get_value(message, 3, strlen(RTS_TR), 5, INT_STRING, 0, 2347,
		WLAN_HELP);
	    RTSThreshold = atoi(message);
	    m_rts = 1;
	    continue;
	case 'I':
	case 'i':
	    if (ap_type == ATMEL410)
		continue;
	    InterRoaming = on_off(15, strlen(INT_ROAMING));
	    clear_main_new(15, 16);
	    print_menusel(15, 0, INT_ROAMING, (InterRoaming == 1) ? ON : OFF);
	    m_inter_roaming = 1;
	    continue;
	case 'B':
	case 'b':
	    if (ap_vendorext != GEMTEK && ap_vendorext != EZYNET)
		continue;
	    get_value(message, 16, strlen(BEACON_PER), 6, INT_STRING, 0, 65535,
		WLAN_HELP);
	    BeaconPeriod = atoi(message);
	    m_beacon = 1;
	    continue;
	case 'D':
	case 'd':
	    if (ap_vendorext != GEMTEK && ap_vendorext != EZYNET)
		continue;
	    get_value(message, 17, strlen(DTIM_I), 4, INT_STRING, 0, 255,
		WLAN_HELP);
	    dtim = atoi(message);
	    m_dtim = 1;
	    continue;
	case 'T':
	case 't':
	    if (ap_vendorext != EZYNET)
		continue;
	    get_value(message, 18, strlen(SIFS_T), 6, INT_STRING, 0, 65535,
		WLAN_HELP);
	    sifs = atoi(message);
	    m_sifs = 1;
	    continue;
	case 'w':
	case 'W':
	    i = 0;
	    if (m_channel) {
		varbinds[i].oid = operChannelID;
		varbinds[i].len_oid = sizeof(operChannelID);
		varbinds[i].value = (char *) &channel;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_basic_rates) {
		for (m_basic_rates = 0; m_basic_rates < 2; m_basic_rates++) {
		    c = basic_rates[3 - m_basic_rates];
		    basic_rates[3 - m_basic_rates] =
			basic_rates[m_basic_rates];
		    basic_rates[m_basic_rates] = c;
		}
		varbinds[i].oid = operBasicRates;
		varbinds[i].len_oid = sizeof(operBasicRates);
		varbinds[i].value = basic_rates;
		varbinds[i].len_val = 4;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_broadcast) {
		varbinds[i].oid = operSSIDBroadcasting;
		varbinds[i].len_oid = sizeof(operSSIDBroadcasting);
		varbinds[i].value = (char *) &SSIDBroadcasting;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_auth) {
		varbinds[i].oid = operAuthenticationType;
		varbinds[i].len_oid = sizeof(operAuthenticationType);
		varbinds[i].value = &AuthenticationType;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_preambule) {
		varbinds[i].oid = operPreambleType;
		varbinds[i].len_oid = sizeof(operPreambleType);
		varbinds[i].value = &PreambleType;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_auto_rate) {
		varbinds[i].oid = operAutoRateFallBack;
		varbinds[i].len_oid = sizeof(operAutoRateFallBack);
		varbinds[i].value = &AutoRateFallBack;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_ap_name) {
		c = strlen(ap_name);
		varbinds[i].oid = operAccessPointName;
		varbinds[i].len_oid = sizeof(operAccessPointName);
		varbinds[i].value = ap_name;
		varbinds[i].len_val = c;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }
	    if (m_fragment) {
		varbinds[i].oid = operFragmentationThreshold;
		varbinds[i].len_oid = sizeof(operFragmentationThreshold);
		FragmentationThreshold = htons(FragmentationThreshold);
		varbinds[i].value = (char *) &FragmentationThreshold;
		varbinds[i].len_val = 2;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_rts) {
		varbinds[i].oid = operRTSThreshold;
		varbinds[i].len_oid = sizeof(operRTSThreshold);
		RTSThreshold = htons(RTSThreshold);
		varbinds[i].value = (char *) &RTSThreshold;
		varbinds[i].len_val = 2;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_essid) {
		ch = strlen(domain);
		varbinds[i].oid = operESSIDLength;
		varbinds[i].len_oid = sizeof(operESSIDLength);
		varbinds[i].value = (char *)&ch;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
		varbinds[i].oid = operESSID;
		varbinds[i].len_oid = sizeof(operESSID);
		varbinds[i].value = domain;
		varbinds[i].len_val = ch;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }
	    if (m_inter_roaming) {
		varbinds[i].oid = operInterRoaming;
		varbinds[i].len_oid = sizeof(operInterRoaming);
		varbinds[i].value = (char *) &InterRoaming;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_beacon) {
		varbinds[i].oid = operBeaconPeriod;
		varbinds[i].len_oid = sizeof(operBeaconPeriod);
		BeaconPeriod = htons(BeaconPeriod);
		varbinds[i].value = (char *) &BeaconPeriod;
		varbinds[i].len_val = 2;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_dtim) {
		varbinds[i].oid = operDTIM;
		varbinds[i].len_oid = sizeof(operDTIM);
		varbinds[i].value = (char *) &dtim;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }
	    if (m_sifs) {
		varbinds[i].oid = operSIFSTIME;
		varbinds[i].len_oid = sizeof(operSIFSTIME);
		sifs = htons(sifs);
		varbinds[i].value = (char *) &sifs;
		varbinds[i].len_val = 2;
		varbinds[i].type = INT_VALUE;
		i++;
	    }

	    print_help(WAIT_SET);
	    if (snmp(varbinds, i, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }
	    wbkgd(main_sub, A_NORMAL);
	    wrefresh(main_sub);
	    print_help(DONE_SET);
	    goto exit;
	}
    }

  exit:
    getch();
  quit:
    print_top(NULL, NULL);
    clear_main(0);
}

void nwn_wireless()
{
    char operESSID[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x01, 0x01, 0x09, 0x01 };
    char operBasicRates[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x01, 0x01, 0x0b, 0x01 };
    char OpenSystem[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x02, 0x01, 0x03, 0x01, 0x01 };
    char SharedKey[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02 };
    char operRTSThreshold[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x01, 0x01, 0x02, 0x01 };
    char operFragmentationThreshold[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x01, 0x01, 0x05, 0x01 };
    char operChannelID[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x04, 0x05, 0x01, 0x01, 0x01 };
    char oid_dot11SupportedAntenna[][11] = {
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x04, 0x08, 0x01, 0x02, 0x01, 0x01 },
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x04, 0x08, 0x01, 0x02, 0x01, 0x02 },
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x04, 0x08, 0x01, 0x03, 0x01, 0x01 },
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x04, 0x08, 0x01, 0x03, 0x01, 0x02 },
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x04, 0x08, 0x01, 0x04, 0x01, 0x01 },
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x04, 0x08, 0x01, 0x04, 0x01, 0x02 }
    };
    char operAccessPointContact[] =
	{ 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x04, 0x00 };
    char operAccessPointName[] =
	{ 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x05, 0x00 };
    char operAccessPointLocation[] =
	{ 0x2b, 0x06, 0x01, 0x02, 0x01, 0x01, 0x06, 0x00 };
    char sysTrapSwitch[] =
	{ 0x2b, 0x06, 0x01, 0x02, 0x01, 0x0b, 0x1e, 0x00 };
    char ChannelPref[] =
	{ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x02, 0x01,
	0x06, 0x00 };

    unsigned short int i, RTSThreshold, FragmentationThreshold,
	m_basic_rates = 0, authi;
    char *auth[3] = { OSYS, SH_KEY, BOTH_TYPE },
	 *rates[3] = { ON, OFF, BASIC },
	 message[1024],
	 m_antenna[6] = { 0, 0, 0, 0, 0, 0 },
	 antenna[6],
	 channel_pref[2] = { 0, 0 };
    extern WINDOW *main_sub;
    extern rdprops regdom_types[];
    extern char *channels[];
    char *domain, basic_rates[] =
	{ 0, 0, 0, 0 }, *ap_name, ap_location[32], ap_contact[32],
	m_ap_contact = 0, m_ap_location = 0;
    char m_channel = 0, m_essid = 0, m_rts = 0, m_fragment = 0, m_auth =
	0, m_ap_name = 0, channel, traps, m_traps = 0;
    varbind varbinds[11];
    int c = 0, reg_domain = 0, rd_idx;
    short __rates[4] = { 2, 4, 11, 22};

    domain = (char *) calloc(32, 1);
    ap_name = (char *) calloc(32, 1);

    for (i = 0; i < 8; i++) {
	varbinds[i].len_val = 0;
	varbinds[i].type = NULL_VALUE;
    }
    varbinds[0].oid = operChannelID;
    varbinds[0].len_oid = sizeof(operChannelID);
    varbinds[1].oid = operESSID;
    varbinds[1].len_oid = sizeof(operESSID);
    varbinds[2].oid = operRTSThreshold;
    varbinds[2].len_oid = sizeof(operRTSThreshold);
    varbinds[3].oid = operFragmentationThreshold;
    varbinds[3].len_oid = sizeof(operFragmentationThreshold);
    varbinds[4].oid = operBasicRates;
    varbinds[4].len_oid = sizeof(operBasicRates);
    varbinds[5].oid = OpenSystem;
    varbinds[5].len_oid = sizeof(OpenSystem);
    varbinds[6].oid = SharedKey;
    varbinds[6].len_oid = sizeof(SharedKey);
    varbinds[7].oid = operAccessPointName;
    varbinds[7].len_oid = sizeof(operAccessPointName);
    print_help(WAIT_RET);
    if (snmp(varbinds, 8, GET) < 8) {
	print_helperr(ERR_RET);
	goto exit;
    }

    channel = *(varbinds[0].value);
    memcpy(domain, varbinds[1].value, varbinds[1].len_val);
    memcpy(basic_rates, varbinds[4].value, varbinds[4].len_val);
    memcpy(&RTSThreshold, (varbinds[2].value), 2);
    RTSThreshold = ntohs(RTSThreshold);
    memcpy(&FragmentationThreshold, (varbinds[3].value), 2);
    FragmentationThreshold = ntohs(FragmentationThreshold);
    authi = (*(varbinds[5].value) == 1 && *(varbinds[6].value) == 1) ? 2 :
	(*(varbinds[5].value) == 1) ? 0 : 1;
    memcpy(ap_name, varbinds[7].value, varbinds[7].len_val);

    sprintf(message, "%s%02u (%u MHz)", CHANNEL, channel, 2407 + 5 * channel);
    mvwaddstr(main_sub, 0, 0, message);
    mvwaddstr(main_sub, 1, 0, ESSID);
    for (i = 0; i < 32 && domain[i]; i++)
	mvwaddch(main_sub, 1, strlen(ESSID) + i, domain[i]);
    mvwaddstr(main_sub, 2, 0, AP_NAME);
    for (i = 0; i < 32 && ap_name[i]; i++)
	mvwaddch(main_sub, 2, strlen(AP_NAME) + i, ap_name[i]);
    sprintf(message, "%s%d", RTS_TR, RTSThreshold);
    mvwaddstr(main_sub, 3, 0, message);
    sprintf(message, "%s%d", FRG_TR, FragmentationThreshold);
    mvwaddstr(main_sub, 4, 0, message);
    sprintf(message, "%s%s", AUTH, auth[authi]);
    mvwaddstr(main_sub, 6, 0, message);
    mvwaddstr(main_sub, 9, 0, RATES);
    mvwaddstr(main_sub, 10, 2, RATES_HEAD);
    for(i = 0; i < 4; i++) {
	sprintf(message, RATES_RECORD "%s", i + 1, (float) __rates[i] / 2,
		basic(basic_rates[i]));
        mvwaddstr(main_sub, 11+i, 2, message);
    }

    reg_domain = get_RegDomain();
    rd_idx = regdom_idx(reg_domain);

    for (i = 0; i < 9; i++) {
	varbinds[i].len_val = 0;
	varbinds[i].type = NULL_VALUE;
    }

    for (i = 0; i < 6; i++) {
	varbinds[i].oid = oid_dot11SupportedAntenna[i];
	varbinds[i].len_oid = sizeof(oid_dot11SupportedAntenna[i]);
    }
    varbinds[6].oid = sysTrapSwitch;
    varbinds[6].len_oid = sizeof(sysTrapSwitch);
    varbinds[7].oid = operAccessPointContact;
    varbinds[7].len_oid = sizeof(operAccessPointContact);
    varbinds[8].oid = operAccessPointLocation;
    varbinds[8].len_oid = sizeof(operAccessPointLocation);

    if (snmp(varbinds, 9, GET) < 9) {
	print_helperr(ERR_RET);
	goto exit;
    }

    for (i = 0; i < 6; i++) {
	antenna[i] = *varbinds[i].value;
    }

    traps = *(varbinds[6].value);
    memcpy(ap_contact, varbinds[7].value, varbinds[7].len_val);
    if (varbinds[7].len_val < 32)
	ap_contact[varbinds[7].len_val] = '\0';
    memcpy(ap_location, varbinds[8].value, varbinds[8].len_val);
    if (varbinds[8].len_val < 32)
	ap_location[varbinds[8].len_val] = '\0';

    sprintf(message, "%s%s", LOCATION, ap_location);
    mvwaddstr(main_sub, 7, 0, message);
    sprintf(message, "%s%s", CONTACT, ap_contact);
    mvwaddstr(main_sub, 8, 0, message);
    sprintf(message, "%s%s", TRAPS, (traps == 1) ? ON : OFF);
    mvwaddstr(main_sub, 5, 0, message);

    mvwaddstr(main_sub, 16, 0, _("Antenna Configuration:"));
    sprintf(message, "%s %s %3s, %s %3s",
	    ANTENNA_RX,
	    ANTENNA_RX_LEFT, (antenna[2] == 1) ? ON : OFF,
	    ANTENNA_RX_RIGHT, (antenna[3] == 1) ? ON : OFF);
    mvwaddstr(main_sub, 17, 1, message);
    sprintf(message, "%s %s %3s, %s %3s",
	    ANTENNA_TX,
	    ANTENNA_TX_LEFT, (antenna[0] == 1) ? ON : OFF,
	    ANTENNA_TX_RIGHT, (antenna[1] == 1) ? ON : OFF);
    mvwaddstr(main_sub, 18, 1, message);
    sprintf(message, "%s %s %3s, %s %3s",
	    ANTENNA_DV,
	    ANTENNA_DV_LEFT, (antenna[4] == 1) ? ON : OFF,
	    ANTENNA_DV_RIGHT, (antenna[5] == 1) ? ON : OFF);
    mvwaddstr(main_sub, 19, 1, message);

    print_top(NULL, _("General Options"));
    print_help(_
	       ("UIOPTY - antenna; SCANLEDFR1234 - options; W - write conf; Q - quit to menu"));
    wrefresh(main_sub);


    noecho();
    while (1) {
	c = getch();
	switch (c) {
	case 'i':
	case 'I':
	    i = strlen(ANTENNA_RX) + 1 +
		strlen(ANTENNA_RX_LEFT) + 6 +
		strlen(ANTENNA_RX_RIGHT) + 2;
	    antenna[3] = on_off(17, i);
	    sprintf(message, "%3s", (antenna[3] == 1) ? ON : OFF);
	    print_menusel(17, i, NULL, message);
	    m_antenna[3] = 1;
	    continue;
	case 'u':
	case 'U':
	    i = strlen(ANTENNA_RX) + 1 +
		strlen(ANTENNA_RX_LEFT) + 2;
	    antenna[2] = on_off(17, i);
	    sprintf(message, "%3s", (antenna[2] == 1) ? ON : OFF);
	    print_menusel(17, i, NULL, message);
	    m_antenna[2] = 1;
	    continue;
	case 'p':
	case 'P':
	    i = strlen(ANTENNA_TX) + 1 +
		strlen(ANTENNA_TX_LEFT) + 6 +
		strlen(ANTENNA_TX_RIGHT) + 2;
	    antenna[1] = on_off(18, i);
	    sprintf(message, "%3s", (antenna[1] == 1) ? ON : OFF);
	    print_menusel(18, i, NULL, message);
	    m_antenna[1] = 1;
	    continue;
	case 'o':
	case 'O':
	    i = strlen(ANTENNA_TX) + 1 +
		strlen(ANTENNA_TX_LEFT) + 2;
	    antenna[0] = on_off(18, i);
	    sprintf(message, "%3s", (antenna[0] == 1) ? ON : OFF);
	    print_menusel(18, i, NULL, message);
	    m_antenna[0] = 1;
	    continue;
	case 'T':
	case 't':
	    i = strlen(ANTENNA_DV) + 1 +
		strlen(ANTENNA_DV_LEFT) + 2;
	    antenna[4] = on_off(19, i);
	    sprintf(message, "%3s", (antenna[4] == 1) ? ON : OFF);
	    print_menusel(19, i, NULL, message);
	    m_antenna[4] = 1;
	    continue;
	case 'Y':
	case 'y':
	    i = strlen(ANTENNA_DV) + 1 +
		strlen(ANTENNA_DV_LEFT) + 6 +
		strlen(ANTENNA_DV_RIGHT) + 2;
	    antenna[5] = on_off(19, i);
	    sprintf(message, "%3s", (antenna[5] == 1) ? ON : OFF);
	    print_menusel(19, i, NULL, message);
	    m_antenna[5] = 1;
	    continue;
	case 'S':
	case 's':
	    traps = on_off(5, strlen(TRAPS));
	    clear_main_new(5, 6);
	    print_menusel(5, 0, TRAPS, (traps == 1) ? ON : OFF);
	    m_traps = 1;
	    continue;
	case 'Q':
	case 'q':
	    goto quit;
        case '1':
	case '2':
	case '3':
	case '4':
		i = c - '0';
            switch (menu_choose(10 + i, 15, rates, 3)) {
                case 0:
                    basic_rates[i-1] = __rates[i-1];
                    break;
                case 1:
                    basic_rates[i-1] = 0;
                    break;
                case 2:
                    basic_rates[i-1] = __rates[i-1] + 0x80;
                }
            clear_main_new(10 + i, 11 + i);
            sprintf(message, RATES_RECORD, i, (float) __rates[i-1] / 2);
	    print_menusel(10 + i, 2, message, basic(basic_rates[i-1]));
            m_basic_rates = 1;
            break;
	case 'C':
	case 'c':
	    channel = menu_choose(0, strlen(CHANNEL),
#ifndef NO_REG_DOMAIN
		channels + regdom_types[rd_idx].first_ch - 1,
		regdom_types[rd_idx].chans) + regdom_types[rd_idx].first_ch;
#else
		channels, 14) + 1;
#endif
	    sprintf(message, "%02u (%u MHz)", channel, 2407 + 5 * channel);
	    print_menusel(0, 0, CHANNEL, message);
	    m_channel = 1;
	    continue;
	case 'A':
	case 'a':
	    authi = menu_choose(6, strlen(AUTH), auth, 3);
	    clear_main_new(6, 7);
	    print_menusel(6, 0, AUTH, auth[authi]);
	    m_auth = 1;
	    continue;
	case 'N':
	case 'n':
	    get_value(ap_name, 2, strlen(AP_NAME), 32, ANY_STRING, 0, 0, NULL);
	    m_ap_name = 1;
	    continue;
	case 'L':
	case 'l':
	    get_value(ap_location, 7, strlen(LOCATION), 32, ANY_STRING, 0, 0,
		NULL);
	    m_ap_location = 1;
	    continue;
	case 'K':
	case 'k':
	    get_value(ap_contact, 8, strlen(CONTACT), 32, ANY_STRING, 0, 0,
		NULL);
	    m_ap_contact = 1;
	    continue;
	case 'E':
	case 'e':
	    get_value(domain, 1, strlen(ESSID), 32, ANY_STRING, 0, 0, NULL);
	    m_essid = 1;
	    continue;
	case 'F':
	case 'f':
	    get_value(message, 4, strlen(FRG_TR), 5, INT_STRING, 256, 2346,
		WLAN_HELP);
	    FragmentationThreshold = atoi(message);
	    m_fragment = 1;
	    continue;
	case 'R':
	case 'r':
	    get_value(message, 3, strlen(RTS_TR), 5, INT_STRING, 0, 2347,
		WLAN_HELP);
	    RTSThreshold = atoi(message);
	    m_rts = 1;
	    continue;
	case 'w':
	case 'W':
	    i = 0;
	    if (m_channel) {
		channel_pref[0] = channel;
		varbinds[i].oid = ChannelPref;
		varbinds[i].len_oid = sizeof(ChannelPref);
		varbinds[i].value = channel_pref;
		varbinds[i].len_val = 2;
		varbinds[i].type = STRING_VALUE;
		i++;
		varbinds[i].oid = operChannelID;
		varbinds[i].len_oid = sizeof(operChannelID);
		varbinds[i].value = (char *) &channel;
		varbinds[i].len_val = 1;
		varbinds[i].type = 0x02;
		i++;
	    }
	    if (m_basic_rates) {
		varbinds[i].oid = operBasicRates;
		varbinds[i].len_oid = sizeof(operBasicRates);
		varbinds[i].value = basic_rates;
		varbinds[i].len_val = 4;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }

	    print_help(WAIT_SET);

	    if (snmp(varbinds, i, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }

	    i = 0;
	    if (m_auth) {
		m_auth = (authi == 1) ? 2 : 1;
		m_basic_rates = (authi == 0) ? 2 : 1;
		varbinds[i].oid = OpenSystem;
		varbinds[i].len_oid = sizeof(OpenSystem);
		varbinds[i].value = (char *) &m_auth;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
		varbinds[i].oid = SharedKey;
		varbinds[i].len_oid = sizeof(SharedKey);
		varbinds[i].value = (char *) &m_basic_rates;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }

	    if (snmp(varbinds, i, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }

	    i = 0;
	    if (m_ap_name) {
		c = strlen(ap_name);
		varbinds[i].oid = operAccessPointName;
		varbinds[i].len_oid = sizeof(operAccessPointName);
		varbinds[i].value = ap_name;
		varbinds[i].len_val = c;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }
	    if (m_ap_location) {
		c = strlen(ap_location);
		varbinds[i].oid = operAccessPointLocation;
		varbinds[i].len_oid = sizeof(operAccessPointLocation);
		varbinds[i].value = ap_location;
		varbinds[i].len_val = c;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }

	    if (snmp(varbinds, i, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }

	    i = 0;
	    if (m_ap_contact) {
		c = strlen(ap_contact);
		varbinds[i].oid = operAccessPointContact;
		varbinds[i].len_oid = sizeof(operAccessPointContact);
		varbinds[i].value = ap_contact;
		varbinds[i].len_val = c;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }
	    if (m_fragment) {
		varbinds[i].oid = operFragmentationThreshold;
		varbinds[i].len_oid = sizeof(operFragmentationThreshold);
		FragmentationThreshold = htons(FragmentationThreshold);
		varbinds[i].value = (char *) &FragmentationThreshold;
		varbinds[i].len_val = 2;
		varbinds[i].type = 0x02;
		i++;
	    }
	    if (m_rts) {
		varbinds[i].oid = operRTSThreshold;
		varbinds[i].len_oid = sizeof(operRTSThreshold);
		RTSThreshold = htons(RTSThreshold);
		varbinds[i].value = (char *) &RTSThreshold;
		varbinds[i].len_val = 2;
		varbinds[i].type = 0x02;
		i++;
	    }
	    if (m_traps) {
		varbinds[i].oid = sysTrapSwitch;
		varbinds[i].len_oid = sizeof(sysTrapSwitch);
		varbinds[i].value = &traps;
		varbinds[i].len_val = 1;
		varbinds[i].type = 0x02;
		i++;
	    }

	    if (snmp(varbinds, i, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }

	    c = 0;
	    for (i = 0; i < 4; i++)
		if (m_antenna[i]) {
		    varbinds[c].oid = oid_dot11SupportedAntenna[i];
		    varbinds[c].len_oid =
			sizeof(oid_dot11SupportedAntenna[i]);
		    varbinds[c].value = &antenna[i];
		    varbinds[c].len_val = 1;
		    varbinds[c].type = INT_VALUE;
		    c++;
		}

	    if (snmp(varbinds, c, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }

	    c = 0;
	    for (i = i; i < 6; i++)
		if (m_antenna[i]) {
		    varbinds[c].oid = oid_dot11SupportedAntenna[i];
		    varbinds[c].len_oid =
			sizeof(oid_dot11SupportedAntenna[i]);
		    varbinds[c].value = &antenna[i];
		    varbinds[c].len_val = 1;
		    varbinds[c].type = INT_VALUE;
		    c++;
		}

	    if (snmp(varbinds, c, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }

	    i = 0;
	    if (m_essid) {
		c = strlen(domain);
		varbinds[i].oid = operESSID;
		varbinds[i].len_oid = sizeof(operESSID);
		varbinds[i].value = domain;
		varbinds[i].len_val = c;
		varbinds[i].type = 0x04;
		i++;
	    }

	    if (snmp(varbinds, i, SET) <= 0) {
		print_helperr(ERR_SET);
		goto exit;
	    }

	    wbkgd(main_sub, A_NORMAL);
	    wrefresh(main_sub);
	    print_help(DONE_SET);
	    goto exit;
	default:
	    continue;
	}
    }

  exit:
    getch();
  quit:
    print_top(NULL, NULL);

    free(domain);
    free(ap_name);
    clear_main(0);
}
