]> git.decadent.org.uk Git - ap-utils.git/blob - src/aplink.c
Pass correct platform options to configure
[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 <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include "ap-utils.h"
24
25 #define S_RSSI     _("RSSI:     [")
26 #define S_RSSI_AVG _("RSSI avg: [")
27 #define S_RSSI_TOP _("RSSI top: [")
28 #define S_RSSI_ROU _("RSSI rou: [")
29 #define APLINK_HELP _("P - pause, T - toggle graph view, Q - quit to menu, Other key - force update.")
30
31 #define GRWIN_LENGTH    (COLS - MCOLS - 7)
32 #define GRWIN_HEIGHT    (LAST_ROW - 10)
33
34 int gr_mode = 0;
35
36 extern WINDOW *main_sub;
37 extern short ap_type, ap_vendorext;
38 extern int wait_mode, poll_delay;
39
40 /*
41  * TODO: Implement APClientInfo as alternative, for NetGear ME102 MIB
42  * (ap_type == ATMEL12350 && ap_vendorext == NONE).
43  */
44
45 void atmel_aplink()
46 {
47     char bridgeOperationalMode[] = {
48         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
49     };
50     /*
51      * ATMEL12350 EZYNET MIB and ATMEL410 SBRIDGES MIB specific OIDs:
52      * for ATMEL410 SBRIDGES MIB: .1.3.6.1.4.1.410.1.2.8.1.0
53      * for ATMEL12350 EZYNET MIB: .1.3.6.1.4.1.12350.1.2.7.4.0
54      */
55     char NetworkSettings[] = {
56         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x08, 0x01, 0x00
57     };
58
59     /* APClient mode: AP link diagnostics */
60
61     struct NetworkSettings_ATMEL410_SBRIDGES sa_sb_410;
62     struct NetworkSettings_ATMEL12350_EZYNET sa_en_12350;
63
64     /* Used common members of the 2 structures above. */
65     unsigned char BSSID[6];
66     /* unsigned short InfoCapability; */
67     unsigned char Rssi;
68     unsigned char Channel;
69     /* LinkQuality for NetworkSettings_ATMEL410_SBRIDGES */
70     /* CurrentRate for NetworkSettings_ATMEL12350_EZYNET */
71     unsigned char LQCR;
72     unsigned char ESSID[32];
73     unsigned long ESSLEN; /* uchar for NetworkSettings_ATMEL410_SBRIDGES */
74
75     int i, j = 0, linked = 0, samples = 0, sum = 0, rssi_perc;
76     int rssi_avg = 0, rssi_avg_perc, rssi_top = 0, rssi_top_perc;
77     int rssi_rou, rssi_rou_perc, lq_perc = 0, lq_perc_top = 0;
78     int ringbuf_pos = 0, p_wait_mode = wait_mode;
79     char ringbuf[20];
80     char message[1024];
81     char *gr_modes[5] = { _("RSSI [%]"),
82                           _("RSSI average [%]"),
83                           _("RSSI rounded [%]"),
84                           _("Link Quality [%]"),
85                           NULL };
86     WINDOW *gauge_rssi;
87     WINDOW *gauge_rssi_top;
88     WINDOW *gauge_rssi_avg;
89     WINDOW *gauge_rssi_rou;
90     WINDOW *grwin_rssi;
91     WINDOW *grwin_rssi_avg = NULL;
92     WINDOW *grwin_rssi_rou = NULL;
93     WINDOW *grwin_lq = NULL;
94     varbind varbinds[1];
95
96     if (ap_type == ATMEL12350) {
97         bridgeOperationalMode[5] = 0xE0;
98         bridgeOperationalMode[6] = 0x3E;
99
100         NetworkSettings[5] = 0xE0;
101         NetworkSettings[6] = 0x3E;
102         NetworkSettings[9] = 0x07;
103         NetworkSettings[10] = 0x04;
104     }   
105
106     gauge_rssi = derwin(main_sub, 1, 20, 2, strlen(S_RSSI));
107     gauge_rssi_top = derwin(main_sub, 1, 20, 3, strlen(S_RSSI_TOP));
108     gauge_rssi_avg = derwin(main_sub, 1, 20, 4, strlen(S_RSSI_AVG));
109     gauge_rssi_rou = derwin(main_sub, 1, 20, 5, strlen(S_RSSI_ROU));
110     grwin_rssi = derwin(main_sub, GRWIN_HEIGHT + 2, GRWIN_LENGTH + 2, 9, 3);
111
112     /* find out mode the device is currently in */
113     varbinds[0].oid = bridgeOperationalMode;
114     varbinds[0].len_oid = sizeof(bridgeOperationalMode);
115     varbinds[0].value = bridgeOperationalMode;
116     varbinds[0].len_val = 0;
117     varbinds[0].type = NULL_VALUE;
118     print_help(WAIT_RET);
119     if (snmp(varbinds, 1, GET) <= 0) {
120           print_helperr(ERR_RET);
121           getch();
122           goto exit;
123     }
124
125     /*
126      * Rule out all modes except APClient(3) mode and WRepeater(5) mode on
127      * device running firmware with necessary vendor extensions.
128      */
129     if(!( ((ap_type == ATMEL410 && ap_vendorext == SBRIDGES) ||
130            (ap_type == ATMEL12350 && ap_vendorext == EZYNET)) &&
131           (*(varbinds[0].value) == 3 || *(varbinds[0].value) == 5) )) {
132         mvwaddstr(main_sub, 1, 1,
133             _("Not available - device must have firmware with necessary "));
134         mvwaddstr(main_sub, 2, 1,
135             _("vendor extensions and be in either 'Access Point client'"));
136         mvwaddstr(main_sub, 3, 1,
137             _("or 'Repeater' mode."));
138         print_help(ANY_KEY);
139         wrefresh(main_sub);
140         getch();
141         goto exit;
142     }
143
144     wait_mode = WAIT_TIMEOUT;
145
146     print_top(POLL_ON, AP_TITLE);
147     print_help(APLINK_HELP);
148     noecho();
149
150     memset(ringbuf, 0, sizeof(ringbuf));
151
152     box(grwin_rssi, 0, 0);
153     for (i = GRWIN_HEIGHT - GRWIN_HEIGHT / 3; i > 0; i -= GRWIN_HEIGHT / 3) {
154         j += 33;
155         mvwprintw(main_sub, 9 + i, 0, "%u", j);
156         mvwaddch(grwin_rssi, i, 0, ACS_SSSS);
157     }
158     delwin(grwin_rssi);
159     wmove(main_sub, 9, 6);
160     print_bold(main_sub, gr_modes[gr_mode]);
161     grwin_rssi     = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4);
162     grwin_rssi_avg = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4);
163     grwin_rssi_rou = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4);
164     if (ap_type == ATMEL410)
165         grwin_lq       = newwin(GRWIN_HEIGHT, GRWIN_LENGTH, 12, MCOLS + 4);
166     wattrset(grwin_rssi,     COLOR_PAIR(COLOR_BLUE));
167     wattrset(grwin_rssi_avg, COLOR_PAIR(COLOR_BLUE));
168     wattrset(grwin_rssi_rou, COLOR_PAIR(COLOR_BLUE));
169     if (ap_type == ATMEL410)
170         wattrset(grwin_lq, COLOR_PAIR(COLOR_BLUE));
171
172     while (1) {
173         mvwaddstr(main_sub, 0, 0, "Associated with AP: ");
174
175         varbinds[0].oid = NetworkSettings;
176         varbinds[0].len_oid = sizeof(NetworkSettings);
177         varbinds[0].value = NetworkSettings;
178         varbinds[0].type = STRING_VALUE;
179         varbinds[0].len_val = 0;
180
181         if (snmp(varbinds, 1, GET) <= 0) {
182             /* do just once */
183             waddstr(main_sub, NO);
184             if (linked) {
185                 linked = sum = samples = ringbuf_pos = 0;
186                 memset(ringbuf, 0, sizeof(ringbuf));
187
188                 wclrtoeol(main_sub);
189                 clear_main_new(1, 9);
190                 /* wclrtobot(main_sub); */
191
192                 wattrset(grwin_rssi,     COLOR_PAIR(COLOR_RED));
193                 wattrset(grwin_rssi_avg, COLOR_PAIR(COLOR_RED));
194                 wattrset(grwin_rssi_rou, COLOR_PAIR(COLOR_RED));
195                 if (ap_type == ATMEL410)
196                     wattrset(grwin_lq,   COLOR_PAIR(COLOR_RED));
197
198                 for (i = 0; i < GRWIN_HEIGHT; i++) {
199                     mvwdelch(grwin_rssi,     i, 0);
200                     mvwdelch(grwin_rssi_avg, i, 0);
201                     mvwdelch(grwin_rssi_rou, i, 0);
202                     mvwaddch(grwin_rssi,     i, GRWIN_LENGTH - 1, ACS_SBSB);
203                     mvwaddch(grwin_rssi_avg, i, GRWIN_LENGTH - 1, ACS_SBSB);
204                     mvwaddch(grwin_rssi_rou, i, GRWIN_LENGTH - 1, ACS_SBSB);
205                     if (ap_type == ATMEL410) {
206                         mvwdelch(grwin_lq,   i, 0);
207                         mvwaddch(grwin_lq,   i, GRWIN_LENGTH - 1, ACS_SBSB);
208                     }
209                 }
210                 wattrset(grwin_rssi,     COLOR_PAIR(COLOR_BLUE));
211                 wattrset(grwin_rssi_avg, COLOR_PAIR(COLOR_BLUE));
212                 wattrset(grwin_rssi_rou, COLOR_PAIR(COLOR_BLUE));
213                 if (ap_type == ATMEL410)
214                     wattrset(grwin_lq,   COLOR_PAIR(COLOR_BLUE));
215             }
216
217             wnoutrefresh(main_sub);
218             wnoutrefresh(gr_mode == 0 ? grwin_rssi :
219                          gr_mode == 1 ? grwin_rssi_avg :
220                          gr_mode == 2 ? grwin_rssi_rou : grwin_lq);
221
222             doupdate();
223         } else {
224             waddstr(main_sub, YES);
225
226             if (ap_type == ATMEL410) {
227                 memcpy(&sa_sb_410, varbinds[0].value, varbinds[0].len_val);
228
229                 memcpy(BSSID, sa_sb_410.BSSID, 6);
230                 /* InfoCapability = sa_sb_410.InfoCapability; */
231                 Rssi = sa_sb_410.Rssi;
232                 Channel = sa_sb_410.Channel;
233                 LQCR = sa_sb_410.LinkQuality;
234                 memcpy(ESSID, sa_sb_410.ESSID, 32);
235                 ESSLEN = sa_sb_410.ESSLEN;
236             } else { /* ap_type == ATMEL12350 */
237                 memcpy(&sa_en_12350, varbinds[0].value, varbinds[0].len_val);
238
239                 memcpy(BSSID, sa_en_12350.BSSID, 6);
240                 /* InfoCapability = sa_en_12350.InfoCapability; */
241                 Rssi = sa_en_12350.Rssi;
242                 Channel = sa_en_12350.Channel;
243                 LQCR = sa_en_12350.CurrentRate;
244                 memcpy(ESSID, sa_en_12350.ESSID, 32);
245                 ESSLEN = sa_en_12350.ESSLEN;
246             }
247
248             sprintf(message, "Joined BSSID: %02X%02X%02X%02X%02X%02X",
249                 BSSID[0] & 0xFF, BSSID[1] & 0xFF, BSSID[2] & 0xFF,
250                 BSSID[3] & 0xFF, BSSID[4] & 0xFF, BSSID[5] & 0xFF);
251             mvwaddstr(main_sub, 1, 0, message);
252
253             mvwaddstr(main_sub, 2, 0, S_RSSI);
254             rssi_perc = (int)((minimum (Rssi, 40)) * (float)2.5);
255             werase(gauge_rssi);
256             for (i = 0; i < (20 * rssi_perc / 100); i++) {
257                 if (i == 0)
258                     wattrset(gauge_rssi, COLOR_PAIR(COLOR_RED));
259                 if (i == 7)
260                     wattrset(gauge_rssi, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
261                 if (i == 14)
262                     wattrset(gauge_rssi, COLOR_PAIR(COLOR_GREEN));
263                 waddch(gauge_rssi, ACS_BLOCK);
264             }
265             wnoutrefresh(gauge_rssi);
266             sprintf(message, "] [%4ddBm] [%3u%%] [%3u]",
267                 dbmconv(Rssi), rssi_perc, Rssi);
268             mvwaddstr(main_sub, 2, strlen(S_RSSI) + 20, message);
269
270             mvwaddstr(main_sub, 3, 0, S_RSSI_TOP);
271             if (Rssi > rssi_top)
272                 rssi_top = Rssi;
273             rssi_top_perc = (int)((minimum (rssi_top, 40)) * (float)2.5);
274             werase(gauge_rssi_top);
275             for (i = 0; i < (20 * rssi_top_perc / 100); i++) {
276                 if (i == 0)
277                     wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_RED));
278                 if (i == 7)
279                     wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
280                 if (i == 14)
281                     wattrset(gauge_rssi_top, COLOR_PAIR(COLOR_GREEN));
282                 waddch(gauge_rssi_top, ACS_BLOCK);
283             }
284             wnoutrefresh(gauge_rssi_top);
285             sprintf(message, "] [%4ddBm] [%3u%%] [%3u]",
286                 dbmconv(rssi_top), rssi_top_perc, rssi_top);
287             mvwaddstr(main_sub, 3, strlen(S_RSSI_TOP) + 20, message);
288
289             mvwaddstr(main_sub, 4, 0, S_RSSI_AVG);
290             sum += Rssi;
291             rssi_avg = sum / ++samples;
292             if (samples == 100000) {
293                 samples = 1;
294                 sum = Rssi;
295             }
296             rssi_avg_perc = (int)((minimum (rssi_avg, 40)) * (float)2.5);
297             werase(gauge_rssi_avg);
298             for (i = 0; i < (20 * rssi_avg_perc / 100); i++) {
299                 if (i == 0)
300                     wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_RED));
301                 if (i == 7)
302                     wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
303                 if (i == 14)
304                     wattrset(gauge_rssi_avg, COLOR_PAIR(COLOR_GREEN));
305                 waddch(gauge_rssi_avg, ACS_BLOCK);
306             }
307             wnoutrefresh(gauge_rssi_avg);
308             sprintf(message, "] [%4ddBm] [%3u%%] / %5u sampl.",
309                 dbmconv(rssi_avg), rssi_avg_perc, samples);
310             mvwaddstr(main_sub, 4, strlen(S_RSSI_AVG) + 20, message);
311
312             mvwaddstr(main_sub, 5, 0, S_RSSI_ROU);
313             ringbuf[ringbuf_pos++] = Rssi;
314             if (ringbuf_pos == sizeof(ringbuf))
315                 ringbuf_pos = 0;
316             rssi_rou = 0;
317             for (i = 0; i < (int)sizeof(ringbuf); rssi_rou += ringbuf[i], i++);
318             rssi_rou /= sizeof(ringbuf);
319             rssi_rou_perc = (int)((minimum (rssi_rou, 40)) * (float)2.5);
320             werase(gauge_rssi_rou);
321             for (i = 0; i < (20 * rssi_rou_perc / 100); i++) {
322                 if (i == 0)
323                     wattrset(gauge_rssi_rou, COLOR_PAIR(COLOR_RED));
324                 if (i == 7)
325                     wattrset(gauge_rssi_rou, COLOR_PAIR(COLOR_YELLOW) | A_BOLD);
326                 if (i == 14)
327                     wattrset(gauge_rssi_rou, COLOR_PAIR(COLOR_GREEN));
328                 waddch(gauge_rssi_rou, ACS_BLOCK);
329             }
330             wnoutrefresh(gauge_rssi_rou);
331             sprintf(message, "] [%4ddBm] [%3u%%] / last %2u sam.",
332                 dbmconv(rssi_rou), rssi_rou_perc, sizeof(ringbuf));
333             mvwaddstr(main_sub, 5, strlen(S_RSSI_ROU) + 20, message);
334
335             if (ap_type == ATMEL410) {
336                 lq_perc = (int)(100 - (minimum (LQCR, 40)) * (float)2.5);
337                 if (lq_perc > lq_perc_top)
338                     lq_perc_top = lq_perc;
339                 sprintf(message, "Link quality: %3u%% (top: %3u%%)",
340                     lq_perc, lq_perc_top);
341             } else { /* ap_type == ATMEL12350 */
342                 sprintf(message, "Current rate: ");
343                 switch(LQCR) {
344                    case 0:
345                         strcat(message, "1 Mbps  ");
346                         break;
347                    case 1:
348                         strcat(message, "2 Mbps  ");
349                         break;
350                    case 2:
351                         strcat(message, "5.5 Mbps");
352                         break;
353                    case 3:
354                         strcat(message, "11 Mbps ");
355                 }
356             }
357             mvwaddstr(main_sub, 6, 0, message);
358
359             sprintf(message, "Channel: %2u", Channel);
360             mvwaddstr(main_sub, 7, 0, message);
361
362             mvwaddstr(main_sub, 8, 0, "ESSID: ");
363             waddnstr(main_sub, ESSID, ESSLEN);
364 /*
365             sprintf(message, "InfoCapability: %3u", InfoCapability & 0xFF);
366             mvwaddstr(main_sub, 9, 0, message);
367 */
368             wnoutrefresh(main_sub);
369
370             for (i = 0; i < GRWIN_HEIGHT; i++) {
371                 mvwdelch(grwin_rssi,     i, 0);
372                 mvwdelch(grwin_rssi_avg, i, 0);
373                 mvwdelch(grwin_rssi_rou, i, 0);
374                 if (ap_type == ATMEL410)
375                     mvwdelch(grwin_lq,   i, 0);
376             }
377             for (i = 0; i < GRWIN_HEIGHT * rssi_perc / 100; i++)
378                 mvwaddch(grwin_rssi,
379                     GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK);
380             for (i = 0; i < GRWIN_HEIGHT * rssi_avg_perc / 100; i++)
381                 mvwaddch(grwin_rssi_avg,
382                     GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK);
383             for (i = 0; i < GRWIN_HEIGHT * rssi_rou_perc / 100; i++)
384                 mvwaddch(grwin_rssi_rou,
385                     GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK);
386             if (ap_type == ATMEL410)
387                 for (i = 0; i < GRWIN_HEIGHT * lq_perc / 100; i++)
388                     mvwaddch(grwin_lq,
389                         GRWIN_HEIGHT - 1 - i, GRWIN_LENGTH - 1, ACS_BLOCK);
390
391             wnoutrefresh(gr_mode == 0 ? grwin_rssi :
392                          gr_mode == 1 ? grwin_rssi_avg :
393                          gr_mode == 2 ? grwin_rssi_rou : grwin_lq);
394
395             doupdate();
396
397             linked = 1;
398         }
399
400         i = wait_key(poll_delay);
401         switch(i) {
402             case 'p':
403             case 'P':
404                 getch();
405                 break;
406             case 'q':
407             case 'Q':
408                 goto exit;
409             case 't':
410             case 'T':
411                 gr_mode++;
412                 if (gr_mode == (ap_type == ATMEL410 ? 4 : 3))
413                     gr_mode = 0;
414
415                 wmove(main_sub, 9, 6);
416                 print_bold(main_sub, gr_modes[gr_mode]);
417                 for (i = 0; i < 10; i++)
418                     waddch(main_sub, ACS_BSBS);
419         }
420         /* either timeout for user input (i == 0) or invalid key => cont. */
421     }
422
423 exit:
424     wait_mode = p_wait_mode;
425
426     delwin(gauge_rssi);
427     delwin(gauge_rssi_top);
428     delwin(gauge_rssi_avg);
429     delwin(gauge_rssi_rou);
430
431     delwin(grwin_rssi);
432     delwin(grwin_rssi_avg);
433     delwin(grwin_rssi_rou);
434     if (ap_type == ATMEL410)
435         delwin(grwin_lq);
436
437     print_top(NULL, NULL);
438     clear_main(0);
439 }