/*
 *      auth.c from Access Point SNMP Utils for Linux
 *
 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
 * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
 *
 * 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 <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "ap-utils.h"

#define MAX_LINES LINES-12
#define PACKET_ERROR _("AuthorizedMacTableString packet error")

#define AUTH_TITLE _("APClient authorization credentials")

#define MAC_AUTH _("[A] MAC authorization: ")
#define MAC_ADD  _("Enter MAC: ")
#define MAC_DEL  _("Delete Num: ")
#define MAC_HEADER _(" NUM     MAC address     ")
#define MAC_HELP _("A: auth; N: new; D: del; arrows: scroll; W: write conf; Q: quit")

#define RADIUS_IP _("[I] Radius server IP: ")
#define RADIUS_DEST_PORT _("[P] Radius server port: ")
#define RADIUS_SECRET _("[S] Radius server secret: ")
#define RADIUS_TIME _("[T] Reauthorization time (minutes): ")
#define RADIUS_PORT _("[F] Radius source port: ")
#define RADIUS_HELP _("A: auth; N: new; D: del; IPSTF: set; arrows: scroll; W: write conf; Q: quit")

#define DOT1X_MODE _("[M] 802.1x authorization: ")
#define DOT1X_TIME _("[T] key broadcasting time period (seconds): ")
#define DOT1X_IP _("[I] 802.1x auth. server IP: ")
#define DOT1X_SECRET _("[S] 802.1x auth. server secret: ")
#define DOT1X_HELP _("A: auth; N: new; D: del; MTIS: set; arrows: scroll; W: write conf; Q: quit")

extern WINDOW *main_sub;
extern int LINES;
extern short ap_type, ap_vendorext;

void atmel_auth()
{
    char AuthorizationMacEnable[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x01, 0x00
    };
    char AutorizedMac[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x02, 0x00
    };

    /* These 6 are ATMEL410 MIB with SBRIDGES extensions -specific */
    char AuthRadiusIP[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x03, 0x00
    };
    char AuthRadiusSecret[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x04, 0x00
    };
    char AuthRadiusSecretLength[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x05, 0x00
    };
    char AuthRadiusPort[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x06, 0x00
    };
    char AuthRadiusReauthorizationTime[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x07, 0x00
    };
    char AuthRadiusDestinPort[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x08, 0x00
    };

    /* These 4 are ATMEL12350 MIB with EZYNET extensions -specific */
    /* Note: GEMTEK MIB falsely claims it has these, but it is not true. :( */
    char Dot1xEnable[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x08, 0x01, 0x00
    };
    char BroadcastKeyPeriod[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x08, 0x02, 0x00
    };
    char ServerIP[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x08, 0x03, 0x00
    };
    char ServerSecret[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x08, 0x04, 0x00
    };

    struct AuthorizedMacTableString {
	unsigned int short Action;
	unsigned int short NumOfAllTableAddresses;
	unsigned int short NumOfCurrentAddress;
	unsigned char MacAddress[6];
    } *AuthMac = NULL, get;

    /* for ATMEL* MIBs with NONE extensions */
    char *AuthModes_OO[] = {
	ON,
	OFF
    };
	
    /* for ATMEL410 MIB with SBRIDGES extensions */
    char *AuthModes_IOR[] = {
	_("Internal"),
	OFF,
	_("Radius")
    };

    /* for ATMEL12350 MIBs with GEMTEK or EZYNET extensions */
    char *AuthModes_AOD[] = {
	_("Allow listed MACs only"),
	OFF,
	_("Deny listed MACs only")
    };

    char *Dot1xModes[] = {
	ON,
	OFF,
	_("Mixed environment")
    };

    /* These will be used for both Radius-related and 802.1x-related stuff. */
    struct in_addr ea_ip;
    char ea_secret[33];
    int ea_mode, ea_port, ea_time, ea_dest_port,
	m_ea_mode = 0, m_ea_port = 0, m_ea_ip = 0, m_ea_secret = 0,
	m_ea_time = 0, m_ea_dest_port = 0;

    struct MacListStat *pmac, *first = NULL, *curr = NULL;
    char message[1024], m_authmac = 0;
    int i = 0, total_mac, auth_mode = 0, mac_num = 0, begin, end;
    varbind varbinds[7];


    if (ap_type == ATMEL12350) {
	AuthorizationMacEnable[5] = 0xE0;
	AuthorizationMacEnable[6] = 0x3E;
	AutorizedMac[5] = 0xE0;
	AutorizedMac[6] = 0x3E;
    }

    varbinds[i].oid = AuthorizationMacEnable;
    varbinds[i].len_oid = sizeof(AuthorizationMacEnable);
    varbinds[i].type = NULL_VALUE;
    varbinds[i].len_val = 0;
    i++;

    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES) {
	varbinds[i].oid = AuthRadiusIP;
	varbinds[i].len_oid = sizeof(AuthRadiusIP);
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	i++;

	varbinds[i].oid = AuthRadiusPort;
	varbinds[i].len_oid = sizeof(AuthRadiusPort);
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	i++;

	varbinds[i].oid = AuthRadiusReauthorizationTime;
	varbinds[i].len_oid = sizeof(AuthRadiusReauthorizationTime);
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	i++;

	varbinds[i].oid = AuthRadiusDestinPort;
	varbinds[i].len_oid = sizeof(AuthRadiusDestinPort);
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	i++;
    }

    if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
	varbinds[i].oid = Dot1xEnable;
	varbinds[i].len_oid = sizeof(Dot1xEnable);
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	i++;

	varbinds[i].oid = BroadcastKeyPeriod;
	varbinds[i].len_oid = sizeof(BroadcastKeyPeriod);
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	i++;

	varbinds[i].oid = ServerIP;
	varbinds[i].len_oid = sizeof(ServerIP);
	varbinds[i].type = NULL_VALUE;
	varbinds[i].len_val = 0;
	i++;
    }

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

    auth_mode = *(varbinds[0].value);

    strcpy(ea_secret, _("(not shown)"));

    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES) {
	sprintf(message, "%s%s", MAC_AUTH, AuthModes_IOR[auth_mode - 1]);
	mvwaddstr(main_sub, 0, 0, message);

	if (auth_mode == 3) { /* Radius */
	    memcpy(&ea_ip.s_addr, varbinds[1].value, 4);
	    sprintf(message, "%s%s", RADIUS_IP, inet_ntoa(ea_ip));
	    mvwaddstr(main_sub, 1, 0, message);

	    ea_dest_port = varbinds[4].len_val == 2 ?
		(varbinds[4].value[0] << 8) | varbinds[4].value[1] :
		varbinds[4].value[0] < 0x80 ?
		varbinds[4].value[0] : 0xff00 | varbinds[4].value[0];
	    sprintf(message, "%s%d", RADIUS_DEST_PORT, ea_dest_port);
	    mvwaddstr(main_sub, 2, 0, message);

	    sprintf(message, "%s%s", RADIUS_SECRET, ea_secret);
	    mvwaddstr(main_sub, 3, 0, message);

	    ea_time = varbinds[3].len_val == 2 ?
		(varbinds[3].value[0] << 8) | varbinds[3].value[1] :
		varbinds[3].value[0] < 0x80 ?
		varbinds[3].value[0] : 0xff00 | varbinds[3].value[0];
	    sprintf(message, "%s%d", RADIUS_TIME, ea_time);
	    mvwaddstr(main_sub, 4, 0, message);

	    ea_port = varbinds[2].len_val == 2 ?
		(varbinds[2].value[0] << 8) | varbinds[2].value[1] :
		varbinds[2].value[0] < 0x80 ?
		varbinds[2].value[0] : 0xff00 | varbinds[2].value[0];
	    sprintf(message, "%s%d", RADIUS_PORT, ea_port);
	    mvwaddstr(main_sub, 5, 0, message);
	}
    } else if (ap_type == ATMEL12350 &&
	(ap_vendorext == GEMTEK || ap_vendorext == EZYNET)) {
	sprintf(message, "%s%s", MAC_AUTH, AuthModes_AOD[auth_mode - 1]);
	mvwaddstr(main_sub, 0, 0, message);

	if (ap_vendorext == EZYNET) {
	    ea_mode = *(varbinds[1].value);
	    sprintf(message, "%s%s", DOT1X_MODE, Dot1xModes[ea_mode - 1]);
	    mvwaddstr(main_sub, 1, 0, message);

	    ea_time = varbinds[2].len_val == 2 ?
		(varbinds[2].value[0] << 8) | varbinds[2].value[1] :
		varbinds[2].value[0] < 0x80 ?
		varbinds[2].value[0] : 0xff00 | varbinds[2].value[0];
	    sprintf(message, "%s%d", DOT1X_TIME, ea_time);
	    mvwaddstr(main_sub, 2, 0, message);

	    memcpy(&ea_ip.s_addr, varbinds[3].value, 4);
	    sprintf(message, "%s%s", DOT1X_IP, inet_ntoa(ea_ip));
	    mvwaddstr(main_sub, 3, 0, message);

	    sprintf(message, "%s%s", DOT1X_SECRET, ea_secret);
	    mvwaddstr(main_sub, 4, 0, message);
	}
    } else {
	sprintf(message, "%s%s", MAC_AUTH, AuthModes_OO[auth_mode - 1]);
	mvwaddstr(main_sub, 0, 0, message);
    }
    mvwaddstr(main_sub, 7, 0, _("Authorized MAC addresses:"));
    wattrset(main_sub, COLOR_PAIR(13));
    mvwaddstr(main_sub, 8, 0, MAC_HEADER);
    wattrset(main_sub, A_NORMAL);
    wrefresh(main_sub);

    print_help("Trying to retrieve auth. MAC address list from AP. Please wait.");

    total_mac = 0;
    mac_num = 0;

    while (mac_num <= total_mac) {
	get.Action = 0x02; rshort(get.Action);
	get.NumOfAllTableAddresses = total_mac;	rshort(get.NumOfAllTableAddresses);
	get.NumOfCurrentAddress = mac_num; rshort(get.NumOfCurrentAddress);

	varbinds[0].oid = AutorizedMac;
	varbinds[0].len_oid = sizeof(AutorizedMac);
	varbinds[0].value = (char *) &get;
	varbinds[0].len_val = 12;
	varbinds[0].type = STRING_VALUE;

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

	if (varbinds[0].len_val == 12) {
	    if (AuthMac)
		free(AuthMac);
	    AuthMac =
		(struct AuthorizedMacTableString *) malloc(varbinds[0].
							   len_val);
	    memcpy(AuthMac, varbinds[0].value, varbinds[0].len_val);
/*	    AuthMac =
		(struct AuthorizedMacTableString *) varbinds[0].value;*/
	} else {
	    print_helperr(PACKET_ERROR);
	    goto exit;
	}

	rshort(AuthMac->NumOfAllTableAddresses);
	total_mac =
	    (AuthMac->NumOfAllTableAddresses ==
	     65535) ? 0 : AuthMac->NumOfAllTableAddresses;

	if (mac_num) {
	    if (first == NULL) {
		first = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = first;
	    } else {
		curr->next = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = curr->next;
	    }
	    memcpy(curr->addr, AuthMac->MacAddress, 6);
	    curr->next = NULL;
	}
	mac_num++;
    }

    begin = (mac_num > MAX_LINES) ? mac_num + 1 - (MAX_LINES) : 1;
    end = mac_num;

    if (i < 0) {
	mvwaddstr(main_sub, 9, 0, _("(insufficient community used)"));
	wrefresh(main_sub);
    } else {
	scroll_rows(first, begin, end, 9, 0);
    }

    noecho();

    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES)
	print_help(RADIUS_HELP);
    else if (ap_type == ATMEL12350 && ap_vendorext == EZYNET)
	print_help(DOT1X_HELP);
    else
	print_help(MAC_HELP);

    while (1) {
	switch (getch()) {
	case 'q':
	case 'Q':
	    goto quit;
	case 'a':
	case 'A':
	    auth_mode = menu_choose(0, strlen(MAC_AUTH),
		ap_type == ATMEL410 && ap_vendorext == SBRIDGES ?
		    AuthModes_IOR :
		ap_type == ATMEL12350 &&
		    (ap_vendorext == GEMTEK || ap_vendorext == EZYNET) ?
		    AuthModes_AOD :
		    AuthModes_OO,
		ap_vendorext == NONE ?
		    2 : 3
	    );
	    clear_main_new(0, 1);
	    print_menusel(0, 0, MAC_AUTH,
		ap_type == ATMEL410 && ap_vendorext == SBRIDGES ?
		    AuthModes_IOR[auth_mode] :
		ap_type == ATMEL12350 &&
		    (ap_vendorext == GEMTEK || ap_vendorext == EZYNET) ?
		    AuthModes_AOD[auth_mode] :
		    AuthModes_OO[auth_mode]
	    );
	    auth_mode++;
/*
	    auth_mode = on_off(0, strlen(MAC_AUTH));
	    clear_main_new(0, 1);
	    print_menusel(0, 0, MAC_AUTH, (auth_mode == 1) ? ON : OFF);
*/
	    m_authmac = 1;
	    continue;
	case 'd':
	case 'D':
	    /* no MACs available for deletion */
	    if (mac_num == 1)
		continue;

	    mvwaddstr(main_sub, 6, 0, MAC_DEL);
	    get_value(message, 6, strlen(MAC_DEL), 5, INT_STRING,
		0, mac_num - 1, NULL);
	    i = atoi(message);
	    if (i == 0) {
		clear_main_new(6, 7);
		continue;
	    }
	    curr = first;
	    if (i == 1) {
		if (curr->next) {
		    pmac = curr->next;
		    free(first);
		    first = pmac;
		}
	    } else {
		int j = i;

		while (--j > 1)
		    curr = curr->next;
		pmac = curr->next;
		curr->next = pmac->next;
		free(pmac);
	    }

	    mac_num--;

	    /* Rather do not ask how this works. */
	    if (i < begin) {
		begin--;
		end--;
	    } else if (i > (end - 1)) {
		/* Nothing to do! */
	    } else { /* begin <= i <= (end - 1) */
		if ((begin == 1) && ((end - 1) == mac_num)) {
		    end--;
		} else if ((begin > 1) && ((end - 1) < mac_num)) {
		    /* Uncomment for top side scrolling first. */
/*
		    begin--;
		    end--;
*/
		} else if (begin > 1) {
		    begin--;
		    end--;
		}
	    }
#if 0 /* DEBUG */
	    sprintf(message, "MAX_LINES: %i mac_num: %i begin: %i end: %i",
		MAX_LINES, mac_num, begin, end);
	    clear_main(0);
	    mvwaddstr(main_sub, 0, 0, message);
	    wrefresh(main_sub);
	    exit(0);
#endif /* DEBUG */
	    scroll_rows(first, begin, end, 9, 0);
	    clear_main_new(6, 7);
	    continue;
	case 'n':
	case 'N':
	    if (mac_num == 1) {
		free(first);
		first = NULL;
	    }
again:
	    mvwaddstr(main_sub, 6, 0, MAC_ADD);
	    get_mac(message, 6, strlen(MAC_ADD));

	    curr = first;
	    i = 1;
	    while (curr) {
		if (memcmp(curr->addr, message, 6) == 0) {
		    sprintf(message, _("Given MAC already exists in MAC list "
			"at position %d. Press any key."), i);
		    print_helperr(message);
		    getch();
		    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES)
			print_help(RADIUS_HELP);
		    else if (ap_type == ATMEL12350 && ap_vendorext == EZYNET)
			print_help(DOT1X_HELP);
		    else
			print_help(MAC_HELP);
		    goto again;
		}
		curr = curr->next;
		i++;
	    }

	    curr = first;
	    while (curr && curr->next)
		curr = curr->next;
	    if (first == NULL) {
		first = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = first;
	    } else {
		curr->next = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = curr->next;
	    }
	    curr->next = NULL;
	    memcpy(curr->addr, message, 6);
	    mac_num++;
/*	    get_value(message, 1, strlen(MAC_ADD), 13, ANY_STRING, 0, 0,
		NULL);

	    for (i = 0; i < 6; i++) {
		mess[0] = message[2 * i];
		mess[1] = message[2 * i + 1];
		mess[2] = '\0';
		curr->addr[i] = strtol(mess, NULL, 16);
	    }
	    clear_main_new(1, 2);
*/
	    begin = (mac_num > MAX_LINES) ? mac_num + 1 - (MAX_LINES) : 1;
	    end = mac_num;
	    scroll_rows(first, begin, end, 9, 0);
	    clear_main_new(6, 7);
	    continue;
	case 'f':
	case 'F':
	    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES && auth_mode == 3) {
		get_value(message, 5, strlen(RADIUS_PORT), 6,
		    INT_STRING, 0, 65535, RADIUS_HELP);
		ea_port = atoi(message);
		m_ea_port = 1;
	    };
	    continue;
	case 'i':
	case 'I':
	    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES && auth_mode == 3) {
		get_ip(&ea_ip, 1, strlen(RADIUS_IP), RADIUS_HELP);
		m_ea_ip = 1;
	    }
	    if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
		get_ip(&ea_ip, 3, strlen(DOT1X_IP), DOT1X_HELP);
		m_ea_ip = 1;
	    }
	    continue;
	case 'm':
	case 'M':
	    if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
		ea_mode = menu_choose(1, strlen(DOT1X_MODE), Dot1xModes, 3);
		clear_main_new(1, 2);
		print_menusel(1, 0, DOT1X_MODE, Dot1xModes[ea_mode]);
		ea_mode++;
 		m_ea_mode = 1;
	    }
	    continue;
	case 'p':
	case 'P':
	    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES && auth_mode == 3) {
		get_value(message, 2, strlen(RADIUS_DEST_PORT), 6,
		    INT_STRING, 0, 65535, RADIUS_HELP);
		ea_dest_port = atoi(message);
		m_ea_dest_port = 1;
	    }
	    continue;
	case 's':
	case 'S':
	    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES && auth_mode == 3) {
		get_value(ea_secret, 3, strlen(RADIUS_SECRET), -33,
		    ANY_STRING, 0, 0, NULL);
		m_ea_secret = 1;
	    }
	    if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
		get_value(ea_secret, 4, strlen(DOT1X_SECRET), -17,
		    ANY_STRING, 0, 0, NULL);
		m_ea_secret = 1;
	    }
	    continue;
	case 't':
	case 'T':
	    if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES && auth_mode == 3) {
		get_value(message, 4, strlen(RADIUS_TIME), 6,
		    INT_STRING, 0, 65535, RADIUS_HELP);
		ea_time = atoi(message);
		m_ea_time = 1;
	    }
	    if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
		get_value(message, 2, strlen(DOT1X_TIME), 6,
		    INT_STRING, 0, 65535, RADIUS_HELP);
		ea_time = atoi(message);
		m_ea_time = 1;
	    }
	    continue;
	case 'w':
	case 'W':
	    curr = first;
	    i = (mac_num == 1 ? 0 : 1);
	    while (curr != NULL) {
		get.Action = 0x01; rshort(get.Action);
		get.NumOfAllTableAddresses = mac_num - 1; rshort(get.NumOfAllTableAddresses);
		get.NumOfCurrentAddress = i; rshort(get.NumOfCurrentAddress);
		memcpy(get.MacAddress, curr->addr, 6);
		varbinds[0].oid = AutorizedMac;
		varbinds[0].len_oid = sizeof(AutorizedMac);
		varbinds[0].value = (char *) &get;
		varbinds[0].len_val = 12;
		varbinds[0].type = STRING_VALUE;
		print_help(WAIT_SET);
		if (snmp(varbinds, 1, SET) <= 0) {
		    print_helperr(ERR_SET);
		    goto exit;
		}
		if (varbinds[0].len_val != 12) {
		    print_helperr(PACKET_ERROR);
		    goto exit;
		}
		curr = curr->next;
		i++;
	    }

	    i = 0;

	    if (m_authmac) {
		int c = swap4(auth_mode);

		varbinds[i].oid = AuthorizationMacEnable;
		varbinds[i].len_oid = sizeof(AuthorizationMacEnable);
		varbinds[i].value = (char *) &c;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }

	    if (m_ea_port) {
		varbinds[i].oid = AuthRadiusPort;
		varbinds[i].len_oid = sizeof(AuthRadiusPort);
		ea_port = htons(ea_port);
		varbinds[i].value = (char *) &ea_port;
		varbinds[i].len_val = 2;
		varbinds[i].type = INT_VALUE;
		i++;
	    }

	    if (m_ea_ip) {
		if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES) {
		    varbinds[i].oid = AuthRadiusIP;
		    varbinds[i].len_oid = sizeof(AuthRadiusIP);
		}

		if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
		    varbinds[i].oid = ServerIP;
		    varbinds[i].len_oid = sizeof(ServerIP);
		}

		ea_ip.s_addr = htonl(ea_ip.s_addr);
		ea_ip.s_addr = swap4(ea_ip.s_addr);
		varbinds[i].value = (char *) &ea_ip.s_addr;
		varbinds[i].len_val = 4;
		varbinds[i].type = INT_VALUE;
		i++;
	    }

	    if (m_ea_mode) {
		varbinds[i].oid = Dot1xEnable;
		varbinds[i].len_oid = sizeof(Dot1xEnable);
		ea_mode = swap4(ea_mode);
		varbinds[i].value = (char *) &ea_mode;
		varbinds[i].len_val = 1;
		varbinds[i].type = INT_VALUE;
		i++;
	    }

	    if (m_ea_dest_port) {
		varbinds[i].oid = AuthRadiusDestinPort;
		varbinds[i].len_oid = sizeof(AuthRadiusDestinPort);
		ea_dest_port = htons(ea_dest_port);
		varbinds[i].value = (char *) &ea_dest_port;
		varbinds[i].len_val = 2;
		varbinds[i].type = INT_VALUE;
		i++;
	    }

	    if (m_ea_secret) {
		int c = strlen(ea_secret);

		if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES) {
		    varbinds[i].oid = AuthRadiusSecretLength;
		    varbinds[i].len_oid = sizeof(AuthRadiusSecretLength);
		    varbinds[i].value = (char *) &c;
		    varbinds[i].len_val = 1;
		    varbinds[i].type = INT_VALUE;
		    i++;

		    varbinds[i].oid = AuthRadiusSecret;
		    varbinds[i].len_oid = sizeof(AuthRadiusSecret);
		}

		if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
		    varbinds[i].oid = ServerSecret;
		    varbinds[i].len_oid = sizeof(ServerSecret);
		}

		varbinds[i].value = ea_secret;
		varbinds[i].len_val = c;
		varbinds[i].type = STRING_VALUE;
		i++;
	    }

	    if (m_ea_time) {
		if (ap_type == ATMEL410 && ap_vendorext == SBRIDGES) {
		    varbinds[i].oid = AuthRadiusReauthorizationTime;
		    varbinds[i].len_oid = sizeof(AuthRadiusReauthorizationTime);
		}

		if (ap_type == ATMEL12350 && ap_vendorext == EZYNET) {
		    varbinds[i].oid = BroadcastKeyPeriod;
		    varbinds[i].len_oid = sizeof(BroadcastKeyPeriod);
		}

		ea_time = htons(ea_time);
		varbinds[i].value = (char *) &ea_time;
		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);
	    wattrset(main_sub, COLOR_PAIR(13));
	    mvwaddstr(main_sub, 8, 0, MAC_HEADER);
	    wattrset(main_sub, A_NORMAL);
	    wrefresh(main_sub);
	    print_help(DONE_SET);
	    goto exit;
	case KEY_DOWN:
	case KEY_RIGHT:
	    if (end < mac_num) {
		begin++;
		end++;
		scroll_rows(first, begin, end, 9, 0);
	    }
	    continue;
	case KEY_UP:
	case KEY_LEFT:
	    if (begin > 1) {
		begin--;
		end--;
		scroll_rows(first, begin, end, 9, 0);
	    }
	    continue;
	case KEY_NPAGE:
	    if (end < mac_num) {
		end = (end + (MAX_LINES) - 1 < mac_num) ?
		    end + (MAX_LINES) - 1 : mac_num;
		begin = (end - (MAX_LINES) + 1 > 0) ?
		    end - (MAX_LINES) + 1 : 1;
		scroll_rows(first, begin, end, 9, 0);
	    }
	    continue;
	case KEY_PPAGE:
	    if (begin > 1) {
		begin = (begin - (MAX_LINES) + 1 > 0) ?
		    begin - (MAX_LINES) + 1 : 1;
		end = (begin + (MAX_LINES) - 1 < mac_num) ?
		    begin + (MAX_LINES) - 1 : mac_num;
		scroll_rows(first, begin, end, 9, 0);
	    }
	    continue;
	case KEY_END:
	    if (end < mac_num) {
		begin = (mac_num > MAX_LINES) ? mac_num + 1 - (MAX_LINES) : 1;
		end = mac_num;
		scroll_rows(first, begin, end, 9, 0);
	    }
	    continue;
	case KEY_HOME:
	    if (begin > 1) {
		begin = 1;
		end = (mac_num > MAX_LINES) ? MAX_LINES : mac_num;
		scroll_rows(first, begin, end, 9, 0);
	    }
	    continue;
	}
	continue;
    }

    print_help(ANY_KEY);
  exit:
    getch();
  quit:
    while ((curr = first)) {
	first = curr->next;
	free(curr);
    }
    if (AuthMac)
	free(AuthMac);
    print_top(NULL, NULL);
    clear_main(0);
}

