/*
 *      stations.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 <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include "ap-utils.h"

#define MAX_LINES LINES-4

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

void atmel_stations()
{
    char StasNum[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x01, 0x00
    };
    char StasMac[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x05, 0x02, 0x00
    };
    char bridgeOperationalMode[] = {
         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
    };
    
    struct AssociatedSTAsInfo {
	unsigned short Num;
	unsigned char MacAddress[6];
	unsigned char Status;
	unsigned char Port;
	unsigned char ParentMacAddress[6];
	unsigned char RSSI;
	unsigned char LinkQuality;
	unsigned char IP[4];
	unsigned char Reserved[2];
    } *mac = NULL, get;

    struct MacListStat *first = NULL, *curr = NULL;
    char message[1024];
    int mac_num, begin, end, total_mac;
    varbind varbinds[1];

    print_top(NULL, ST_TITLE);

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

    if (*(varbinds[0].value) == 3) {
	mvwaddstr(main_sub, 3, 1, _("AP is currently in AP Client Mode => "
	    "no associated STAtions."));
	print_help(ANY_KEY);
	wrefresh(main_sub);
	getch();
	goto exit;
    }

    varbinds[0].oid = StasNum;
    varbinds[0].len_oid = sizeof(StasNum);
    varbinds[0].value = StasNum;
    varbinds[0].type = NULL_VALUE;
    varbinds[0].len_val = 0;
    print_help(WAIT_RET);
    if (snmp(varbinds, 1, GET) <= 0) {
	print_helperr(ERR_RET);
	getch();
	goto exit;
    }

    total_mac = *(varbinds[0].value);
    mac_num = 1;

    sprintf(message, "%s: %d", ST_TITLE, total_mac);
    print_top(NULL, message);
    wattrset(main_sub, COLOR_PAIR(13));
    mvwaddstr(main_sub, 0, 0,
	_("  #     MAC       Parent MAC  RSSI   LQ Sts MACn      IP        "));
    wattrset(main_sub, A_NORMAL);
    noecho();

    while (mac_num <= total_mac) {

	varbinds[0].oid = StasMac;
	varbinds[0].len_oid = sizeof(StasMac);
	varbinds[0].type = INT_VALUE;
	get.Num = swap2(mac_num);
	varbinds[0].value = (char *) &get;
	varbinds[0].len_val = sizeof(get);

	if (snmp(varbinds, 1, SET) <= 0) {
	    print_helperr(ERR_RET);
	    getch();
	    goto exit;
	}

	if (varbinds[0].len_val == 24) {
	    if (mac)
		free(mac);
	    mac =
		(struct AssociatedSTAsInfo *) malloc(varbinds[0].len_val);
	    memcpy(mac, varbinds[0].value, varbinds[0].len_val);
/*	    mac = (struct AssociatedSTAsInfo *) varbinds[0].value;*/
	} else {
	    print_helperr(_("AssociatedSTAsInfo packet error"));
	    goto exit;
	}


	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, mac->MacAddress, 6);
//	memcpy(curr->ParentMacAddress, mac->ParentMacAddress, 6);
	memcpy(&(curr->IP.s_addr), mac->IP, 4);
	curr->quality = 100 - (minimum(mac->LinkQuality, 40)*2.5);
//	curr->rssi = - 96 + mac->RSSI;
//	curr->quality = mac->LinkQuality;
	curr->rssi = mac->RSSI;
	
	curr->Port = mac->Port;
	curr->Status = mac->Status;
	curr->next = NULL;
	mac_num++;
    }
    begin = 1;
    end = (mac_num > MAX_LINES) ? MAX_LINES : mac_num;
    scroll_rows(first, begin, end, 1, 2);
    while (1) {
	print_help(_("Arrows - scroll; S - save to file; Q - quit to menu."));
	switch (getch()) {
	case 'S':
	case 's':
	    save_Stations(first);
	    continue;
	case KEY_RIGHT:
	case KEY_DOWN:
	    if (end < mac_num) {
		begin++;
		end++;
		scroll_rows(first, begin, end, 1, 2);
	    }
	    continue;
	case KEY_UP:
	case KEY_LEFT:
	    if (begin > 1) {
		begin--;
		end--;
		scroll_rows(first, begin, end, 1, 2);
	    }
	    continue;
	case 'Q':
	case 'q':
	    goto exit;
	}
    }

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

