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