]> git.decadent.org.uk Git - ap-utils.git/blob - src/aplink.c
Imported Upstream version 1.5~pre2
[ap-utils.git] / src / aplink.c
1 /*
2  *        aplink.c from Access Point SNMP Utils for Linux
3  *
4  * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License Version 2 from
8  * June 1991 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 #include <sys/wait.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <fcntl.h>
24 #include <signal.h>
25 #include <string.h>
26 #include "ap-utils.h"
27
28 #define S_RSSI     _("RSSI:     [")
29 #define S_RSSI_AVG _("RSSI avg: [")
30 #define S_RSSI_TOP _("RSSI top: [")
31
32 extern WINDOW *main_sub;
33 extern short ap_type, ap_vendorext;
34 extern int wait_mode, snmp_retries;
35
36 /*
37  * TODO: Implement APClientInfo as alternative, for NetGear ME102 MIB
38  * (ap_type == ATMEL12350 && ap_vendorext == NONE).
39  */
40
41 void atmel_aplink()
42 {
43     char bridgeOperationalMode[] = {
44         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
45     };
46     /*
47      * ATMEL12350 EZYNET MIB and ATMEL410 SBRIDGES MIB specific:
48      * for ATMEL410 SBRIDGES MIB: .1.3.6.1.4.1.410.1.2.8.1.0
49      * for ATMEL12350 EZYNET MIB: .1.3.6.1.4.1.12350.1.2.7.4.0
50      */
51     char NetworkSettings[] = {
52         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x08, 0x01, 0x00
53     };
54
55     /* APClient mode: AP link diagnostics */
56
57     struct NetworkSettings_ATMEL410_SBRIDGES sa_sb_410;
58     struct NetworkSettings_ATMEL12350_EZYNET sa_en_12350;
59
60     /* Used common members of the 2 structures above. */
61     unsigned char BSSID[6];
62     /* unsigned short InfoCapability; */
63     unsigned char Rssi;
64     unsigned char Channel;
65     /* LinkQuality for NetworkSettings_ATMEL410_SBRIDGES */
66     /* CurrentRate for NetworkSettings_ATMEL12350_EZYNET */
67     unsigned char LQCR;
68     unsigned char ESSID[32];
69     unsigned long ESSLEN; /* uchar for NetworkSettings_ATMEL410_SBRIDGES */
70
71     char message[1024];
72     int i, linked = 0, rssi_perc, samples = 0, sum = 0, avg = 0, avg_perc;
73     int top = 0, top_perc;
74     varbind varbinds[1];
75     WINDOW *gauge_rssi, *gauge_rssi_avg, *gauge_rssi_top;
76
77     if (ap_type == ATMEL12350) {
78         bridgeOperationalMode[5] = 0xE0;
79         bridgeOperationalMode[6] = 0x3E;
80
81         NetworkSettings[5] = 0xE0;
82         NetworkSettings[6] = 0x3E;
83         NetworkSettings[9] = 0x07;
84         NetworkSettings[10] = 0x04;
85     }   
86
87     gauge_rssi = derwin(main_sub, 1, 20, 2, strlen(S_RSSI));
88     gauge_rssi_top = derwin(main_sub, 1, 20, 3, strlen(S_RSSI_TOP));
89     gauge_rssi_avg = derwin(main_sub, 1, 20, 4, strlen(S_RSSI_AVG));
90
91     /* find out mode the device is currently in */
92     varbinds[0].oid = bridgeOperationalMode;
93     varbinds[0].len_oid = sizeof(bridgeOperationalMode);
94     varbinds[0].value = bridgeOperationalMode;
95     varbinds[0].len_val = 0;
96     varbinds[0].type = NULL_VALUE;
97     print_help(WAIT_RET);
98     if (snmp(varbinds, 1, GET) <= 0) {
99           print_helperr(ERR_RET);
100           getch();
101           goto exit;
102     }
103
104     /*
105      * Rule out all modes except APClient(3) mode and WRepeater(5) mode on
106      * device running firmware with necessary vendor extensions.
107      */
108     if(!( ((ap_type == ATMEL410 && ap_vendorext == SBRIDGES) ||
109            (ap_type == ATMEL12350 && ap_vendorext == EZYNET)) &&
110           (*(varbinds[0].value) == 3 || *(varbinds[0].value) == 5) )) {
111         mvwaddstr(main_sub, 1, 1,
112             _("Not available - device must have firmware with necessary "));
113         mvwaddstr(main_sub, 2, 1,
114             _("vendor extensions and be in either 'Access Point client'"));
115         mvwaddstr(main_sub, 3, 1,
116             _("or 'Repeater' mode."));
117         print_help(ANY_KEY);
118         wrefresh(main_sub);
119         getch();
120         goto exit;
121     }
122
123     print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF, AP_TITLE);
124     print_help(QT_HELP);
125     noecho();
126
127     while (1) {
128         /* find out how many STAtions is in the list */
129         varbinds[0].oid = NetworkSettings;
130         varbinds[0].len_oid = sizeof(NetworkSettings);
131         varbinds[0].value = NetworkSettings;
132         varbinds[0].type = STRING_VALUE;
133         varbinds[0].len_val = 0;
134
135         if (wait_mode == WAIT_FOREVER)
136             print_help(WAIT_RET);
137
138         snmp_retries = 1;
139         mvwaddstr(main_sub, 0, 0, "Associated with AP: ");
140         if (snmp(varbinds, 1, GET) <= 0) {
141             waddstr(main_sub, NO);
142             if (linked)
143                 clear_main(0);
144
145             wrefresh(main_sub);
146             linked = 0;
147             sum = samples = 0;
148         } else {
149             if (wait_mode == WAIT_FOREVER)
150                 print_help(QT_HELP);
151
152             waddstr(main_sub, YES);
153
154             if (ap_type == ATMEL410) {
155                 memcpy(&sa_sb_410, varbinds[0].value, varbinds[0].len_val);
156
157                 memcpy(BSSID, sa_sb_410.BSSID, 6);
158                 /* InfoCapability = sa_sb_410.InfoCapability; */
159                 Rssi = sa_sb_410.Rssi;
160                 Channel = sa_sb_410.Channel;
161                 LQCR = sa_sb_410.LinkQuality;
162                 memcpy(ESSID, sa_sb_410.ESSID, 32);
163                 ESSLEN = sa_sb_410.ESSLEN;
164             } else { /* ap_type == ATMEL12350 */
165                 memcpy(&sa_en_12350, varbinds[0].value, varbinds[0].len_val);
166
167                 memcpy(BSSID, sa_en_12350.BSSID, 6);
168                 /* InfoCapability = sa_en_12350.InfoCapability; */
169                 Rssi = sa_en_12350.Rssi;
170                 Channel = sa_en_12350.Channel;
171                 LQCR = sa_en_12350.CurrentRate;
172                 memcpy(ESSID, sa_en_12350.ESSID, 32);
173                 ESSLEN = sa_en_12350.ESSLEN;
174             }
175
176             sprintf(message, "Joined BSSID: %02X%02X%02X%02X%02X%02X",
177                 BSSID[0] & 0xFF, BSSID[1] & 0xFF, BSSID[2] & 0xFF,
178                 BSSID[3] & 0xFF, BSSID[4] & 0xFF, BSSID[5] & 0xFF);
179             mvwaddstr(main_sub, 1, 0, message);
180
181             mvwaddstr(main_sub, 2, 0, S_RSSI);
182             rssi_perc = (int)((minimum (Rssi, 40)) * (float)2.5);
183             werase(gauge_rssi);
184             for (i = 0; i < (20 * rssi_perc / 100); i++) {
185                 if (i == 0)
186                     wattrset(gauge_rssi, COLOR_PAIR(COLOR_RED));
187                 if (i == 7)
188                     wattrset(gauge_rssi, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
189                 if (i == 14)
190                     wattrset(gauge_rssi, COLOR_PAIR(COLOR_GREEN));
191                 waddch(gauge_rssi, ACS_BLOCK);
192             }
193             wnoutrefresh(gauge_rssi);
194             sprintf(message, "] [%4ddBm] [%3u%%] [%3u]",
195                 -96 + Rssi, rssi_perc, Rssi);
196             mvwaddstr(main_sub, 2, strlen(S_RSSI) + 20, message);
197
198             mvwaddstr(main_sub, 3, 0, S_RSSI_TOP);
199             if (Rssi > top)
200                 top = Rssi;
201             top_perc = (int)((minimum (top, 40)) * (float)2.5);
202             werase(gauge_rssi_top);
203             for (i = 0; i < (20 * top_perc / 100); i++) {
204                 if (i == 0)
205                     wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_RED));
206                 if (i == 7)
207                     wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
208                 if (i == 14)
209                     wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_GREEN));
210                 waddch(gauge_rssi_top, ACS_BLOCK);
211             }
212             wnoutrefresh(gauge_rssi_top);
213             sprintf(message, "] [%4ddBm] [%3u%%] [%3u]",
214                 -96 + top, top_perc, top);
215             mvwaddstr(main_sub, 3, strlen(S_RSSI_TOP) + 20, message);
216
217             mvwaddstr(main_sub, 4, 0, S_RSSI_AVG);
218             sum += Rssi;
219             avg = sum / ++samples;
220             if (samples == 100000) {
221                 samples = 1;
222                 sum = Rssi;
223             }
224             avg_perc = (int)((minimum (avg, 40)) * (float)2.5);
225             werase(gauge_rssi_avg);
226             for (i = 0; i < (20 * avg_perc / 100); i++) {
227                 if (i == 0)
228                     wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_RED));
229                 if (i == 7)
230                     wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
231                 if (i == 14)
232                     wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_GREEN));
233                 waddch(gauge_rssi_avg, ACS_BLOCK);
234             }
235             wnoutrefresh(gauge_rssi_avg);
236             sprintf(message, "] [%4ddBm] [%3u%%] / %5u sampl.",
237                 -96 + avg, avg_perc, samples);
238             mvwaddstr(main_sub, 4, strlen(S_RSSI_AVG) + 20, message);
239
240             if (ap_type == ATMEL410) {
241                 sprintf(message, "Link quality: %3u%%",
242                     (int)(100 - (minimum (LQCR, 40)) * (float)2.5));
243             } else { /* ap_type == ATMEL12350 */
244                 sprintf(message, "Current rate: ");
245                 switch(LQCR) {
246                    case 0:
247                         strcat(message, "1 Mbps  ");
248                         break;
249                    case 1:
250                         strcat(message, "2 Mbps  ");
251                         break;
252                    case 2:
253                         strcat(message, "5.5 Mbps");
254                         break;
255                    case 3:
256                         strcat(message, "11 Mbps ");
257                 }
258             }
259             mvwaddstr(main_sub, 5, 0, message);
260
261             sprintf(message, "Channel: %2u", Channel);
262             mvwaddstr(main_sub, 6, 0, message);
263
264             mvwaddstr(main_sub, 7, 0, "ESSID: ");
265             waddnstr(main_sub, ESSID, ESSLEN);
266 /*
267             sprintf(message, "InfoCapability: %3u", InfoCapability & 0xFF);
268             mvwaddstr(main_sub, 8, 0, message);
269 */
270             wnoutrefresh(main_sub);
271
272             doupdate();
273
274             i = wait_key();
275             if (i == -1)
276                 goto exit;
277
278             switch((char) i) {
279                 case 'q':
280                 case 'Q':
281                     goto exit;
282                 case 't':
283                 case 'T':
284                     wait_mode = (wait_mode == WAIT_FOREVER ?
285                         WAIT_TIMEOUT : WAIT_FOREVER);
286                     print_top(wait_mode == WAIT_TIMEOUT ? POLL_ON : POLL_OFF,
287                         AP_TITLE);
288             }
289
290             linked = 1;
291
292             /* either timeout for user input (i == 0) or invalid key => cont. */
293         }
294     }
295
296 exit:
297     snmp_retries = 5;
298     delwin(gauge_rssi);
299     delwin(gauge_rssi_top);
300     delwin(gauge_rssi_avg);
301     print_top(NULL, NULL);
302     clear_main(0);
303 }
304