void nwn_auth_mac()
{
    struct MacListStat *pmac, *first = NULL, *curr = NULL;
    char Mac[] =
	{ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x02,
	0x02, 0x01, 0x02, 0x00
    };
    char MacAllow[] =
	{ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x02,
	0x02, 0x01, 0x03, 0x00
    };
    char MacRowStatus[] =
	{ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x87, 0x29, 0x03, 0x01, 0x03, 0x02,
	0x02, 0x01, 0x04, 0x00
    };
    char message[1024], auth_enable[] =
	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
    char destroy = 6, create = 4, allow = 1;
    int i, auth_mac = 0, mac_num = 0, begin, end;
    varbind varbinds[3];
    print_top(NULL, AUTH_TITLE);

    mvwaddstr(main_sub, 2, 0, MAC_HEADER);
    wrefresh(main_sub);
    print_help(WAIT_RET);

    mac_num = 1;
    varbinds[0].oid = Mac;
    varbinds[0].len_oid = sizeof(Mac);
    varbinds[0].value = Mac;
    varbinds[0].len_val = 0;
    varbinds[0].type = NULL_VALUE;
    if (snmp(varbinds, 1, GET_NEXT) <= 0) {
	print_helperr(ERR_RET);
	goto exit;
    }

    while (memcmp(varbinds[0].oid, Mac, sizeof(Mac) - 1) == 0) {

	Mac[sizeof(Mac) - 1] = varbinds[0].oid[sizeof(Mac) - 1];
	MacAllow[sizeof(MacAllow) - 1] = varbinds[0].oid[sizeof(Mac) - 1];
	MacRowStatus[sizeof(MacRowStatus) - 1] =
	    varbinds[0].oid[sizeof(Mac) - 1];

	varbinds[0].oid = Mac;
	varbinds[0].len_oid = sizeof(Mac);
	varbinds[0].value = Mac;
	varbinds[0].len_val = 0;
	varbinds[0].type = NULL_VALUE;
	varbinds[1].oid = MacAllow;
	varbinds[1].len_oid = sizeof(MacAllow);
	varbinds[1].value = Mac;
	varbinds[1].len_val = 0;
	varbinds[1].type = NULL_VALUE;
	varbinds[2].oid = MacRowStatus;
	varbinds[2].len_oid = sizeof(MacRowStatus);
	varbinds[2].value = Mac;
	varbinds[2].len_val = 0;
	varbinds[2].type = NULL_VALUE;
	if (snmp(varbinds, 3, GET) < 3) {
	    print_helperr(ERR_RET);
	    goto exit;
	}
	if (memcmp(auth_enable, varbinds[0].value, 6)) {
	    if (first == NULL) {
		first = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = first;
	    } else {
		curr->next = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = curr->next;
	    }
	    memcpy(curr->addr, varbinds[0].value, 6);
	    curr->next = NULL;
	    mac_num++;
	} else
	    auth_mac = 1;


	varbinds[0].oid = Mac;
	varbinds[0].len_oid = sizeof(Mac);
	varbinds[0].value = Mac;
	varbinds[0].len_val = 0;
	varbinds[0].type = NULL_VALUE;
	if (snmp(varbinds, 1, GET_NEXT) <= 0) {
	    print_helperr(ERR_RET);
	    goto exit;
	}
    }

    begin = 1;
    end = (mac_num > MAX_LINES) ? MAX_LINES : mac_num;

    sprintf(message, "%s%s", MAC_AUTH, (auth_mac) ? OFF : ON);
    mvwaddstr(main_sub, 0, 0, message);

    scroll_rows(first, begin, end, 3, 0);

    noecho();

    print_help(MAC_HELP);
    while (1) {
	switch (getch()) {
	case 'Q':
	case 'q':
	    goto quit;
	case 'a':
	    auth_mac = on_off(0, strlen(MAC_AUTH)) - 1;
	    clear_main_new(0, 1);
	    print_menusel(0, 0, MAC_AUTH, (auth_mac) ? OFF : ON);
	    continue;
	case 'd':
	    mvwaddstr(main_sub, 1, 0, MAC_DEL);
	    get_value(message, 1, strlen(MAC_DEL), 5, INT_STRING,
		1, mac_num - 1, NULL);
	    i = atoi(message);
	    if (i == 1) {
		pmac = first;
		first = first->next;
		free(pmac);
	    } else {
		curr = first;
		while (--i > 1)
		    curr = curr->next;
		pmac = curr->next;
		curr->next = pmac->next;
		free(pmac);
	    }
	    mac_num--;
	    begin = 1;
	    end = (mac_num > MAX_LINES) ? MAX_LINES : mac_num;
	    scroll_rows(first, begin, end, 3, 0);
	    clear_main_new(1, 2);
	    continue;
	case 'n':
	case 'N':
	    mvwaddstr(main_sub, 1, 0, MAC_ADD);
	    curr = first;
	    while (curr && curr->next)
		curr = curr->next;
	    if (first == NULL) {
		first = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = first;
	    } else {
		curr->next = (struct MacListStat *)
		    malloc(sizeof(struct MacListStat));
		curr = curr->next;
	    }
	    curr->next = NULL;
	    mac_num++;
	    get_mac(curr->addr, 1, strlen(MAC_ADD));
/*
	    for (i = 0; i < 6; i++) {
		get_value(message, 1, 20 + i * 3, 3, ANY_STRING, 0, 0, NULL);
		curr->addr[i] = strtol(message, NULL, 16);
	    }
	    clear_main_new(1, 2);
*/
	    begin = 1;
	    end = (mac_num > MAX_LINES) ? MAX_LINES : mac_num;
	    scroll_rows(first, begin, end, 3, 0);
	    continue;
	case 'w':
	case 'W':
	    print_help(WAIT_SET);

	    Mac[sizeof(Mac) - 1] = 0;

	    varbinds[0].oid = Mac;
	    varbinds[0].len_oid = sizeof(Mac);
	    varbinds[0].value = Mac;
	    varbinds[0].len_val = 0;
	    varbinds[0].type = NULL_VALUE;
	    if (snmp(varbinds, 1, GET_NEXT) <= 0) {
		print_helperr(ERR_RET);
		goto exit;
	    }
	    while (memcmp(varbinds[0].oid, Mac, sizeof(Mac) - 1) == 0) {

		MacRowStatus[sizeof(MacRowStatus) - 1] =
		    varbinds[0].oid[sizeof(Mac) - 1];
		varbinds[0].oid = MacRowStatus;
		varbinds[0].len_oid = sizeof(MacRowStatus);
		varbinds[0].value = &destroy;
		varbinds[0].len_val = 1;
		varbinds[0].type = INT_VALUE;
		if (snmp(varbinds, 1, SET) <= 0) {
		    print_helperr(ERR_SET);
		    goto exit;
		}
		varbinds[0].oid = Mac;
		varbinds[0].len_oid = sizeof(Mac);
		varbinds[0].value = Mac;
		varbinds[0].len_val = 0;
		varbinds[0].type = NULL_VALUE;
		if (snmp(varbinds, 1, GET_NEXT) <= 0) {
		    print_helperr(ERR_RET);
		    goto exit;
		}
	    }


	    curr = first;
	    i = 1;

	    if (auth_mac) {
		Mac[sizeof(Mac) - 1] = i;
		MacAllow[sizeof(MacAllow) - 1] = i;
		MacRowStatus[sizeof(MacRowStatus) - 1] = i;

		varbinds[0].oid = MacRowStatus;
		varbinds[0].len_oid = sizeof(MacRowStatus);
		varbinds[0].value = &create;
		varbinds[0].len_val = 1;
		varbinds[0].type = INT_VALUE;
		varbinds[1].oid = Mac;
		varbinds[1].len_oid = sizeof(Mac);
		varbinds[1].value = auth_enable;
		varbinds[1].len_val = 6;
		varbinds[1].type = STRING_VALUE;
		varbinds[2].oid = MacAllow;
		varbinds[2].len_oid = sizeof(MacAllow);
		varbinds[2].value = &allow;
		varbinds[2].len_val = 1;
		varbinds[2].type = INT_VALUE;
		print_help(WAIT_SET);
		if (snmp(varbinds, 3, SET) <= 0) {
		    print_helperr(ERR_SET);
		    goto exit;
		}
		i++;
	    }




	    while (curr != NULL) {
		Mac[sizeof(Mac) - 1] = i;
		MacAllow[sizeof(MacAllow) - 1] = i;
		MacRowStatus[sizeof(MacRowStatus) - 1] = i;

		varbinds[0].oid = MacRowStatus;
		varbinds[0].len_oid = sizeof(MacRowStatus);
		varbinds[0].value = &create;
		varbinds[0].len_val = 1;
		varbinds[0].type = INT_VALUE;
		varbinds[1].oid = Mac;
		varbinds[1].len_oid = sizeof(Mac);
		varbinds[1].value = curr->addr;
		varbinds[1].len_val = 6;
		varbinds[1].type = STRING_VALUE;
		varbinds[2].oid = MacAllow;
		varbinds[2].len_oid = sizeof(MacAllow);
		varbinds[2].value = &allow;
		varbinds[2].len_val = 1;
		varbinds[2].type = INT_VALUE;
		print_help(WAIT_SET);
		if (snmp(varbinds, 3, SET) <= 0) {
		    print_helperr(ERR_SET);
		    goto exit;
		}
		curr = curr->next;
		i++;
	    }
	    wbkgd(main_sub, A_NORMAL);
	    wrefresh(main_sub);
	    print_help(DONE_SET);
	    goto exit;
	case KEY_DOWN:
	case KEY_RIGHT:
	    if (end < mac_num) {
		begin++;
		end++;
		scroll_rows(first, begin, end, 3, 0);
	    }

	    continue;
	case KEY_UP:
	case KEY_LEFT:
	    if (begin > 1) {
		begin--;
		end--;
		scroll_rows(first, begin, end, 3, 0);
	    }
	    continue;
	}
	continue;
    }

    print_help(ANY_KEY);
  exit:
    getch();
  quit:
    while ((curr = first)) {
	first = curr->next;
	free(curr);
    }
    print_top(NULL, NULL);
    clear_main(0);
}
