2 * aps.c from Access Point SNMP Utils for Linux
4 * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
5 * Copyright (c) 2004 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License Version 2 from
9 * June 1991 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/types.h>
30 #define KNOWN_APS _("Known Access Points")
32 extern WINDOW *main_win, *main_sub /* *win_for_menu */;
33 extern short ap_type, ap_vendorext;
34 extern int sockfd, atmel410_filter;
35 extern struct in_addr ap_ip;
42 * Structure of single record in the KnownAP table.
48 unsigned char channel;
50 unsigned char options;
52 unsigned char essid[32];
56 * Structure used to preserve important values of AP records learnt
57 * by KnownAP scan. Used to connect to a specific AP.
64 enum { Infrastructure, AdHoc } nettype;
67 /* this one is ATMEL12350 specific */
68 char SiteSurveyCommand[] = {
69 0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x01, 0x01, 0x07, 0x00
72 char bridgeOperationalMode[] = {
73 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x01, 0x00
75 char bridgeRemoteBridgeBSSID[] = {
76 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x04, 0x02, 0x00
79 char operChannelID[] = {
80 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x01, 0x00
82 char operESSIDLength[] = {
83 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x02, 0x00
86 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x03, 0x00
89 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x07, 0x01, 0x00
92 char value[] = "", c, bridge_mode;
93 char essid[33], bssid[13], message[65];
94 int i, j, errno, aps_num = 0, needs_opmode_restore = 0;
97 if (ap_type == ATMEL12350) {
98 operESSIDLength[5] = 0xE0;
99 operESSIDLength[6] = 0x3E;
102 operChannelID[5] = 0xE0;
103 operChannelID[6] = 0x3E;
106 bridgeOperationalMode[5] = 0xE0;
107 bridgeOperationalMode[6] = 0x3E;
108 bridgeRemoteBridgeBSSID[5] = 0xE0;
109 bridgeRemoteBridgeBSSID[6] = 0x3E;
113 print_help(WAIT_RET);
115 varbinds[0].oid = bridgeOperationalMode;
116 varbinds[0].len_oid = sizeof(bridgeOperationalMode);
117 varbinds[0].value = bridgeOperationalMode;
118 varbinds[0].len_val = 0;
119 varbinds[0].type = NULL_VALUE;
120 if (snmp(varbinds, 1, GET) <= 0) {
121 print_helperr(ERR_RET);
124 bridge_mode = *(varbinds[0].value);
126 /* ATMEL410 firmware KnownAP scan is active in AP Client mode only */
127 if (ap_type == ATMEL410 && bridge_mode != 3) {
128 mvwaddstr(main_sub, 3, 1,
130 ("Your Access Point is not in \"AP client\" mode => getting"));
131 mvwaddstr(main_sub, 4, 1,
133 ("up-to-date \"Known APs\" info requires your AP to be"));
134 mvwaddstr(main_sub, 5, 1,
136 ("temporarily configured into \"AP client\" mode and rebooted."));
137 mvwaddstr(main_sub, 6, 1,
139 ("Your AP will be reconfigured back to original mode by this"));
140 mvwaddstr(main_sub, 7, 1,
142 ("utility once you quit the \"KnownAP\" view. This, in turn, may"));
143 mvwaddstr(main_sub, 8, 1,
145 ("cause loss of Access Point's current configuration."));
146 wattrset(main_sub, A_BOLD);
147 mvwaddstr(main_sub, 9, 1,
149 ("Do NOT answer \"Yes\" if you're connected to the Access Point"));
150 mvwaddstr(main_sub, 10, 1,
152 ("via its wireless port."));
153 wattrset(main_sub, A_NORMAL);
154 mvwaddstr(main_sub, 12, 20, _("Do you want to continue? "));
159 needs_opmode_restore = 1;
160 print_help(WAIT_RET);
161 varbinds[0].oid = bridgeOperationalMode;
162 varbinds[0].len_oid = sizeof(bridgeOperationalMode);
163 varbinds[0].type = INT_VALUE;
165 varbinds[0].value = &c;
166 varbinds[0].len_val = 1;
167 if (snmp(varbinds, 1, SET) <= 0) {
168 print_helperr(ERR_RET);
173 print_helperr(ERR_RET);
174 goto restore_before_exit;
179 sprintf(message, "%s%c", VIEW, ap_viewtype + '0');
180 print_top(message, KNOWN_APS);
183 varbinds[0].oid = KnownAP;
184 varbinds[0].len_oid = sizeof(KnownAP);
185 varbinds[0].type = NULL_VALUE;
186 varbinds[0].value = value;
187 varbinds[0].len_val = sizeof(value);
189 if (snmp(varbinds, 1, GET) <= 0) {
190 print_helperr(ERR_RET);
191 goto restore_before_exit;
196 /* display column info in main_sub */
197 mvwin(main_sub, 0, 0);
198 wattrset(main_sub, COLOR_PAIR(13));
199 for (i = 0; i < 64; i++)
200 waddch(main_sub, ' ');
201 switch (ap_viewtype) {
204 mvwaddstr(main_sub, 0, 0, "#");
205 mvwaddstr(main_sub, 0, 2, "ESSID");
206 mvwaddstr(main_sub, 0, 18, "BSSID (MAC)");
207 mvwaddstr(main_sub, 0, 31, "CN");
208 mvwaddstr(main_sub, 0, 34, _("NetworkType"));
209 mvwaddstr(main_sub, 0, 49, "P");
210 mvwaddstr(main_sub, 0, 51, "WEP");
211 mvwaddstr(main_sub, 0, 55, "RSSI");
212 if (ap_type == ATMEL410) mvwaddstr(main_sub, 0, 62, "LQ");
215 mvwaddstr(main_sub, 0, 0, "#");
216 mvwaddstr(main_sub, 0, 2, "ESSID");
217 mvwaddstr(main_sub, 0, 35, "BSSID (MAC)");
218 mvwaddstr(main_sub, 0, 48, "CN");
219 mvwaddstr(main_sub, 0, 51, "P");
220 mvwaddstr(main_sub, 0, 53, "WEP");
221 mvwaddstr(main_sub, 0, 57, "RSSI");
222 if (ap_type == ATMEL410) mvwaddstr(main_sub, 0, 62, "LQ");
225 mvwaddstr(main_sub, 0, 0, "#");
226 mvwaddstr(main_sub, 0, 2, "BSSID (MAC)");
227 mvwaddstr(main_sub, 0, 15, "Manufacturer OUI");
230 wattrset(main_sub, A_NORMAL);
235 app = (struct ap *) &varbinds[0].value[i];
237 j = app->mac[0] | app->mac[1] | app->mac[2] |
238 app->mac[3] | app->mac[4] | app->mac[5];
240 if (!app->channel || app->channel>14 || app->mac[0] == 0xFF
241 || j == 0 || aps_num == 16)
244 i += sizeof(struct ap);
248 sprintf(message, "%c", (aps_num < 10) ? aps_num + '0' : aps_num + 55);
249 mvwaddstr(main_sub, aps_num+1, 0, message);
252 sprintf(bssid, "%02X%02X%02X%02X%02X%02X",
253 app->mac[0] & 0xFF, app->mac[1] & 0xFF,
254 app->mac[2] & 0xFF, app->mac[3] & 0xFF,
255 app->mac[4] & 0xFF, app->mac[5] & 0xFF);
258 /* get ESSID and its length */
259 for (j = 0; j < 32 && app->essid[j]; j++) {
260 essid[j] = app->essid[j];
265 * fill up ap[] field member to preserve ESSID, BSSID, Channel and
266 * Network type of current AP record, so we may use it later
267 * to connect to this very AP
269 memcpy(ap[aps_num-1].mac, app->mac, 6);
270 memcpy(ap[aps_num-1].essid, essid, j);
271 ap[aps_num-1].essid_len = j;
272 ap[aps_num-1].channel = app->channel;
273 ap[aps_num-1].nettype = (app->options & 1) ? Infrastructure : AdHoc;
275 /* display ESSID, BSSID, Channel, NetworkType, Preambule and WEP */
276 switch (ap_viewtype) {
279 mvwaddnstr(main_sub, aps_num+1, 2, essid, 15);
280 mvwaddstr(main_sub, aps_num+1, 18, bssid);
281 sprintf(message, "%2u", app->channel);
282 mvwaddstr(main_sub, aps_num+1, 31, message);
283 mvwaddstr(main_sub, aps_num+1, 34,
284 (app->options & 1) ? _("Infrastructure") : "Ad-Hoc");
285 mvwaddstr(main_sub, aps_num+1, 49,
286 (app->options & 32) ? "S" : "L");
287 mvwaddstr(main_sub, aps_num+1, 51,
288 (app->options & 16) ? ON : OFF);
291 mvwaddstr(main_sub, aps_num+1, 2, essid);
292 mvwaddstr(main_sub, aps_num+1, 35, bssid);
293 sprintf(message, "%2u", app->channel);
294 mvwaddstr(main_sub, aps_num+1, 48, message);
295 mvwaddstr(main_sub, aps_num+1, 51,
296 (app->options & 32) ? "S" : "L");
297 mvwaddstr(main_sub, aps_num+1, 53,
298 (app->options & 16) ? ON : OFF);
301 mvwaddstr(main_sub, aps_num+1, 2, bssid);
302 mvwaddnstr(main_sub, aps_num+1, 15,
303 oui2manufacturer(app->mac), 48);
307 /* display RSSI and LQ indicators */
308 switch (ap_viewtype) {
310 sprintf(message, "%3d%%",
311 (int)((minimum (app->q1, 40)) * (float)2.5));
312 mvwaddstr(main_sub, aps_num+1, 55, message);
313 if (ap_type == ATMEL410) {
314 sprintf(message, "%3d%%",
315 (int)(100 - (minimum (app->q2, 40)) * (float)2.5) );
316 mvwaddstr(main_sub, aps_num+1, 60, message);
320 sprintf(message, "%3d", dbmconv(app->q1));
321 mvwaddstr(main_sub, aps_num+1, 56, message);
322 if (ap_type == ATMEL410) {
323 sprintf(message, "%3d%%",
324 (int)(100 - (minimum (app->q2, 40)) * (float)2.5) );
325 mvwaddstr(main_sub, aps_num+1, 60, message);
329 sprintf(message, "%3d", app->q1);
330 mvwaddstr(main_sub, aps_num+1, 57, message);
331 if (ap_type == ATMEL410) {
332 sprintf(message, "%3d", app->q2);
333 mvwaddstr(main_sub, aps_num+1, 61, message);
340 /* display legend in main_sub */
341 switch (ap_viewtype) {
343 mvwaddstr(main_sub, LINES - 6, 0,
344 _("CN: Channel Name; P: Preambule Type (S: Short; L: Long);"));
345 mvwaddstr(main_sub, LINES - 5, 0,
346 _("RSSI: Radio Signal Strength Indicator [%]"));
347 if (ap_type == ATMEL410)
348 waddstr(main_sub, _("; LQ: Link Quality [%]"));
351 mvwaddstr(main_sub, LINES - 6, 0,
352 _("CN: Channel Name; P: Preambule Type (S: Short; L: Long);"));
353 mvwaddstr(main_sub, LINES - 5, 0,
354 _("RSSI: Radio Signal Strength Indicator [dBm]"));
355 if (ap_type == ATMEL410)
356 waddstr(main_sub, _("; LQ: Link Quality [%]"));
359 mvwaddstr(main_sub, LINES - 6, 0,
360 _("CN: Channel Name; P: Preambule Type (S: Short; L: Long);"));
361 mvwaddstr(main_sub, LINES - 5, 0,
362 _("RSSI: Radio Signal Strength Indicator [raw]"));
363 if (ap_type == ATMEL410)
364 waddstr(main_sub, _("; LQ: Link Q. [raw]"));
369 if (ap_type == ATMEL410)
370 print_help(_("# con. to AP #; R refresh with reset; T toggle; Q quit; Other = refr. w/o reset"));
371 else /* ATMEL12350 */
372 print_help(_("# con. to AP #; R initiate AP scan; T toggle view; Q quit; Other = refresh view"));
375 switch (i = getch()) {
378 goto restore_before_exit;
412 /* don't attempt to connect to remote AP in Ad-Hoc net */
413 if(ap[j-1].nettype == AdHoc)
416 print_help(WAIT_SET);
417 varbinds[3].oid = operChannelID;
418 varbinds[3].len_oid = sizeof(operChannelID);
419 varbinds[3].value = &ap[j-1].channel;
420 varbinds[3].len_val = 1;
421 varbinds[3].type = INT_VALUE;
422 varbinds[2].oid = bridgeRemoteBridgeBSSID;
423 varbinds[2].len_oid = sizeof(bridgeRemoteBridgeBSSID);
424 varbinds[2].value = ap[j-1].mac;
425 varbinds[2].len_val = 6;
426 varbinds[2].type = STRING_VALUE;
427 varbinds[1].oid = operESSIDLength;
428 varbinds[1].len_oid = sizeof(operESSIDLength);
429 varbinds[1].value = (char *) &ap[j-1].essid_len;
430 varbinds[1].len_val = 1;
431 varbinds[1].type = INT_VALUE;
432 varbinds[0].oid = operESSID;
433 varbinds[0].len_oid = sizeof(operESSID);
434 varbinds[0].value = ap[j-1].essid;
435 varbinds[0].len_val = ap[j-1].essid_len;
436 varbinds[0].type = STRING_VALUE;
437 if (snmp(varbinds, 4, SET) <= 0) {
438 print_helperr(ERR_SET);
439 goto restore_before_exit;
442 if (bridge_mode != 3) {
444 needs_opmode_restore = 1;
447 if (SysUpload() < 0 ) {
448 print_helperr(ERR_SET);
450 goto restore_before_exit;
452 print_help(DONE_SET);
454 goto restore_before_exit;
457 if (ap_type == ATMEL410) {
458 /* force KnownAP scan by reset */
459 print_help(WAIT_RET);
460 if (SysReset() < 0) {
461 print_helperr(ERR_RET);
463 goto restore_before_exit;
467 } else { /* ATMEL12350 */
469 * Init KnownAP scan by issuing SiteSurveyCommand.
470 * Unfortunately, we may not use snmp() here becouse
471 * it would time out, as buggy firmware in ATMEL12350
472 * devices does not confirm our query reception
473 * received via wireless port, in a reasonable
474 * time frame. So we rather use sendto() here.
476 struct sockaddr_in toip;
480 varbinds[0].oid = SiteSurveyCommand;
481 varbinds[0].len_oid = sizeof(SiteSurveyCommand);
483 varbinds[0].value = &c;
484 varbinds[0].len_val = 1;
485 varbinds[0].type = INT_VALUE;
487 memset(&toip, 0, sizeof toip);
488 toip.sin_family = AF_INET;
489 toip.sin_port = htons(161);
490 toip.sin_addr.s_addr = ap_ip.s_addr;
492 if (snmp(varbinds, 1, SET) <= 0) {
493 print_helperr(ERR_SET);
498 i = ber(message, varbinds, 1, SET);
499 if (sendto(sockfd, message, i, 0,
500 (struct sockaddr *) &toip, SIZE) == -1) {
501 sprintf(message, _("Failure in sendto(): %s. "
502 "Press any key."), strerror(errno));
503 print_helperr(message);
508 mvwaddstr(main_sub, 3, 1,
510 ("You have just initiated the AP scan. Be advised that it may"));
511 mvwaddstr(main_sub, 4, 1,
513 ("take a few seconds for your Access Point to find out some"));
514 mvwaddstr(main_sub, 5, 1,
516 ("values, so expect finishing the scan in about 5 seconds."));
517 mvwaddstr(main_sub, 6, 1,
519 ("Also note that your Access Point stops forwarding the network"));
520 mvwaddstr(main_sub, 7, 1,
522 ("traffic while the scan is in progress, but restores itself"));
523 mvwaddstr(main_sub, 8, 1,
525 ("to normal operation in time ranging up to 1 minute."));
526 mvwaddstr(main_sub, 9, 1,
528 ("Hence, if you are connected to target Access Point via its"));
529 mvwaddstr(main_sub, 10, 1,
531 ("wireless port, you need to wait a bit longer"));
532 mvwaddstr(main_sub, 11, 1,
534 ("after pressing 'S'."));
539 * Eat the confirmation packet from socket, if it
540 * has been sent by the AP. This only happens
541 * if we issued KnownAP scan via its ethernet
547 FD_SET(sockfd, &rfd);
548 if (select(sockfd + 1, &rfd, NULL, NULL, &tv) > 0)
549 recv(sockfd, message, 65, 0);
551 print_help("Now, you can try pressing 'S' repeatedly "
552 "to watch the progress.");
562 sprintf(message, "%s%c", VIEW, ap_viewtype + '0');
563 print_top(message, KNOWN_APS);
566 print_help(WAIT_RET);
572 if (needs_opmode_restore) {
573 print_help(WAIT_SET);
574 varbinds[0].oid = bridgeOperationalMode;
575 varbinds[0].len_oid = sizeof(bridgeOperationalMode);
576 varbinds[0].value = (char *) &bridge_mode;
577 varbinds[0].len_val = 1;
578 varbinds[0].type = INT_VALUE;
579 if (snmp(varbinds, 1, SET) <= 0) {
580 print_helperr(ERR_RET);
585 print_helperr(ERR_RET);
594 print_top(NULL, NULL);