2 * aps.c from Access Point SNMP Utils for Linux
4 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
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.
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.
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
23 #include <sys/types.h>
28 #include "ap-curses.h"
30 extern WINDOW *main_sub/*, *win_for_menu*/;
32 extern int sockfd, atmel410_filter;
33 extern struct in_addr ap_ip;
40 * Structure of single record in the KnownAP table.
46 unsigned char channel;
48 unsigned char options;
50 unsigned char essid[32];
54 * Structure used to preserve important values of AP records learnt
55 * by KnownAP scan. Used to connect to a specific AP.
62 enum { Infrastructure, AdHoc } nettype;
65 /* this one is ATMEL12350 specific */
66 char SiteSurveyCommand[] = {
67 0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x01, 0x01, 0x07, 0x00
70 char bridgeOperationalMode[] = {
71 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
73 char bridgeRemoteBridgeBSSID[] = {
74 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x02, 0x00
77 char operChannelID[] = {
78 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x01, 0x00
80 char operESSIDLength[] = {
81 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x02, 0x00
84 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x03, 0x00
87 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x07, 0x01, 0x00
90 char value[] = "", c, bridge_mode;
91 char essid[33], bssid[13], message[65];
92 int i, j, errno, aps_num = 0, needs_opmode_restore = 0;
95 if (ap_type == ATMEL12350) {
96 operESSIDLength[5] = 0xE0;
97 operESSIDLength[6] = 0x3E;
100 operChannelID[5] = 0xE0;
101 operChannelID[6] = 0x3E;
104 bridgeOperationalMode[5] = 0xE0;
105 bridgeOperationalMode[6] = 0x3E;
106 bridgeRemoteBridgeBSSID[5] = 0xE0;
107 bridgeRemoteBridgeBSSID[6] = 0x3E;
111 print_help(WAIT_RET);
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 if (snmp(varbinds, 1, GET) <= 0) {
119 print_helperr(ERR_RET);
122 bridge_mode = *(varbinds[0].value);
124 /* ATMEL410 firmware KnownAP scan is active in AP Client mode only */
125 if (ap_type == ATMEL410 && bridge_mode != 3) {
126 mvwaddstr(main_sub, 3, 1,
128 ("Your Access Point is not in \"AP client\" mode => getting"));
129 mvwaddstr(main_sub, 4, 1,
131 ("up-to-date \"Known APs\" info requires your AP to be"));
132 mvwaddstr(main_sub, 5, 1,
134 ("temporarily configured into \"AP client\" mode and rebooted."));
135 mvwaddstr(main_sub, 6, 1,
137 ("Your AP will be reconfigured back to original mode by this"));
138 mvwaddstr(main_sub, 7, 1,
140 ("utility once you quit the \"KnownAP\" view. This, in turn, may"));
141 mvwaddstr(main_sub, 8, 1,
143 ("cause loss of Access Point's current configuration."));
144 wattrset(main_sub, A_BOLD);
145 mvwaddstr(main_sub, 9, 1,
147 ("Do NOT answer \"Yes\" if you're connected to the Access Point"));
148 mvwaddstr(main_sub, 10, 1,
150 ("via its wireless port."));
151 wattrset(main_sub, A_NORMAL);
152 mvwaddstr(main_sub, 12, 20, _("Do you want to continue? "));
154 print_help(_("(Y - Yes; N - No (it's safer to answer No)"));
168 needs_opmode_restore = 1;
169 print_help(WAIT_RET);
170 varbinds[0].oid = bridgeOperationalMode;
171 varbinds[0].len_oid = sizeof(bridgeOperationalMode);
172 varbinds[0].type = INT_VALUE;
174 varbinds[0].value = &c;
175 varbinds[0].len_val = 1;
176 if (snmp(varbinds, 1, SET) <= 0) {
177 print_helperr(ERR_RET);
182 print_helperr(ERR_RET);
183 goto restore_before_exit;
189 varbinds[0].oid = KnownAP;
190 varbinds[0].len_oid = sizeof(KnownAP);
191 varbinds[0].type = NULL_VALUE;
192 varbinds[0].value = value;
193 varbinds[0].len_val = sizeof(value);
195 if (snmp(varbinds, 1, GET) <= 0) {
196 print_helperr(ERR_RET);
197 goto restore_before_exit;
202 print_title(_("Known Access Points"));
203 print_viewtype(ap_viewtype);
205 /* display column info in main_sub */
206 mvwin(main_sub, 0, 0);
207 wattrset(main_sub, COLOR_PAIR(3));
208 for (i = 0; i < 64; i++)
209 waddch(main_sub, ' ');
210 switch (ap_viewtype) {
213 mvwaddstr(main_sub, 0, 0, "#");
214 mvwaddstr(main_sub, 0, 2, "ESSID");
215 mvwaddstr(main_sub, 0, 18, "BSSID (MAC)");
216 mvwaddstr(main_sub, 0, 31, "CN");
217 mvwaddstr(main_sub, 0, 34, _("NetworkType"));
218 mvwaddstr(main_sub, 0, 49, "P");
219 mvwaddstr(main_sub, 0, 51, "WEP");
220 mvwaddstr(main_sub, 0, 55, "RSSI");
221 if (ap_type == ATMEL410) mvwaddstr(main_sub, 0, 62, "LQ");
224 mvwaddstr(main_sub, 0, 0, "#");
225 mvwaddstr(main_sub, 0, 2, "ESSID");
226 mvwaddstr(main_sub, 0, 35, "BSSID (MAC)");
227 mvwaddstr(main_sub, 0, 48, "CN");
228 mvwaddstr(main_sub, 0, 51, "P");
229 mvwaddstr(main_sub, 0, 53, "WEP");
230 mvwaddstr(main_sub, 0, 57, "RSSI");
231 if (ap_type == ATMEL410) mvwaddstr(main_sub, 0, 62, "LQ");
234 mvwaddstr(main_sub, 0, 0, "#");
235 mvwaddstr(main_sub, 0, 2, "BSSID (MAC)");
236 mvwaddstr(main_sub, 0, 15, "Manufacturer OUI");
239 wattrset(main_sub, A_NORMAL);
244 app = (struct ap *) &varbinds[0].value[i];
246 j = app->mac[0] | app->mac[1] | app->mac[2] |
247 app->mac[3] | app->mac[4] | app->mac[5];
249 if (!app->channel || app->channel>14 || app->mac[0] == 0xFF
250 || j == 0 || aps_num == 16)
253 i += sizeof(struct ap);
257 sprintf(message, "%c", (aps_num < 10) ? aps_num + '0' : aps_num + 55);
258 mvwaddstr(main_sub, aps_num+1, 0, message);
261 sprintf(bssid, "%02X%02X%02X%02X%02X%02X",
262 app->mac[0] & 0xFF, app->mac[1] & 0xFF,
263 app->mac[2] & 0xFF, app->mac[3] & 0xFF,
264 app->mac[4] & 0xFF, app->mac[5] & 0xFF);
267 /* get ESSID and its length */
268 for (j = 0; j < 32 && app->essid[j]; j++) {
269 essid[j] = app->essid[j];
274 * fill up ap[] field member to preserve ESSID, BSSID, Channel and
275 * Network type of current AP record, so we may use it later
276 * to connect to this very AP
278 memcpy(ap[aps_num-1].mac, app->mac, 6);
279 memcpy(ap[aps_num-1].essid, essid, j);
280 ap[aps_num-1].essid_len = j;
281 ap[aps_num-1].channel = app->channel;
282 ap[aps_num-1].nettype = (app->options & 1) ? Infrastructure : AdHoc;
284 /* display ESSID, BSSID, Channel, NetworkType, Preambule and WEP */
285 switch (ap_viewtype) {
288 mvwaddnstr(main_sub, aps_num+1, 2, essid, 15);
289 mvwaddstr(main_sub, aps_num+1, 18, bssid);
290 sprintf(message, "%2u", app->channel);
291 mvwaddstr(main_sub, aps_num+1, 31, message);
292 mvwaddstr(main_sub, aps_num+1, 34,
293 (app->options & 1) ? _("Infrastructure") : "Ad-Hoc");
294 mvwaddstr(main_sub, aps_num+1, 49,
295 (app->options & 32) ? "S" : "L");
296 mvwaddstr(main_sub, aps_num+1, 51,
297 (app->options & 16) ? ON : OFF);
300 mvwaddstr(main_sub, aps_num+1, 2, essid);
301 mvwaddstr(main_sub, aps_num+1, 35, bssid);
302 sprintf(message, "%2u", app->channel);
303 mvwaddstr(main_sub, aps_num+1, 48, message);
304 mvwaddstr(main_sub, aps_num+1, 51,
305 (app->options & 32) ? "S" : "L");
306 mvwaddstr(main_sub, aps_num+1, 53,
307 (app->options & 16) ? ON : OFF);
310 mvwaddstr(main_sub, aps_num+1, 2, bssid);
311 mvwaddnstr(main_sub, aps_num+1, 15,
312 oui2manufacturer(app->mac), 48);
316 /* display RSSI and LQ indicators */
317 switch (ap_viewtype) {
319 sprintf(message, "%3d", -96 + app->q1);
320 mvwaddstr(main_sub, aps_num+1, 56, message);
321 if (ap_type == ATMEL410) {
322 sprintf(message, "%3d", (int)(100 - (minimum (app->q2, 40)) * (float)2.5) );
323 mvwaddstr(main_sub, aps_num+1, 61, message);
327 sprintf(message, "%3d%%",
328 (int)((minimum (app->q1, 40)) * (float)2.5));
329 mvwaddstr(main_sub, aps_num+1, 55, message);
330 if (ap_type == ATMEL410) {
331 sprintf(message, "%3d%%",
332 (int)(100 - (minimum (app->q2, 40)) * (float)2.5) );
333 mvwaddstr(main_sub, aps_num+1, 60, message);
337 sprintf(message, "%3d", app->q1);
338 mvwaddstr(main_sub, aps_num+1, 57, message);
339 if (ap_type == ATMEL410) {
340 sprintf(message, "%3d", app->q2);
341 mvwaddstr(main_sub, aps_num+1, 61, message);
348 /* display legend in main_sub */
349 switch (ap_viewtype) {
351 mvwaddstr(main_sub, LINES - 7, 0,
352 _("CN: Channel Name; P: Preambule Type (S: Short; L: Long);"));
353 mvwaddstr(main_sub, LINES - 6, 0,
354 _("RSSI: Radio Signal Strength Indicator [%];"));
355 if (ap_type == ATMEL410)
356 mvwaddstr(main_sub, LINES - 5, 0, _("LQ: Link Quality [%]"));
359 mvwaddstr(main_sub, LINES - 7, 0,
360 _("CN: Channel Name; P: Preambule Type (S: Short; L: Long);"));
361 mvwaddstr(main_sub, LINES - 6, 0,
362 _("RSSI: Radio Signal Strength Indicator [dBm];"));
363 if (ap_type == ATMEL410)
364 mvwaddstr(main_sub, LINES - 5, 0, _("LQ: Link Quality [%]"));
367 mvwaddstr(main_sub, LINES - 7, 0,
368 _("CN: Channel Name; P: Preambule Type (S: Short; L: Long);"));
369 mvwaddstr(main_sub, LINES - 6, 0,
370 _("RSSI: Radio Signal Strength Indicator [raw];"));
371 if (ap_type == ATMEL410)
372 mvwaddstr(main_sub, LINES - 5, 0, _("LQ: Link Quality [raw]"));
377 if (ap_type == ATMEL410)
378 print_help(_("# con. to this AP; R refresh with reset; S refresh w/o reset; T toggle; Q quit"));
379 else /* ATMEL12350 */
380 print_help(_("# con. to this AP; R initiate AP scan; S refresh view; T toggle view; Q quit"));
383 switch (i = getch()) {
386 goto restore_before_exit;
420 /* don't attempt to connect to remote AP in Ad-Hoc net */
421 if(ap[j-1].nettype == AdHoc)
424 print_help(WAIT_SET);
425 varbinds[3].oid = operChannelID;
426 varbinds[3].len_oid = sizeof(operChannelID);
427 varbinds[3].value = &ap[j-1].channel;
428 varbinds[3].len_val = 1;
429 varbinds[3].type = INT_VALUE;
430 varbinds[2].oid = bridgeRemoteBridgeBSSID;
431 varbinds[2].len_oid = sizeof(bridgeRemoteBridgeBSSID);
432 varbinds[2].value = ap[j-1].mac;
433 varbinds[2].len_val = 6;
434 varbinds[2].type = STRING_VALUE;
435 varbinds[1].oid = operESSIDLength;
436 varbinds[1].len_oid = sizeof(operESSIDLength);
437 varbinds[1].value = (char *) &ap[j-1].essid_len;
438 varbinds[1].len_val = 1;
439 varbinds[1].type = INT_VALUE;
440 varbinds[0].oid = operESSID;
441 varbinds[0].len_oid = sizeof(operESSID);
442 varbinds[0].value = ap[j-1].essid;
443 varbinds[0].len_val = ap[j-1].essid_len;
444 varbinds[0].type = STRING_VALUE;
445 if (snmp(varbinds, 4, SET) <= 0) {
446 print_helperr(ERR_SET);
447 goto restore_before_exit;
450 if (bridge_mode != 3) {
452 needs_opmode_restore = 1;
455 if (SysUpload() < 0 ) {
456 print_helperr(ERR_SET);
458 goto restore_before_exit;
460 print_help(DONE_SET);
462 goto restore_before_exit;
465 if (ap_type == ATMEL410) {
466 /* force KnownAP scan by reset */
467 print_help(WAIT_RET);
468 if (SysReset() < 0) {
469 print_helperr(ERR_RET);
471 goto restore_before_exit;
475 } else { /* ATMEL12350 */
477 * Init KnownAP scan by issuing SiteSurveyCommand.
478 * Unfortunately, we may not use snmp() here becouse
479 * it would time out, as buggy firmware in ATMEL12350
480 * devices does not confirm our query reception
481 * received via wireless port, in a reasonable
482 * time frame. So we rather use sendto() here.
484 struct sockaddr_in toip;
488 varbinds[0].oid = SiteSurveyCommand;
489 varbinds[0].len_oid = sizeof(SiteSurveyCommand);
491 varbinds[0].value = &c;
492 varbinds[0].len_val = 1;
493 varbinds[0].type = INT_VALUE;
495 memset(&toip, 0, sizeof toip);
496 toip.sin_family = AF_INET;
497 toip.sin_port = htons(161);
498 toip.sin_addr.s_addr = ap_ip.s_addr;
500 if (snmp(varbinds, 1, SET) <= 0) {
501 print_helperr(ERR_SET);
506 i = ber(message, varbinds, 1, SET);
507 if (sendto(sockfd, message, i, 0,
508 (struct sockaddr *) &toip, SIZE) == -1) {
509 sprintf(message, _("Failure in sendto(): %s. "
510 "Press any key."), strerror(errno));
511 print_helperr(message);
516 mvwaddstr(main_sub, 3, 1,
518 ("You have just initiated the AP scan. Be advised that it may"));
519 mvwaddstr(main_sub, 4, 1,
521 ("take a few seconds for your Access Point to find out some"));
522 mvwaddstr(main_sub, 5, 1,
524 ("values, so expect finishing the scan in about 5 seconds."));
525 mvwaddstr(main_sub, 6, 1,
527 ("Also note that your Access Point stops forwarding the network"));
528 mvwaddstr(main_sub, 7, 1,
530 ("traffic while the scan is in progress, but restores itself"));
531 mvwaddstr(main_sub, 8, 1,
533 ("to normal operation in time ranging up to 1 minute."));
534 mvwaddstr(main_sub, 9, 1,
536 ("Hence, if you are connected to target Access Point via its"));
537 mvwaddstr(main_sub, 10, 1,
539 ("wireless port, you need to wait a bit longer"));
540 mvwaddstr(main_sub, 11, 1,
542 ("after pressing 'S'."));
547 * Eat the confirmation packet from socket, if it
548 * has been sent by the AP. This only happens
549 * if we issued KnownAP scan via its ethernet
555 FD_SET(sockfd, &rfd);
556 if (select(sockfd + 1, &rfd, NULL, NULL, &tv) > 0)
557 recv(sockfd, message, 65, 0);
559 print_help("Now, you can try pressing 'S' repeatedly "
560 "to watch the progress.");
566 print_help(WAIT_RET);
579 if (needs_opmode_restore) {
580 print_help(WAIT_SET);
581 varbinds[0].oid = bridgeOperationalMode;
582 varbinds[0].len_oid = sizeof(bridgeOperationalMode);
583 varbinds[0].value = (char *) &bridge_mode;
584 varbinds[0].len_val = 1;
585 varbinds[0].type = INT_VALUE;
586 if (snmp(varbinds, 1, SET) <= 0) {
587 print_helperr(ERR_RET);
592 print_helperr(ERR_RET);