X-Git-Url: https://git.decadent.org.uk/gitweb/?p=ap-utils.git;a=blobdiff_plain;f=src%2Faplink.c;fp=src%2Faplink.c;h=e3e5413133893be188995e6cbeda226c2fe2f078;hp=0000000000000000000000000000000000000000;hb=1aac4ac30a9a0d6cd2182013d2b3fd48b65ed2fd;hpb=5c77e013a46530bb3650f61d768dfed0dd3b72cb diff --git a/src/aplink.c b/src/aplink.c new file mode 100644 index 0000000..e3e5413 --- /dev/null +++ b/src/aplink.c @@ -0,0 +1,439 @@ +/* + * aplink.c from Access Point SNMP Utils for Linux + * + * Copyright (c) 2005 Jan Rafaj + * + * 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 +#include +#include +#include "ap-utils.h" + +#define S_RSSI _("RSSI: [") +#define S_RSSI_AVG _("RSSI avg: [") +#define S_RSSI_TOP _("RSSI top: [") +#define S_RSSI_ROU _("RSSI rou: [") +#define APLINK_HELP _("P - pause, T - toggle graph view, Q - quit to menu, Other key - force update.") + +#define GRWIN_LENGTH (COLS - MCOLS - 7) +#define GRWIN_HEIGHT (LAST_ROW - 10) + +int gr_mode = 0; + +extern WINDOW *main_sub; +extern short ap_type, ap_vendorext; +extern int wait_mode, poll_delay; + +/* + * 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 OIDs: + * 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 */ + + int i, j = 0, linked = 0, samples = 0, sum = 0, rssi_perc; + int rssi_avg = 0, rssi_avg_perc, rssi_top = 0, rssi_top_perc; + int rssi_rou, rssi_rou_perc, lq_perc = 0, lq_perc_top = 0; + int ringbuf_pos = 0, p_wait_mode = wait_mode; + char ringbuf[20]; + char message[1024]; + char *gr_modes[5] = { _("RSSI [%]"), + _("RSSI average [%]"), + _("RSSI rounded [%]"), + _("Link Quality [%]"), + NULL }; + WINDOW *gauge_rssi; + WINDOW *gauge_rssi_top; + WINDOW *gauge_rssi_avg; + WINDOW *gauge_rssi_rou; + WINDOW *grwin_rssi; + WINDOW *grwin_rssi_avg = NULL; + WINDOW *grwin_rssi_rou = NULL; + WINDOW *grwin_lq = NULL; + varbind varbinds[1]; + + 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)); + gauge_rssi_rou = derwin(main_sub, 1, 20, 5, strlen(S_RSSI_ROU)); + grwin_rssi = derwin(main_sub, GRWIN_HEIGHT + 2, GRWIN_LENGTH + 2, 9, 3); + + /* 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; + } + + wait_mode = WAIT_TIMEOUT; + + print_top(POLL_ON, AP_TITLE); + print_help(APLINK_HELP); + noecho(); + + memset(ringbuf, 0, sizeof(ringbuf)); + + box(grwin_rssi, 0, 0); + for (i = GRWIN_HEIGHT - GRWIN_HEIGHT / 3; i > 0; i -= GRWIN_HEIGHT / 3) { + j += 33; + mvwprintw(main_sub, 9 + i, 0, "%u", j); + mvwaddch(grwin_rssi, i, 0, ACS_SSSS); + } + delwin(grwin_rssi); + wmove(main_sub, 9, 6); + print_bold(main_sub, gr_modes[gr_mode]); + grwin_rssi = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4); + grwin_rssi_avg = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4); + grwin_rssi_rou = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4); + if (ap_type == ATMEL410) + grwin_lq = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4); + wattrset(grwin_rssi, COLOR_PAIR(COLOR_BLUE)); + wattrset(grwin_rssi_avg, COLOR_PAIR(COLOR_BLUE)); + wattrset(grwin_rssi_rou, COLOR_PAIR(COLOR_BLUE)); + if (ap_type == ATMEL410) + wattrset(grwin_lq, COLOR_PAIR(COLOR_BLUE)); + + while (1) { + mvwaddstr(main_sub, 0, 0, "Associated with AP: "); + + 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 (snmp(varbinds, 1, GET) <= 0) { + /* do just once */ + waddstr(main_sub, NO); + if (linked) { + linked = sum = samples = ringbuf_pos = 0; + memset(ringbuf, 0, sizeof(ringbuf)); + + wclrtoeol(main_sub); + clear_main_new(1, 9); + /* wclrtobot(main_sub); */ + + wattrset(grwin_rssi, COLOR_PAIR(COLOR_RED)); + wattrset(grwin_rssi_avg, COLOR_PAIR(COLOR_RED)); + wattrset(grwin_rssi_rou, COLOR_PAIR(COLOR_RED)); + if (ap_type == ATMEL410) + wattrset(grwin_lq, COLOR_PAIR(COLOR_RED)); + + for (i = 0; i < GRWIN_HEIGHT; i++) { + mvwdelch(grwin_rssi, i, 0); + mvwdelch(grwin_rssi_avg, i, 0); + mvwdelch(grwin_rssi_rou, i, 0); + mvwaddch(grwin_rssi, i, GRWIN_LENGTH - 1, ACS_SBSB); + mvwaddch(grwin_rssi_avg, i, GRWIN_LENGTH - 1, ACS_SBSB); + mvwaddch(grwin_rssi_rou, i, GRWIN_LENGTH - 1, ACS_SBSB); + if (ap_type == ATMEL410) { + mvwdelch(grwin_lq, i, 0); + mvwaddch(grwin_lq, i, GRWIN_LENGTH - 1, ACS_SBSB); + } + } + wattrset(grwin_rssi, COLOR_PAIR(COLOR_BLUE)); + wattrset(grwin_rssi_avg, COLOR_PAIR(COLOR_BLUE)); + wattrset(grwin_rssi_rou, COLOR_PAIR(COLOR_BLUE)); + if (ap_type == ATMEL410) + wattrset(grwin_lq, COLOR_PAIR(COLOR_BLUE)); + } + + wnoutrefresh(main_sub); + wnoutrefresh(gr_mode == 0 ? grwin_rssi : + gr_mode == 1 ? grwin_rssi_avg : + gr_mode == 2 ? grwin_rssi_rou : grwin_lq); + + doupdate(); + } else { + 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]", + dbmconv(Rssi), rssi_perc, Rssi); + mvwaddstr(main_sub, 2, strlen(S_RSSI) + 20, message); + + mvwaddstr(main_sub, 3, 0, S_RSSI_TOP); + if (Rssi > rssi_top) + rssi_top = Rssi; + rssi_top_perc = (int)((minimum (rssi_top, 40)) * (float)2.5); + werase(gauge_rssi_top); + for (i = 0; i < (20 * rssi_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]", + dbmconv(rssi_top), rssi_top_perc, rssi_top); + mvwaddstr(main_sub, 3, strlen(S_RSSI_TOP) + 20, message); + + mvwaddstr(main_sub, 4, 0, S_RSSI_AVG); + sum += Rssi; + rssi_avg = sum / ++samples; + if (samples == 100000) { + samples = 1; + sum = Rssi; + } + rssi_avg_perc = (int)((minimum (rssi_avg, 40)) * (float)2.5); + werase(gauge_rssi_avg); + for (i = 0; i < (20 * rssi_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.", + dbmconv(rssi_avg), rssi_avg_perc, samples); + mvwaddstr(main_sub, 4, strlen(S_RSSI_AVG) + 20, message); + + mvwaddstr(main_sub, 5, 0, S_RSSI_ROU); + ringbuf[ringbuf_pos++] = Rssi; + if (ringbuf_pos == sizeof(ringbuf)) + ringbuf_pos = 0; + rssi_rou = 0; + for (i = 0; i < (int)sizeof(ringbuf); rssi_rou += ringbuf[i], i++); + rssi_rou /= sizeof(ringbuf); + rssi_rou_perc = (int)((minimum (rssi_rou, 40)) * (float)2.5); + werase(gauge_rssi_rou); + for (i = 0; i < (20 * rssi_rou_perc / 100); i++) { + if (i == 0) + wattrset(gauge_rssi_rou, COLOR_PAIR(COLOR_RED)); + if (i == 7) + wattrset(gauge_rssi_rou, COLOR_PAIR(COLOR_YELLOW) | A_BOLD); + if (i == 14) + wattrset(gauge_rssi_rou, COLOR_PAIR(COLOR_GREEN)); + waddch(gauge_rssi_rou, ACS_BLOCK); + } + wnoutrefresh(gauge_rssi_rou); + sprintf(message, "] [%4ddBm] [%3u%%] / last %2u sam.", + dbmconv(rssi_rou), rssi_rou_perc, sizeof(ringbuf)); + mvwaddstr(main_sub, 5, strlen(S_RSSI_ROU) + 20, message); + + if (ap_type == ATMEL410) { + lq_perc = (int)(100 - (minimum (LQCR, 40)) * (float)2.5); + if (lq_perc > lq_perc_top) + lq_perc_top = lq_perc; + sprintf(message, "Link quality: %3u%% (top: %3u%%)", + lq_perc, lq_perc_top); + } 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, 6, 0, message); + + sprintf(message, "Channel: %2u", Channel); + mvwaddstr(main_sub, 7, 0, message); + + mvwaddstr(main_sub, 8, 0, "ESSID: "); + waddnstr(main_sub, ESSID, ESSLEN); +/* + sprintf(message, "InfoCapability: %3u", InfoCapability & 0xFF); + mvwaddstr(main_sub, 9, 0, message); +*/ + wnoutrefresh(main_sub); + + for (i = 0; i < GRWIN_HEIGHT; i++) { + mvwdelch(grwin_rssi, i, 0); + mvwdelch(grwin_rssi_avg, i, 0); + mvwdelch(grwin_rssi_rou, i, 0); + if (ap_type == ATMEL410) + mvwdelch(grwin_lq, i, 0); + } + for (i = 0; i < GRWIN_HEIGHT * rssi_perc / 100; i++) + mvwaddch(grwin_rssi, + GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK); + for (i = 0; i < GRWIN_HEIGHT * rssi_avg_perc / 100; i++) + mvwaddch(grwin_rssi_avg, + GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK); + for (i = 0; i < GRWIN_HEIGHT * rssi_rou_perc / 100; i++) + mvwaddch(grwin_rssi_rou, + GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK); + if (ap_type == ATMEL410) + for (i = 0; i < GRWIN_HEIGHT * lq_perc / 100; i++) + mvwaddch(grwin_lq, + GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK); + + wnoutrefresh(gr_mode == 0 ? grwin_rssi : + gr_mode == 1 ? grwin_rssi_avg : + gr_mode == 2 ? grwin_rssi_rou : grwin_lq); + + doupdate(); + + linked = 1; + } + + i = wait_key(poll_delay); + switch(i) { + case 'p': + case 'P': + getch(); + break; + case 'q': + case 'Q': + goto exit; + case 't': + case 'T': + gr_mode++; + if (gr_mode == (ap_type == ATMEL410 ? 4 : 3)) + gr_mode = 0; + + wmove(main_sub, 9, 6); + print_bold(main_sub, gr_modes[gr_mode]); + for (i = 0; i < 10; i++) + waddch(main_sub, ACS_BSBS); + } + /* either timeout for user input (i == 0) or invalid key => cont. */ + } + +exit: + wait_mode = p_wait_mode; + + delwin(gauge_rssi); + delwin(gauge_rssi_top); + delwin(gauge_rssi_avg); + delwin(gauge_rssi_rou); + + delwin(grwin_rssi); + delwin(grwin_rssi_avg); + delwin(grwin_rssi_rou); + if (ap_type == ATMEL410) + delwin(grwin_lq); + + print_top(NULL, NULL); + clear_main(0); +}