]> git.decadent.org.uk Git - ap-utils.git/blob - lib/common.c
Imported Upstream version 1.5
[ap-utils.git] / lib / common.c
1 /*
2  *      common.c from Access Point SNMP Utils for Linux
3  *
4  * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
5  * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <menu.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include "ap-utils.h"
31
32 #define APIP _("Access Point IP-address: ")
33 #define APPASS _("Password (community): ")
34 #define AUTODETECT _("Autodetect AP MIB properties? ")
35 #define APTYPE _("AP MIB type: ")
36 #define APVENDOREXT _("AP MIB vendor extensions: ")
37 #define WANT_SYS_APLABEL _("Do you want to use AP's name as its label? ")
38 #define APLABEL _("Access Point label: ")
39 #define SAVESETTINGS _("Save connect-settings: ")
40 #define POLL_I _("[P] Polling mode interval (tenths of second): ")
41 #define POLL_HELP _("P - change polling mode interval; Q - quit to menu")
42
43 char *ap_types[] = {
44     "ATMEL410",
45     "NWN",
46     "ATMEL12350"
47 };
48
49 char *ap_vendorexts[][3] = {
50     { "NONE", "SBRIDGES" },             /* ATMEL410 exts */
51     { "NONE" },                         /* NWN exts */
52     { "NONE", "GEMTEK", "EZYNET" },     /* ATMEL12350 exts */
53     { 0 }                               /* do not delete! */
54 };
55
56 rdprops regdom_types[] = {
57     { 0x10, "FCC (USA)", 1, 11 },
58     { 0x20, "DOC (Canada)", 1, 11 },
59     { 0x30, "ETSI (Europe)", 1, 13 },
60     { 0x31, "Spain", 10, 2 },
61     { 0x32, "France", 10, 4 },
62     { 0x40, "MKK (Japan)", 14, 1 },
63     { 0x41, "MKK1 (Japan)", 1, 14 },
64     { 0x42, "Israel", 3, 7 },
65     { 0x00, "unknown", 1, 14 }  /* hopefully 0x00 is not taken by any? */
66 };
67
68 char *channels[] = {
69     "01", "02", "03", "04", "05", "06", "07",
70     "08", "09", "10", "11", "12", "13", "14"
71 };
72
73 extern WINDOW *main_sub;
74 extern char *community, *prog_title;
75 extern struct in_addr ap_ip;
76
77 short ap_type, ap_vendorext;
78 int poll_delay = 10;
79
80 void about()
81 {
82     int nrow = 14, ncol = 47, brow = (LINES - 5 - nrow) / 2, bcol =
83         (COLS - MCOLS - 2 - ncol) / 2, i;
84     char message[100];
85
86     noecho();
87     curs_set(0);
88
89     print_top(NULL, _("About"));
90
91     /* drawing the box */
92     mvwaddch(main_sub, brow, bcol, ACS_ULCORNER);
93     mvwaddch(main_sub, brow, bcol + ncol, ACS_URCORNER);
94     mvwaddch(main_sub, brow + nrow, bcol, ACS_LLCORNER);
95     mvwaddch(main_sub, brow + nrow, bcol + ncol, ACS_LRCORNER);
96     for (i = 1; i < ncol; i++) {
97         mvwaddch(main_sub, brow, bcol + i, ACS_HLINE);
98         mvwaddch(main_sub, brow + nrow, bcol + i, ACS_HLINE);
99     }
100     for (i = 1; i < nrow; i++) {
101         mvwaddch(main_sub, brow + i, bcol, ACS_VLINE);
102         mvwaddch(main_sub, brow + i, bcol + ncol, ACS_VLINE);
103     }
104
105     mvwaddstr(main_sub, brow + 1, bcol + 2, prog_title);
106     sprintf(message, _("From %s"), TITLE);
107     mvwaddstr(main_sub, brow + 2, bcol + 2, message);
108     sprintf(message, _("Version %s"), VERSION);
109     mvwaddstr(main_sub, brow + 3, bcol + 2, message);
110     mvwaddstr(main_sub, brow + 5, bcol + 2,
111         _("Written by Roman Festchook roma@polesye.net"));
112     mvwaddstr(main_sub, brow + 6, bcol + 2,
113         _("and Jan Rafaj jr-aputils@cedric.unob.cz"));
114     mvwaddstr(main_sub, brow + 7, bcol + 2,
115         _("Copyright (c) 2001-2005"));
116     mvwaddstr(main_sub, brow + 8, bcol + 2,
117         _("Roman Festchook and Jan Rafaj"));
118     mvwaddstr(main_sub, brow + 9, bcol + 2, "http://ap-utils.polesye.net/");
119     mvwaddstr(main_sub, brow + 11, bcol + 2,
120         _("This program is distributed under the terms"));
121     mvwaddstr(main_sub, brow +12, bcol + 2,
122         _("of the GNU General Public License version 2."));
123     mvwaddstr(main_sub, brow + 13, bcol + 2,
124         _("See the included COPYING file for details."));
125
126     wrefresh(main_sub);
127
128     print_help(ANY_KEY);
129     getch();
130     print_help("");
131     print_top(NULL, NULL);
132     clear_main(0);
133     return;
134 }
135
136 void connect_options(unsigned long int ip, int type)
137 {
138     /*
139      * operAccessPointName OIDs used to retrieve AP NAME [in order of
140      * corresponding AP MIB types: ATMEL410, NWN, ATMEL12350]
141      */
142     char operAccessPointName[3][12] = {
143       {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x0A, 0x00},
144       {0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x05, 0x00},
145       {0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x01, 0x0A, 0x00}
146     };
147
148     extern int atmel410_filter; /* boolean; = 1 if we call from ap-gl utility */
149     unsigned char message[256];
150     unsigned char label[17];
151     int fd, i;
152     char *home_dir;
153     char save_settings=1;
154     varbind varbinds[1];
155
156     if (reopen_sockfd() == -1) {
157         print_helperr(ERR_SOCKET);
158         getch();
159         goto exit;
160     }
161
162     noecho();
163     curs_set(0);
164
165     print_top(NULL, _("Connect options"));
166
167 get_all_again:
168     mvwaddstr(main_sub, 1, 1, APIP);
169     if (ip) {
170         ap_ip.s_addr = ip;
171         mvwaddstr(main_sub, 1, 1 + strlen(APIP), inet_ntoa(ap_ip));
172     } else {
173         print_help(_("Enter IP address of your Access Point."));
174         get_ip(&ap_ip, 1, 1 + strlen(APIP), NULL);
175     }
176
177     mvwaddstr(main_sub, 2, 1, APPASS);
178
179     i = 0;
180     print_help("");
181
182     print_help(_("Entered characters will not be displayed "
183                  "for security reason."));
184     get_pass(message, 2, 1 + strlen(APPASS), 16);
185     if (community)
186         free(community);
187     i = strlen(message) + 1;
188     community = (char *) malloc(i);
189     strncpy(community, message, i);
190
191     if (type && !atmel410_filter) {
192         /* entered from ap_search() */
193
194         /* community already exists */
195 /*      wattrset(main_sub, A_BOLD);
196         for(i = 0; community[i++]; waddch(main_sub, '*'));
197         wattrset(main_sub, A_NORMAL);
198 */
199         ap_type = --type;
200
201         print_menusel(3, 1, APTYPE, ap_types[ap_type]);
202
203         /* well, we already know the MIB type, but lets find out MIB ext */
204         get_mib_details();
205
206         /* marks that we want offer AP name -> AP label later */
207         i = 1;
208
209         mvwaddstr(main_sub, 4, 1, APVENDOREXT);
210     } else {
211         if (atmel410_filter) {
212             ap_type = --type;
213             print_menusel(3, 1, APTYPE, ap_types[ap_type]);
214             ap_vendorext = NONE; /* no need to choose here, really */
215             /* marks that we want offer AP name -> AP label later */
216             i = 1;
217             mvwaddstr(main_sub, 4, 1, APVENDOREXT);
218         } else {
219             mvwaddstr(main_sub, 3, 1, AUTODETECT);
220             wrefresh(main_sub);
221             i = yes_no(3, 1 + strlen(AUTODETECT));
222             clear_main_new(3, 4);
223             mvwaddstr(main_sub, 3, 1, APTYPE);
224             if (i == 2) { /* NO */
225                 wrefresh(main_sub);
226                 ap_type = menu_choose(3, 1 + strlen(APTYPE), ap_types, 3);
227                 print_bold(main_sub, ap_types[ap_type]);
228                 mvwaddstr(main_sub, 4, 1, APVENDOREXT);
229                 wrefresh(main_sub);
230                 for (i = 0; ap_vendorexts[ap_type][i]; i++);
231                 if (i == 1)
232                     ap_vendorext = NONE; /* no need to choose here, really */
233                 else
234                     ap_vendorext = menu_choose(4, 1 + strlen(APVENDOREXT),
235                     ap_vendorexts[ap_type], i);
236             } else { /* YES */
237                 if (get_mib_details() == -1) {
238                     clear_main_new(1, 4);
239                     goto get_all_again;
240                 }
241                 print_bold(main_sub, ap_types[ap_type]);
242                 mvwaddstr(main_sub, 4, 1, APVENDOREXT);
243             }
244         }
245     }
246     print_bold(main_sub, ap_vendorexts[ap_type][ap_vendorext]);
247
248     print_help(
249         _("This label will be stored on HDD (independently on AP name!)."));
250     if (i == 1) {
251         /*
252          * (being called from ap_search()) or (YES for AP type autodetection)
253          * => offer possibility to use AP's name as the label
254          */
255         mvwaddstr(main_sub, 5, 1, WANT_SYS_APLABEL);
256         wrefresh(main_sub);
257         if (yes_no(5, 1 + strlen(WANT_SYS_APLABEL)) == 1) { /* YES */
258             varbinds[0].oid = operAccessPointName[ap_type];
259             varbinds[0].len_oid = (ap_type == NWN ?
260                 8 : sizeof(operAccessPointName[ap_type]));
261             varbinds[0].type = NULL_VALUE;
262             varbinds[0].len_val = 0;
263
264             print_help(WAIT_RET);
265             if (snmp(varbinds, i, GET) <= 0) {
266                 print_helperr(ERR_RET);
267                 getch();
268             } else {
269                 clear_main_new(5, 6);
270                 mvwaddstr(main_sub, 5, 1, APLABEL);
271                 wattrset(main_sub, A_BOLD);
272                 for (i = 0; i < varbinds[0].len_val && i < 16 &&
273                      *(varbinds[0].value + i); i++) {
274                     label[i] = *(varbinds[0].value + i);
275                     waddch(main_sub, label[i]);
276                 }
277                 label[i] = '\0';
278                 wattrset(main_sub, A_NORMAL);
279                 if (strlen(varbinds[0].value) > 16) {
280                     print_helperr("Warning! AP LABEL truncated to first 16 characters of AP NAME. Press any key.");
281                     getch();
282                 }
283             }
284             print_help("");
285             i = -1;
286         }
287     }
288
289     if (i != -1) { /* we have NOT been asked with WANT_SYS_APLABEL */
290         clear_main_new(5, 6);
291         mvwaddstr(main_sub, 5, 1, APLABEL);
292         get_value(message, 5, 1 + strlen(APLABEL), -sizeof(label), ANY_STRING,
293             0, 0, NULL);
294         strncpy(label, message, strlen(message) + 1);
295     }
296
297     mvwaddstr(main_sub, 6, 1, SAVESETTINGS);
298     wrefresh(main_sub);
299     save_settings = on_off(6, 1 + strlen(SAVESETTINGS));
300     clear_main_new(6, 7);
301     print_menusel(6, 1, SAVESETTINGS, (save_settings == 1) ? ON : OFF);
302
303     print_bottom(inet_ntoa(ap_ip));
304
305     if(save_settings == 1) {
306         if ((home_dir = getenv("HOME"))) {
307             sprintf(message, "%s/.ap-config", home_dir);
308             if ((fd = open(message, O_CREAT|O_WRONLY|O_APPEND, 0600)) != -1) {
309                 sprintf(message, "%s:%s:%s:%d:%d\n", inet_ntoa(ap_ip),
310                     community, label, ap_type, ap_vendorext);
311                 write(fd, message, strlen(message));
312                 close(fd);
313                 wbkgd(main_sub, A_NORMAL);
314                 wrefresh(main_sub);
315                 print_help(DONE_WRITING_APCONF);
316             } else
317                 print_helperr(ERR_WRITING_APCONF);
318
319             getch();
320         }
321     }
322   exit:
323     print_help("");
324     print_top(NULL, NULL);
325     clear_main(0);
326     return;
327 }
328
329 /*
330  * Determines AP MIB type (fills ap_type global), and AP MIB vendor extensions
331  * (fills ap_vendorext global). Returns with -1 on error or 0
332  * if everything is OK.
333  */
334 int get_mib_details()
335 {
336     char sysDescr_NWN[] = {
337         0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00
338     };
339     char sysDescr_ATMEL[] = {
340         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x01, 0x00
341     };
342     /*
343      * ATMEL410: SMARTBRIDGES MIB define this with length 4 (IpAddress); others
344      * (hopefully) do not define this but eventually return (hopefully)
345      * different value than 4.
346      */
347     char AuthRadiusIP_ATMEL[] = {
348         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x03, 0x00
349     };
350     /* ATMEL12350: GEMTEK and EZYNET MIBs define length 160, others 92 or 128 */
351     char sysDeviceInfo_ATMEL[] = {
352         0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x01, 0x01, 0x05, 0x00
353     };
354     /* ATMEL12350: EZYNET MIB defines length 104, others 88 */
355     char wirelessStatistics_ATMEL[] = {
356         0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x03, 0x01, 0x00
357     };
358
359     varbind varbinds[2];
360     int i;
361
362     print_help(_("Trying to probe AP for MIB properties. Please wait..."));
363
364     /* first, determine the private MIB types according to enterprises ID */
365     varbinds[0].oid = sysDescr_NWN;
366     varbinds[0].len_oid = sizeof(sysDescr_NWN);
367     varbinds[0].value = NULL;
368     varbinds[0].len_val = 0;
369     varbinds[0].type = NULL_VALUE;
370     if (snmp(varbinds, 1, GET) > 0) {
371         ap_type = NWN;
372     } else {
373         varbinds[0].oid = sysDescr_ATMEL;
374         varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
375         varbinds[0].value = NULL;
376         varbinds[0].len_val = 0;
377         varbinds[0].type = NULL_VALUE;
378         if (snmp(varbinds, 1, GET) > 0) {
379             ap_type = ATMEL410;
380         } else {
381             sysDescr_ATMEL[5] = 0xE0;
382             sysDescr_ATMEL[6] = 0x3E;
383             varbinds[0].oid = sysDescr_ATMEL;
384             varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
385             varbinds[0].value = NULL;
386             varbinds[0].len_val = 0;
387             varbinds[0].type = NULL_VALUE;
388             if (snmp(varbinds, 1, GET) > 0) {
389                 ap_type = ATMEL12350;
390             } else {
391                 print_helperr(_("Unable to determine AP MIB properties "
392                     "(no response from AP). Press any key."));
393                 getch();
394                 return -1;
395             }
396         }
397     }
398
399     /*
400      * It is best to do the following HERE and FOR ONCE ONLY: find out more
401      * about specific MIB vendor extensions - we'll check against them
402      * on different places later.
403      */
404
405     ap_vendorext = NONE;
406
407     if (ap_type == ATMEL410) {
408         varbinds[0].oid = AuthRadiusIP_ATMEL;
409         varbinds[0].len_oid = sizeof(AuthRadiusIP_ATMEL);
410         varbinds[0].value = NULL;
411         varbinds[0].len_val = 0;
412         varbinds[0].type = NULL_VALUE;
413
414         i = snmp(varbinds, 1, GET);
415         if (i < 0) {
416             print_helperr(ERR_RET);
417             getch();
418             return -1;
419         }
420
421         /*
422          * i == 0 => 'no such variable in the MIB' returned =>
423          * consider 'ap_vendorext = NONE' too.
424          */
425
426         if (varbinds[0].len_val == 4)
427             ap_vendorext = SBRIDGES;
428     }
429
430     if (ap_type == ATMEL12350) {
431         varbinds[0].oid = sysDeviceInfo_ATMEL;
432         varbinds[0].len_oid = sizeof(sysDeviceInfo_ATMEL);
433         varbinds[0].value = NULL;
434         varbinds[0].len_val = 0;
435         varbinds[0].type = NULL_VALUE;
436         varbinds[1].oid = wirelessStatistics_ATMEL;
437         varbinds[1].len_oid = sizeof(wirelessStatistics_ATMEL);
438         varbinds[1].value = NULL;
439         varbinds[1].len_val = 0;
440         varbinds[1].type = NULL_VALUE;
441
442         if (snmp(varbinds, 2, GET) <= 0) {
443             print_helperr(ERR_RET);
444             getch();
445             return -1;
446         }
447
448         if (varbinds[0].len_val == 160)
449             ap_vendorext = GEMTEK;
450
451         if (varbinds[1].len_val == 104)
452             ap_vendorext = EZYNET;
453     }
454
455     return 0;
456 }
457
458 void exit_program()
459 {
460     erase();
461     refresh();
462     endwin();
463     exit(0);
464 }
465
466 void exit_shell()
467 {
468     def_prog_mode();
469     endwin();
470     system("sh");
471     curs_set(0);
472     refresh();
473 }
474
475 /*
476  * Sets different-than-default (1 sec.) polling interval for polling-active
477  * modes, from interval <0.1;86400> seconds.
478  * poll_delay is natively in tenths of second.
479  */
480 void polling_interval()
481 {
482     unsigned char message[256];
483     int c = 0;
484
485     noecho();
486     print_help(POLL_HELP);
487
488     while (1) {
489         sprintf(message, _("%s%u"), POLL_I, poll_delay);
490         mvwaddstr(main_sub, 0, 0, message);
491         sprintf(message, _("(%0.1f seconds)"), (float) poll_delay / 10);
492         mvwaddstr(main_sub, 1, strlen(POLL_I), message);
493         wrefresh(main_sub);
494         c = getch();
495         switch (c) {
496             case 'P':
497             case 'p':
498                 get_value(message, 0, strlen(POLL_I), 7, INT_STRING, 1, 864000,
499                     POLL_HELP);
500                 poll_delay = atoi(message);
501                 clear_main_new(0, 2);
502                 break;
503             case 'Q':
504             case 'q':
505                 goto quit;
506         }
507     }
508
509 quit:
510     print_help("");
511     clear_main(0);
512     return;
513 }
514
515 /*
516  * Expects regulatory domain code on input and returns index of a corresponding
517  * regdom_types[] member, that describes the given regulatory domain properties.
518  */
519 int regdom_idx(char regdom)
520 {
521     int i;
522
523     for (i = 0; &regdom_types[i]; i++)
524         if (regdom_types[i].code == regdom)
525             return i;
526
527     return i;
528 }