]> git.decadent.org.uk Git - ap-utils.git/blob - lib/common.c
Imported Upstream version 1.5.1~pre3
[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-2006"));
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     wrefresh(main_sub);
170     
171     if (ip) {
172         ap_ip.s_addr = ip;
173         mvwaddstr(main_sub, 1, 1 + strlen(APIP), inet_ntoa(ap_ip));
174     } else {
175         print_help(_("Enter IP address of your Access Point."));
176         get_ip(&ap_ip, 1, 1 + strlen(APIP), NULL);
177     }
178
179     mvwaddstr(main_sub, 2, 1, APPASS);
180
181     i = 0;
182     print_help("");
183
184     print_help(_("Entered characters will not be displayed "
185                  "for security reasons."));
186     get_pass(message, 2, 1 + strlen(APPASS), 16);
187     if (community)
188         free(community);
189     i = strlen(message) + 1;
190     community = (char *) malloc(i);
191     strncpy(community, message, i);
192
193     if (type && !atmel410_filter) {
194         /* entered from ap_search() */
195
196         /* community already exists */
197 /*      wattrset(main_sub, A_BOLD);
198         for(i = 0; community[i++]; waddch(main_sub, '*'));
199         wattrset(main_sub, A_NORMAL);
200 */
201         ap_type = --type;
202
203         print_menusel(3, 1, APTYPE, ap_types[ap_type]);
204
205         /* well, we already know the MIB type, but lets find out MIB ext */
206         get_mib_details();
207
208         /* marks that we want offer AP name -> AP label later */
209         i = 1;
210
211         mvwaddstr(main_sub, 4, 1, APVENDOREXT);
212     } else {
213         if (atmel410_filter) {
214             ap_type = --type;
215             print_menusel(3, 1, APTYPE, ap_types[ap_type]);
216             ap_vendorext = NONE; /* no need to choose here, really */
217             /* marks that we want offer AP name -> AP label later */
218             i = 1;
219             mvwaddstr(main_sub, 4, 1, APVENDOREXT);
220         } else {
221             mvwaddstr(main_sub, 3, 1, AUTODETECT);
222             wrefresh(main_sub);
223             i = yes_no(3, 1 + strlen(AUTODETECT));
224             clear_main_new(3, 4);
225             mvwaddstr(main_sub, 3, 1, APTYPE);
226             if (i == 2) { /* NO */
227                 wrefresh(main_sub);
228                 ap_type = menu_choose(3, 1 + strlen(APTYPE), ap_types, 3);
229                 print_bold(main_sub, ap_types[ap_type]);
230                 mvwaddstr(main_sub, 4, 1, APVENDOREXT);
231                 wrefresh(main_sub);
232                 for (i = 0; ap_vendorexts[ap_type][i]; i++);
233                 if (i == 1)
234                     ap_vendorext = NONE; /* no need to choose here, really */
235                 else
236                     ap_vendorext = menu_choose(4, 1 + strlen(APVENDOREXT),
237                     ap_vendorexts[ap_type], i);
238             } else { /* YES */
239                 if (get_mib_details() == -1) {
240                     clear_main_new(1, 4);
241                     goto get_all_again;
242                 }
243                 print_bold(main_sub, ap_types[ap_type]);
244                 mvwaddstr(main_sub, 4, 1, APVENDOREXT);
245             }
246         }
247     }
248     print_bold(main_sub, ap_vendorexts[ap_type][ap_vendorext]);
249
250     print_help(
251         _("This label will be stored on HDD (independently on AP name!)."));
252     if (i == 1) {
253         /*
254          * (being called from ap_search()) or (YES for AP type autodetection)
255          * => offer possibility to use AP's name as the label
256          */
257         mvwaddstr(main_sub, 5, 1, WANT_SYS_APLABEL);
258         wrefresh(main_sub);
259         if (yes_no(5, 1 + strlen(WANT_SYS_APLABEL)) == 1) { /* YES */
260             varbinds[0].oid = operAccessPointName[ap_type];
261             varbinds[0].len_oid = (ap_type == NWN ?
262                 8 : sizeof(operAccessPointName[ap_type]));
263             varbinds[0].type = NULL_VALUE;
264             varbinds[0].len_val = 0;
265
266             print_help(WAIT_RET);
267             if (snmp(varbinds, i, GET) <= 0) {
268                 print_helperr(ERR_RET);
269                 getch();
270             } else {
271                 clear_main_new(5, 6);
272                 mvwaddstr(main_sub, 5, 1, APLABEL);
273                 wattrset(main_sub, A_BOLD);
274                 for (i = 0; i < varbinds[0].len_val && i < 16 &&
275                      *(varbinds[0].value + i); i++) {
276                     label[i] = *(varbinds[0].value + i);
277                     waddch(main_sub, label[i]);
278                 }
279                 label[i] = '\0';
280                 wattrset(main_sub, A_NORMAL);
281                 if (strlen(varbinds[0].value) > 16) {
282                     print_helperr("Warning! AP LABEL truncated to first 16 characters of AP NAME. Press any key.");
283                     getch();
284                 }
285             }
286             print_help("");
287             i = -1;
288         }
289     }
290
291     if (i != -1) { /* we have NOT been asked with WANT_SYS_APLABEL */
292         clear_main_new(5, 6);
293         mvwaddstr(main_sub, 5, 1, APLABEL);
294         wrefresh(main_sub);
295         get_value(message, 5, 1 + strlen(APLABEL), -sizeof(label), ANY_STRING,
296             0, 0, NULL);
297         strncpy(label, message, strlen(message) + 1);
298     }
299
300     mvwaddstr(main_sub, 6, 1, SAVESETTINGS);
301     wrefresh(main_sub);
302     save_settings = on_off(6, 1 + strlen(SAVESETTINGS));
303     clear_main_new(6, 7);
304     print_menusel(6, 1, SAVESETTINGS, (save_settings == 1) ? ON : OFF);
305
306     print_bottom(inet_ntoa(ap_ip));
307
308     if(save_settings == 1) {
309         if ((home_dir = getenv("HOME"))) {
310             sprintf(message, "%s/.ap-config", home_dir);
311             if ((fd = open(message, O_CREAT|O_WRONLY|O_APPEND, 0600)) != -1) {
312                 sprintf(message, "%s:%s:%s:%d:%d\n", inet_ntoa(ap_ip),
313                     community, label, ap_type, ap_vendorext);
314                 write(fd, message, strlen(message));
315                 close(fd);
316                 wbkgd(main_sub, A_NORMAL);
317                 wrefresh(main_sub);
318                 print_help(DONE_WRITING_APCONF);
319             } else
320                 print_helperr(ERR_WRITING_APCONF);
321
322             getch();
323         }
324     }
325   exit:
326     print_help("");
327     print_top(NULL, NULL);
328     clear_main(0);
329     return;
330 }
331
332 /*
333  * Determines AP MIB type (fills ap_type global), and AP MIB vendor extensions
334  * (fills ap_vendorext global). Returns with -1 on error or 0
335  * if everything is OK.
336  */
337 int get_mib_details()
338 {
339     char sysDescr_NWN[] = {
340         0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00
341     };
342     char sysDescr_ATMEL[] = {
343         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x01, 0x00
344     };
345     /*
346      * ATMEL410: SMARTBRIDGES MIB define this with length 4 (IpAddress); others
347      * (hopefully) do not define this but eventually return (hopefully)
348      * different value than 4.
349      */
350     char AuthRadiusIP_ATMEL[] = {
351         0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x03, 0x00
352     };
353     /* ATMEL12350: GEMTEK and EZYNET MIBs define length 160, others 92 or 128 */
354     char sysDeviceInfo_ATMEL[] = {
355         0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x01, 0x01, 0x05, 0x00
356     };
357     /* ATMEL12350: EZYNET MIB defines length 104, others 88 */
358     char wirelessStatistics_ATMEL[] = {
359         0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x03, 0x01, 0x00
360     };
361
362     varbind varbinds[2];
363     int i;
364
365     print_help(_("Trying to probe AP for MIB properties. Please wait..."));
366
367     /* first, determine the private MIB types according to enterprises ID */
368     varbinds[0].oid = sysDescr_NWN;
369     varbinds[0].len_oid = sizeof(sysDescr_NWN);
370     varbinds[0].value = NULL;
371     varbinds[0].len_val = 0;
372     varbinds[0].type = NULL_VALUE;
373     if (snmp(varbinds, 1, GET) > 0) {
374         ap_type = NWN;
375     } else {
376         varbinds[0].oid = sysDescr_ATMEL;
377         varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
378         varbinds[0].value = NULL;
379         varbinds[0].len_val = 0;
380         varbinds[0].type = NULL_VALUE;
381         if (snmp(varbinds, 1, GET) > 0) {
382             ap_type = ATMEL410;
383         } else {
384             sysDescr_ATMEL[5] = 0xE0;
385             sysDescr_ATMEL[6] = 0x3E;
386             varbinds[0].oid = sysDescr_ATMEL;
387             varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
388             varbinds[0].value = NULL;
389             varbinds[0].len_val = 0;
390             varbinds[0].type = NULL_VALUE;
391             if (snmp(varbinds, 1, GET) > 0) {
392                 ap_type = ATMEL12350;
393             } else {
394                 print_helperr(_("Unable to determine AP MIB properties "
395                     "(no response from AP). Press any key."));
396                 getch();
397                 return -1;
398             }
399         }
400     }
401
402     /*
403      * It is best to do the following HERE and FOR ONCE ONLY: find out more
404      * about specific MIB vendor extensions - we'll check against them
405      * on different places later.
406      */
407
408     ap_vendorext = NONE;
409
410     if (ap_type == ATMEL410) {
411         varbinds[0].oid = AuthRadiusIP_ATMEL;
412         varbinds[0].len_oid = sizeof(AuthRadiusIP_ATMEL);
413         varbinds[0].value = NULL;
414         varbinds[0].len_val = 0;
415         varbinds[0].type = NULL_VALUE;
416
417         i = snmp(varbinds, 1, GET);
418         if (i < 0) {
419             print_helperr(ERR_RET);
420             getch();
421             return -1;
422         }
423
424         /*
425          * i == 0 => 'no such variable in the MIB' returned =>
426          * consider 'ap_vendorext = NONE' too.
427          */
428
429         if (varbinds[0].len_val == 4)
430             ap_vendorext = SBRIDGES;
431     }
432
433     if (ap_type == ATMEL12350) {
434         varbinds[0].oid = sysDeviceInfo_ATMEL;
435         varbinds[0].len_oid = sizeof(sysDeviceInfo_ATMEL);
436         varbinds[0].value = NULL;
437         varbinds[0].len_val = 0;
438         varbinds[0].type = NULL_VALUE;
439         varbinds[1].oid = wirelessStatistics_ATMEL;
440         varbinds[1].len_oid = sizeof(wirelessStatistics_ATMEL);
441         varbinds[1].value = NULL;
442         varbinds[1].len_val = 0;
443         varbinds[1].type = NULL_VALUE;
444
445         if (snmp(varbinds, 2, GET) <= 0) {
446             print_helperr(ERR_RET);
447             getch();
448             return -1;
449         }
450
451         if (varbinds[0].len_val == 160)
452             ap_vendorext = GEMTEK;
453
454         if (varbinds[1].len_val == 104)
455             ap_vendorext = EZYNET;
456     }
457
458     return 0;
459 }
460
461 void exit_program()
462 {
463     erase();
464     refresh();
465     endwin();
466     exit(0);
467 }
468
469 void exit_shell()
470 {
471     def_prog_mode();
472     endwin();
473     system("sh");
474     curs_set(0);
475     refresh();
476 }
477
478 /*
479  * Sets different-than-default (1 sec.) polling interval for polling-active
480  * modes, from interval <0.1;86400> seconds.
481  * poll_delay is natively in tenths of second.
482  */
483 void polling_interval()
484 {
485     unsigned char message[256];
486     int c = 0;
487
488     noecho();
489     print_help(POLL_HELP);
490
491     while (1) {
492         sprintf(message, "%s%u", POLL_I, poll_delay);
493         mvwaddstr(main_sub, 0, 0, message);
494         sprintf(message, _("(%0.1f seconds)"), (float) poll_delay / 10);
495         mvwaddstr(main_sub, 1, strlen(POLL_I), message);
496         wrefresh(main_sub);
497         c = getch();
498         switch (c) {
499             case 'P':
500             case 'p':
501                 get_value(message, 0, strlen(POLL_I), 7, INT_STRING, 1, 864000,
502                     POLL_HELP);
503                 poll_delay = atoi(message);
504                 clear_main_new(0, 2);
505                 break;
506             case 'Q':
507             case 'q':
508                 goto quit;
509         }
510     }
511
512 quit:
513     print_help("");
514     clear_main(0);
515     return;
516 }
517
518 /*
519  * Expects regulatory domain code on input and returns index of a corresponding
520  * regdom_types[] member, that describes the given regulatory domain properties.
521  */
522 int regdom_idx(char regdom)
523 {
524     int i;
525
526     for (i = 0; &regdom_types[i]; i++)
527         if (regdom_types[i].code == regdom)
528             return i;
529
530     return i;
531 }