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

#define ETH_STAT _("Ethernet Statistics")
#define W_STAT _("Wireless Statistics")

extern WINDOW *main_sub;
extern short ap_type;
extern int wait_mode, poll_delay;

void EthStat()
{
    struct EthRxStatistics_s *EthRxStat = NULL;
    struct EthTxStatistics_s *EthTxStat = NULL;

    char EthRxStatistics[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x07, 0x01, 0x00
    };
    char EthTxStatistics[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x07, 0x02, 0x00
    };

    char message[1024];
    varbind varbinds[2];
    int i;

    if (ap_type == ATMEL12350) {
	EthRxStatistics[5] = 0xE0;
	EthRxStatistics[6] = 0x3E;
	EthTxStatistics[5] = 0xE0;
	EthTxStatistics[6] = 0x3E;
    }
    
    print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF, ETH_STAT);
    noecho();

    if (wait_mode == WAIT_TIMEOUT)
        print_help(QT_HELP);

    varbinds[0].oid = EthRxStatistics;
    varbinds[0].len_oid = sizeof(EthRxStatistics);
    varbinds[1].oid = EthTxStatistics;
    varbinds[1].len_oid = sizeof(EthTxStatistics);

    while (1) {
//	varbinds[0].value = EthRxStatistics;
	varbinds[0].len_val = 0;
	varbinds[0].type = NULL_VALUE;
//	varbinds[1].value = EthTxStatistics;
	varbinds[1].len_val = 0;
	varbinds[1].type = NULL_VALUE;

	if (wait_mode == WAIT_FOREVER)
	    print_help(WAIT_RET);

	if (snmp(varbinds, 2, GET) < 2) {
	    print_helperr(ERR_RET);
	    getch();
	    goto quit;
	}

	if (wait_mode == WAIT_FOREVER)
	    print_help(QT_HELP);

	if (varbinds[0].len_val == 64) {
	    if (EthRxStat)
		free(EthRxStat);
	    EthRxStat =
		(struct EthRxStatistics_s *) malloc(varbinds[0].
						       len_val);
	    memcpy(EthRxStat, varbinds[0].value, varbinds[0].len_val);
	} else {
	    print_helperr(_("EthRxStat packet error. Press any key."));
	    getch();
	    goto quit;
	}

	if (varbinds[1].len_val == 56) {
	    if (EthTxStat)
		free(EthTxStat);
	    EthTxStat =
		(struct EthTxStatistics_s *) malloc(varbinds[1].
						       len_val);
	    memcpy(EthTxStat, varbinds[1].value, varbinds[1].len_val);
	} else {
	    print_helperr(_("EthTxStat packet error. Press any key."));
	    getch();
	    goto quit;
	}
	mvwaddstr(main_sub, 1, 2, _("Received:"));
	mvwaddstr(main_sub, 1, 30, _("Transmitted:"));
	sprintf(message, "TotalBytes       %10u TotalBytes         %10u",
		swap4(EthRxStat->TotalBytesRx),
		swap4(EthTxStat->TotalBytesTx));
	mvwaddstr(main_sub, 3, 2, message);
	sprintf(message, "TotalPackets     %10u TotalPackets       %10u",
		swap4(EthRxStat->TotalPacketsRx),
		swap4(EthTxStat->TotalPacketsTx));
	mvwaddstr(main_sub, 4, 2, message);
	sprintf(message, "PacketCRCError   %10u PacketCRCError     %10u",
		swap4(EthRxStat->PacketCRCErrorRx),
		swap4(EthTxStat->PacketCRCErrorTx));
	mvwaddstr(main_sub, 5, 2, message);
	sprintf(message, "FalseCarrier     %10u",
		swap4(EthRxStat->FalseCarrierRx));
	mvwaddstr(main_sub, 6, 2, message);

	sprintf(message, "MulticastPacket  %10u MulticastPacket    %10u",
		swap4(EthRxStat->MulticastPacketRx),
		swap4(EthTxStat->MulticastPacketTx));
	mvwaddstr(main_sub, 7, 2, message);
	sprintf(message, "BroadcastPacket  %10u BroadcastPacket    %10u",
		swap4(EthRxStat->BroadcastPacketRx),
		swap4(EthTxStat->BroadcastPacketTx));
	mvwaddstr(main_sub, 8, 2, message);

	sprintf(message, "ControlFrames    %10u UnicastPacket      %10u",
		swap4(EthRxStat->ControlFramesRx),
		swap4(EthTxStat->UnicastPacketTx));
	mvwaddstr(main_sub, 9, 2, message);
	sprintf(message, "PauseFrames      %10u PauseFrames        %10u",
		swap4(EthRxStat->PauseFramesRx),
		swap4(EthTxStat->PauseFramesTx));
	mvwaddstr(main_sub, 10, 2, message);

	sprintf(message, "UnknownOPCode    %10u SingleDeferPacket  %10u",
		swap4(EthRxStat->UnknownOPCodeRx),
		swap4(EthTxStat->SingleDeferPacketTx));
	mvwaddstr(main_sub, 11, 2, message);
	sprintf(message, "AlignmentError   %10u MultiDeferPackets  %10u",
		swap4(EthRxStat->AlignmentRxError),
		swap4(EthTxStat->MultiDeferPacketsTx));
	mvwaddstr(main_sub, 12, 2, message);
	sprintf(message, "LengthOutOfRange %10u",
		swap4(EthRxStat->LengthOutOfRangeRx));
	mvwaddstr(main_sub, 13, 2, message);
	sprintf(message, "CodeError        %10u SingleCollisions   %10u",
		swap4(EthRxStat->CodeErrorRx),
		swap4(EthTxStat->SingleCollisionsTx));
	mvwaddstr(main_sub, 14, 2, message);
	sprintf(message, "TotalFragments   %10u MultiCollisions    %10u",
		swap4(EthRxStat->TotalFragmentsRx),
		swap4(EthTxStat->MultiCollisionsTx));
	mvwaddstr(main_sub, 15, 2, message);
	sprintf(message, "OversizePackets  %10u LateCollisions     %10u",
		swap4(EthRxStat->OversizePacketsRx),
		swap4(EthTxStat->LateCollisionsTx));
	mvwaddstr(main_sub, 16, 2, message);
	sprintf(message, "UndersizePackets %10u ExcessiveCollision %10u",
		swap4(EthRxStat->UndersizePacketsRx),
		swap4(EthTxStat->ExcessiveCollisionTx));
	mvwaddstr(main_sub, 17, 2, message);
	sprintf(message, "TotalJabber      %10u TotalCollisions    %10u",
		swap4(EthRxStat->TotalJabberRx),
		swap4(EthTxStat->TotalCollisionsTx));
	mvwaddstr(main_sub, 18, 2, message);
	wrefresh(main_sub);

	i = wait_key(poll_delay);
	if (i == -1)
	    goto quit;

	switch((char) i) {
	    case 'q':
	    case 'Q':
		goto quit;
	    case 't':
	    case 'T':
		wait_mode = (wait_mode == WAIT_FOREVER ?
		    WAIT_TIMEOUT : WAIT_FOREVER);
		print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF,
		    ETH_STAT);
	}

	/* either timeout for user input (i == 0) or invalid key => continue */
    }

  quit:
    if (EthRxStat)
	free(EthRxStat);
    if (EthTxStat)
	free(EthTxStat);

    wclear(main_sub);
    print_top(NULL, NULL);
    clear_main(0);
    return;
}

