]> git.decadent.org.uk Git - ap-utils.git/blobdiff - src/aplink.c
Imported Upstream version 1.5~pre2
[ap-utils.git] / src / aplink.c
diff --git a/src/aplink.c b/src/aplink.c
new file mode 100644 (file)
index 0000000..eb5ed3d
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ *        aplink.c from Access Point SNMP Utils for Linux
+ *
+ * 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 <sys/wait.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include "ap-utils.h"
+
+#define S_RSSI     _("RSSI:     [")
+#define S_RSSI_AVG _("RSSI avg: [")
+#define S_RSSI_TOP _("RSSI top: [")
+
+extern WINDOW *main_sub;
+extern short ap_type, ap_vendorext;
+extern int wait_mode, snmp_retries;
+
+/*
+ * TODO: Implement APClientInfo as alternative, for NetGear ME102 MIB
+ * (ap_type == ATMEL12350 && ap_vendorext == NONE).
+ */
+
+void atmel_aplink()
+{
+    char bridgeOperationalMode[] = {
+       0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
+    };
+    /*
+     * ATMEL12350 EZYNET MIB and ATMEL410 SBRIDGES MIB specific:
+     * for ATMEL410 SBRIDGES MIB: .1.3.6.1.4.1.410.1.2.8.1.0
+     * for ATMEL12350 EZYNET MIB: .1.3.6.1.4.1.12350.1.2.7.4.0
+     */
+    char NetworkSettings[] = {
+       0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x08, 0x01, 0x00
+    };
+
+    /* APClient mode: AP link diagnostics */
+
+    struct NetworkSettings_ATMEL410_SBRIDGES sa_sb_410;
+    struct NetworkSettings_ATMEL12350_EZYNET sa_en_12350;
+
+    /* Used common members of the 2 structures above. */
+    unsigned char BSSID[6];
+    /* unsigned short InfoCapability; */
+    unsigned char Rssi;
+    unsigned char Channel;
+    /* LinkQuality for NetworkSettings_ATMEL410_SBRIDGES */
+    /* CurrentRate for NetworkSettings_ATMEL12350_EZYNET */
+    unsigned char LQCR;
+    unsigned char ESSID[32];
+    unsigned long ESSLEN; /* uchar for NetworkSettings_ATMEL410_SBRIDGES */
+
+    char message[1024];
+    int i, linked = 0, rssi_perc, samples = 0, sum = 0, avg = 0, avg_perc;
+    int top = 0, top_perc;
+    varbind varbinds[1];
+    WINDOW *gauge_rssi, *gauge_rssi_avg, *gauge_rssi_top;
+
+    if (ap_type == ATMEL12350) {
+       bridgeOperationalMode[5] = 0xE0;
+       bridgeOperationalMode[6] = 0x3E;
+
+       NetworkSettings[5] = 0xE0;
+       NetworkSettings[6] = 0x3E;
+       NetworkSettings[9] = 0x07;
+       NetworkSettings[10] = 0x04;
+    }  
+
+    gauge_rssi = derwin(main_sub, 1, 20, 2, strlen(S_RSSI));
+    gauge_rssi_top = derwin(main_sub, 1, 20, 3, strlen(S_RSSI_TOP));
+    gauge_rssi_avg = derwin(main_sub, 1, 20, 4, strlen(S_RSSI_AVG));
+
+    /* find out mode the device is currently in */
+    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);
+         getch();
+         goto exit;
+    }
+
+    /*
+     * Rule out all modes except APClient(3) mode and WRepeater(5) mode on
+     * device running firmware with necessary vendor extensions.
+     */
+    if(!( ((ap_type == ATMEL410 && ap_vendorext == SBRIDGES) ||
+          (ap_type == ATMEL12350 && ap_vendorext == EZYNET)) &&
+         (*(varbinds[0].value) == 3 || *(varbinds[0].value) == 5) )) {
+       mvwaddstr(main_sub, 1, 1,
+           _("Not available - device must have firmware with necessary "));
+       mvwaddstr(main_sub, 2, 1,
+           _("vendor extensions and be in either 'Access Point client'"));
+       mvwaddstr(main_sub, 3, 1,
+           _("or 'Repeater' mode."));
+       print_help(ANY_KEY);
+       wrefresh(main_sub);
+       getch();
+       goto exit;
+    }
+
+    print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF, AP_TITLE);
+    print_help(QT_HELP);
+    noecho();
+
+    while (1) {
+       /* find out how many STAtions is in the list */
+       varbinds[0].oid = NetworkSettings;
+       varbinds[0].len_oid = sizeof(NetworkSettings);
+       varbinds[0].value = NetworkSettings;
+       varbinds[0].type = STRING_VALUE;
+       varbinds[0].len_val = 0;
+
+       if (wait_mode == WAIT_FOREVER)
+           print_help(WAIT_RET);
+
+       snmp_retries = 1;
+       mvwaddstr(main_sub, 0, 0, "Associated with AP: ");
+       if (snmp(varbinds, 1, GET) <= 0) {
+           waddstr(main_sub, NO);
+           if (linked)
+               clear_main(0);
+
+           wrefresh(main_sub);
+           linked = 0;
+           sum = samples = 0;
+       } else {
+           if (wait_mode == WAIT_FOREVER)
+               print_help(QT_HELP);
+
+           waddstr(main_sub, YES);
+
+           if (ap_type == ATMEL410) {
+               memcpy(&sa_sb_410, varbinds[0].value, varbinds[0].len_val);
+
+               memcpy(BSSID, sa_sb_410.BSSID, 6);
+               /* InfoCapability = sa_sb_410.InfoCapability; */
+               Rssi = sa_sb_410.Rssi;
+               Channel = sa_sb_410.Channel;
+               LQCR = sa_sb_410.LinkQuality;
+               memcpy(ESSID, sa_sb_410.ESSID, 32);
+               ESSLEN = sa_sb_410.ESSLEN;
+           } else { /* ap_type == ATMEL12350 */
+               memcpy(&sa_en_12350, varbinds[0].value, varbinds[0].len_val);
+
+               memcpy(BSSID, sa_en_12350.BSSID, 6);
+               /* InfoCapability = sa_en_12350.InfoCapability; */
+               Rssi = sa_en_12350.Rssi;
+               Channel = sa_en_12350.Channel;
+               LQCR = sa_en_12350.CurrentRate;
+               memcpy(ESSID, sa_en_12350.ESSID, 32);
+               ESSLEN = sa_en_12350.ESSLEN;
+           }
+
+           sprintf(message, "Joined BSSID: %02X%02X%02X%02X%02X%02X",
+               BSSID[0] & 0xFF, BSSID[1] & 0xFF, BSSID[2] & 0xFF,
+               BSSID[3] & 0xFF, BSSID[4] & 0xFF, BSSID[5] & 0xFF);
+           mvwaddstr(main_sub, 1, 0, message);
+
+           mvwaddstr(main_sub, 2, 0, S_RSSI);
+           rssi_perc = (int)((minimum (Rssi, 40)) * (float)2.5);
+           werase(gauge_rssi);
+           for (i = 0; i < (20 * rssi_perc / 100); i++) {
+               if (i == 0)
+                   wattrset(gauge_rssi, COLOR_PAIR(COLOR_RED));
+               if (i == 7)
+                   wattrset(gauge_rssi, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
+               if (i == 14)
+                   wattrset(gauge_rssi, COLOR_PAIR(COLOR_GREEN));
+               waddch(gauge_rssi, ACS_BLOCK);
+           }
+           wnoutrefresh(gauge_rssi);
+           sprintf(message, "] [%4ddBm] [%3u%%] [%3u]",
+               -96 + Rssi, rssi_perc, Rssi);
+           mvwaddstr(main_sub, 2, strlen(S_RSSI) + 20, message);
+
+           mvwaddstr(main_sub, 3, 0, S_RSSI_TOP);
+           if (Rssi > top)
+               top = Rssi;
+           top_perc = (int)((minimum (top, 40)) * (float)2.5);
+           werase(gauge_rssi_top);
+           for (i = 0; i < (20 * top_perc / 100); i++) {
+               if (i == 0)
+                   wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_RED));
+               if (i == 7)
+                   wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
+               if (i == 14)
+                   wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_GREEN));
+               waddch(gauge_rssi_top, ACS_BLOCK);
+           }
+           wnoutrefresh(gauge_rssi_top);
+           sprintf(message, "] [%4ddBm] [%3u%%] [%3u]",
+               -96 + top, top_perc, top);
+           mvwaddstr(main_sub, 3, strlen(S_RSSI_TOP) + 20, message);
+
+           mvwaddstr(main_sub, 4, 0, S_RSSI_AVG);
+           sum += Rssi;
+           avg = sum / ++samples;
+           if (samples == 100000) {
+               samples = 1;
+               sum = Rssi;
+           }
+           avg_perc = (int)((minimum (avg, 40)) * (float)2.5);
+           werase(gauge_rssi_avg);
+           for (i = 0; i < (20 * avg_perc / 100); i++) {
+               if (i == 0)
+                   wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_RED));
+               if (i == 7)
+                   wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
+               if (i == 14)
+                   wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_GREEN));
+               waddch(gauge_rssi_avg, ACS_BLOCK);
+           }
+           wnoutrefresh(gauge_rssi_avg);
+           sprintf(message, "] [%4ddBm] [%3u%%] / %5u sampl.",
+               -96 + avg, avg_perc, samples);
+           mvwaddstr(main_sub, 4, strlen(S_RSSI_AVG) + 20, message);
+
+           if (ap_type == ATMEL410) {
+               sprintf(message, "Link quality: %3u%%",
+                   (int)(100 - (minimum (LQCR, 40)) * (float)2.5));
+           } else { /* ap_type == ATMEL12350 */
+               sprintf(message, "Current rate: ");
+               switch(LQCR) {
+                  case 0:
+                       strcat(message, "1 Mbps  ");
+                       break;
+                  case 1:
+                       strcat(message, "2 Mbps  ");
+                       break;
+                  case 2:
+                       strcat(message, "5.5 Mbps");
+                       break;
+                  case 3:
+                       strcat(message, "11 Mbps ");
+               }
+           }
+           mvwaddstr(main_sub, 5, 0, message);
+
+           sprintf(message, "Channel: %2u", Channel);
+           mvwaddstr(main_sub, 6, 0, message);
+
+           mvwaddstr(main_sub, 7, 0, "ESSID: ");
+           waddnstr(main_sub, ESSID, ESSLEN);
+/*
+           sprintf(message, "InfoCapability: %3u", InfoCapability & 0xFF);
+           mvwaddstr(main_sub, 8, 0, message);
+*/
+           wnoutrefresh(main_sub);
+
+           doupdate();
+
+           i = wait_key();
+           if (i == -1)
+               goto exit;
+
+           switch((char) i) {
+               case 'q':
+               case 'Q':
+                   goto exit;
+               case 't':
+               case 'T':
+                   wait_mode = (wait_mode == WAIT_FOREVER ?
+                       WAIT_TIMEOUT : WAIT_FOREVER);
+                   print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF,
+                       AP_TITLE);
+           }
+
+           linked = 1;
+
+           /* either timeout for user input (i == 0) or invalid key => cont. */
+       }
+    }
+
+exit:
+    snmp_retries = 5;
+    delwin(gauge_rssi);
+    delwin(gauge_rssi_top);
+    delwin(gauge_rssi_avg);
+    print_top(NULL, NULL);
+    clear_main(0);
+}
+