void WirelessStat()
{
    struct wirelessStatistics_s *WirelessStat = NULL;

    char wirelessStatistics[] = {
	0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x03, 0x01, 0x00
    };

    char message[80];
    int i;
    varbind varbinds[1];

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

    print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF, W_STAT);
    noecho();

    if (wait_mode == WAIT_TIMEOUT)
	print_help(QT_HELP);

    varbinds[0].oid = wirelessStatistics;
    varbinds[0].len_oid = sizeof(wirelessStatistics);

    while (1) {
	varbinds[0].value = wirelessStatistics;
	varbinds[0].len_val = 0;
	varbinds[0].type = NULL_VALUE;

	if (wait_mode == WAIT_FOREVER)
	    print_help(WAIT_RET);

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

	if (wait_mode == WAIT_FOREVER)
	    print_help(QT_HELP);

	if (varbinds[0].len_val == 88 || varbinds[0].len_val == 104) {
	    /*
	     * 88 ... using traditional ATMEL 12350 MIB
	     * 104 .. using functionally enhanced ATMEL 12350 MIB by EZYNET
	     */
	    if (WirelessStat)
		free(WirelessStat);
	    WirelessStat =
		(struct wirelessStatistics_s *) malloc(varbinds[0].len_val);
	    memcpy(WirelessStat, varbinds[0].value, varbinds[0].len_val);
	} else {
	    print_helperr
		(_("WirelessStat packet error. Press any key."));
	    getch();
	    goto quit;
	}

	sprintf(message,
		"UnicastPacketsTx   %10u UnicastPacketsRx   %10u",
		swap4(WirelessStat->UnicastTransmittedPackets),
		swap4(WirelessStat->UnicastReceivedPackets));
	mvwaddstr(main_sub, 1, 1, message);
	sprintf(message,
		"BroadcastPacketsTx %10u BroadcastPacketsRx %10u",
		swap4(WirelessStat->BroadcastTransmittedPackets),
		swap4(WirelessStat->BroadcastReceivedPackets));
	mvwaddstr(main_sub, 2, 1, message);
	sprintf(message,
		"MulticastPacketsTx %10u MulticastPacketsRx %10u",
		swap4(WirelessStat->MulticastTransmittedPackets),
		swap4(WirelessStat->MulticastReceivedPackets));
	mvwaddstr(main_sub, 3, 1, message);
	sprintf(message,
		"BeaconTx           %10u BeaconRx           %10u",
		swap4(WirelessStat->TransmittedBeacon),
		swap4(WirelessStat->ReceivedBeacon));
	mvwaddstr(main_sub, 4, 1, message);
	sprintf(message,
		"ACKTx              %10u ACKRx              %10u",
		swap4(WirelessStat->TransmittedACK),
		swap4(WirelessStat->ReceivedACK));
	mvwaddstr(main_sub, 5, 1, message);
	sprintf(message,
		"RTSTx              %10u RTSRx              %10u",
		swap4(WirelessStat->TransmittedRTS),
		swap4(WirelessStat->ReceivedRTS));
	mvwaddstr(main_sub, 6, 1, message);
	sprintf(message,
		"CTSTx              %10u CTSRx              %10u",
		swap4(WirelessStat->TransmittedCTS),
		swap4(WirelessStat->ReceivedCTS));
	mvwaddstr(main_sub, 7, 1, message);
	sprintf(message, "ACKFailure         %10u",
		swap4(WirelessStat->ACKFailure));
	mvwaddstr(main_sub, 8, 1, message);
	sprintf(message, "CTSFailure         %10u",
		swap4(WirelessStat->CTSFailure));
	mvwaddstr(main_sub, 9, 1, message);
	sprintf(message, "RetryPackets       %10u",
		swap4(WirelessStat->RetryPackets));
	mvwaddstr(main_sub, 10, 1, message);
	sprintf(message, "ReceivedDuplicate  %10u",
		swap4(WirelessStat->ReceivedDuplicate));
	mvwaddstr(main_sub, 11, 1, message);
	sprintf(message, "FailedPackets      %10u",
		swap4(WirelessStat->FailedPackets));
	mvwaddstr(main_sub, 12, 1, message);
	sprintf(message, "AgedPackets        %10u",
		swap4(WirelessStat->AgedPackets));
	mvwaddstr(main_sub, 13, 1, message);
	sprintf(message, "FCSError           %10u",
		swap4(WirelessStat->FCSError));
	mvwaddstr(main_sub, 14, 1, message);
	sprintf(message, "InvalidPLCP        %10u",
		swap4(WirelessStat->InvalidPLCP));
	mvwaddstr(main_sub, 15, 1, message);

	/* ATMEL12350 MIB EZYNET modification has in addition the following */
	if (varbinds[0].len_val == 104) {
	    mvwaddstr(main_sub, 16, 1, "TransmittedPackets:");
	    sprintf(message, "* at 11 Mbps       %10u",
		swap4(WirelessStat->TransmittedPackets_11Mbps));
	    mvwaddstr(main_sub, 17, 1, message);
	    sprintf(message, "* at 5.5 Mbps      %10u",
		swap4(WirelessStat->TransmittedPackets_55Mbps));
	    mvwaddstr(main_sub, 18, 1, message);
	    sprintf(message, "* at 2 Mbps        %10u",
		swap4(WirelessStat->TransmittedPackets_2Mbps));
	    mvwaddstr(main_sub, 19, 1, message);
	    sprintf(message, "* at 1 Mbps        %10u",
		swap4(WirelessStat->TransmittedPackets_1Mbps));
	    mvwaddstr(main_sub, 20, 1, message);
	}
	wrefresh(main_sub);

	i = wait_key(poll_delay);
	if (i == -1)
	    goto quit;

	switch((char) i) {
	    case 'q':
	    case 'Q':
		goto quit;
	    case 't':
	    case 'T':
		wait_mode = (wait_mode == WAIT_FOREVER ?
		    WAIT_TIMEOUT : WAIT_FOREVER);
		print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF,
		    W_STAT);
	}

	/* either timeout for user input (i == 0) or invalid key => continue */
    }

  quit:
    if (WirelessStat)
	free(WirelessStat);
    wclear(main_sub);
    print_top(NULL, NULL);
    clear_main(0);
}


void nwn_wireless_stat()
{
    char oid_dot11TransmittedFragmentCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x01, 0x01 };
    char oid_dot11MulticastTransmittedFrameCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x02, 0x01 };
    char oid_dot11FailedCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x03, 0x01 };
    char oid_dot11RetryCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x04, 0x01 };
    char oid_dot11MultipleRetryCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x05, 0x01 };
    char oid_dot11FrameDuplicateCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x06, 0x01 };
    char oid_dot11RTSSuccessCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x07, 0x01 };
    char oid_dot11RTSFailureCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x08, 0x01 };
    char oid_dot11ACKFailureCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x09, 0x01 };
    char oid_dot11ReceivedFragmentCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0a, 0x01 };
    char oid_dot11MulticastReceivedFrameCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0b, 0x01 };
    char oid_dot11FCSErrorCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0c, 0x01 };
    char oid_dot11TransmittedFrameCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0d, 0x01 };
    char oid_dot11WEPUndecryptableCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x02, 0x02, 0x01, 0x0e, 0x01 };
    char oid_dot11WEPICVErrorCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x05, 0x01, 0x05, 0x01 };
    char oid_dot11WEPExcludedCount[] =
	{ 0x2a, 0x86, 0x48, 0xce, 0x34, 0x01, 0x05, 0x01, 0x06, 0x01 };

    char message[80];
    int i;

    varbind varbinds[16];
    curs_set(0);

    print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF, W_STAT);
    noecho();

    if (wait_mode == WAIT_TIMEOUT)
	print_help(QT_HELP);

    varbinds[0].oid = oid_dot11TransmittedFragmentCount;
    varbinds[0].len_oid = sizeof(oid_dot11TransmittedFragmentCount);
    varbinds[1].oid = oid_dot11MulticastTransmittedFrameCount;
    varbinds[1].len_oid = sizeof(oid_dot11MulticastTransmittedFrameCount);
    varbinds[2].oid = oid_dot11FailedCount;
    varbinds[2].len_oid = sizeof(oid_dot11FailedCount);
    varbinds[3].oid = oid_dot11RetryCount;
    varbinds[3].len_oid = sizeof(oid_dot11RetryCount);
    varbinds[4].oid = oid_dot11MultipleRetryCount;
    varbinds[4].len_oid = sizeof(oid_dot11MultipleRetryCount);
    varbinds[5].oid = oid_dot11FrameDuplicateCount;
    varbinds[5].len_oid = sizeof(oid_dot11FrameDuplicateCount);
    varbinds[6].oid = oid_dot11RTSSuccessCount;
    varbinds[6].len_oid = sizeof(oid_dot11RTSSuccessCount);
    varbinds[7].oid = oid_dot11RTSFailureCount;
    varbinds[7].len_oid = sizeof(oid_dot11RTSFailureCount);
    varbinds[8].oid = oid_dot11ACKFailureCount;
    varbinds[8].len_oid = sizeof(oid_dot11ACKFailureCount);
    varbinds[9].oid = oid_dot11ReceivedFragmentCount;
    varbinds[9].len_oid = sizeof(oid_dot11ReceivedFragmentCount);
    varbinds[10].oid = oid_dot11MulticastReceivedFrameCount;
    varbinds[10].len_oid = sizeof(oid_dot11MulticastReceivedFrameCount);
    varbinds[11].oid = oid_dot11FCSErrorCount;
    varbinds[11].len_oid = sizeof(oid_dot11FCSErrorCount);
    varbinds[12].oid = oid_dot11TransmittedFrameCount;
    varbinds[12].len_oid = sizeof(oid_dot11TransmittedFrameCount);
    varbinds[13].oid = oid_dot11WEPUndecryptableCount;
    varbinds[13].len_oid = sizeof(oid_dot11WEPUndecryptableCount);
    varbinds[14].oid = oid_dot11WEPICVErrorCount;
    varbinds[14].len_oid = sizeof(oid_dot11WEPICVErrorCount);
    varbinds[15].oid = oid_dot11WEPExcludedCount;
    varbinds[15].len_oid = sizeof(oid_dot11WEPExcludedCount);

    while (1) {
	for (i = 0; i < 16; i++) {
	    varbinds[i].value = oid_dot11TransmittedFragmentCount;
	    varbinds[i].len_val = 0;
	    varbinds[i].type = 0x05;
	}

	if (wait_mode == WAIT_FOREVER)
	    print_help(WAIT_RET);

	if (snmp(varbinds, 16, GET) < 16) {
	    print_helperr(ERR_RET);
	    getch();
	    goto quit;
	}

	if (wait_mode == WAIT_FOREVER)
	    print_help(QT_HELP);

	sprintf(message, "FragmentTx       %10lu FragmentRx       %10lu",
		(long) swap4(*varbinds[0].value), (long) swap4(*varbinds[9].value));
	mvwaddstr(main_sub, 1, 1, message);
	sprintf(message, "TransmittedFrame %10lu",
		(long) swap4(*varbinds[12].value));
	mvwaddstr(main_sub, 2, 1, message);
	sprintf(message, "MulticasFrameTx  %10lu MulticastFrameRx %10lu",
		(long) swap4(*varbinds[1].value), (long) swap4(*varbinds[10].value));
	mvwaddstr(main_sub, 3, 1, message);
	sprintf(message, "WEPUndecryptable %10lu WEPExcluded      %10lu",
		(long) swap4(*varbinds[13].value), (long) swap4(*varbinds[15].value));
	mvwaddstr(main_sub, 4, 1, message);
	sprintf(message, "RTSSuccess       %10lu RTSFailure       %10lu",
		(long) swap4(*varbinds[6].value), (long) swap4(*varbinds[7].value));
	mvwaddstr(main_sub, 5, 1, message);
	sprintf(message, "ACKFailure       %10lu",
		(long) swap4(*varbinds[8].value));
	mvwaddstr(main_sub, 6, 1, message);
	sprintf(message, "Retry            %10lu MultipleRetry    %10lu",
		(long) swap4(*varbinds[3].value), (long) swap4(*varbinds[4].value));
	mvwaddstr(main_sub, 7, 1, message);
	sprintf(message, "FrameDuplicate   %10lu",
		(long) swap4(*varbinds[5].value));
	mvwaddstr(main_sub, 8, 1, message);
	sprintf(message, "Failed           %10lu",
		(long) swap4(*varbinds[2].value));
	mvwaddstr(main_sub, 9, 1, message);
	sprintf(message, "FCSError         %10lu WEPICVError      %10lu",
		(long) swap4(*(varbinds[11].value)),
		(long) swap4(*(varbinds[14].value)));
	mvwaddstr(main_sub, 10, 1, message);
	wrefresh(main_sub);

	i = wait_key(poll_delay);
	if (i == -1)
	    goto quit;

	switch((char) i) {
	    case 'q':
	    case 'Q':
		goto quit;
	    case 't':
	    case 'T':
		wait_mode = (wait_mode == WAIT_FOREVER ?
		    WAIT_TIMEOUT : WAIT_FOREVER);
		print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF,
		    W_STAT);
	}

	/* either timeout for user input (i == 0) or invalid key => continue */
    }

  quit:
    wclear(main_sub);
    print_top(NULL, NULL);
    clear_main(0);
}

