]> git.decadent.org.uk Git - ap-utils.git/blobdiff - lib/common.c
Imported Upstream version 1.5~pre1
[ap-utils.git] / lib / common.c
index 16f342dc00ce196228d3eb64eaee2165efa4355f..9c3b4bec7a3d36203a42594fb9c153aa6423a014 100644 (file)
 #include <sys/ioctl.h>
 #include "ap-utils.h"
 
-#define AUTODETECT _("Autodetect AP type? ")
 #define APIP _("Access Point IP-address: ")
 #define APPASS _("Password (community): ")
-#define APTYPE _("AP type: ")
+#define AUTODETECT _("Autodetect AP MIB properties? ")
+#define APTYPE _("AP MIB type: ")
+#define APVENDOREXT _("AP MIB vendor extensions: ")
+#define WANT_SYS_APLABEL _("Do you want to use AP's name as its label? ")
+#define APLABEL _("Access Point label: ")
 #define SAVESETTINGS _("Save connect-settings: ")
 
+char *ap_types[] = {
+    "ATMEL410",
+    "NWN",
+    "ATMEL12350"
+};
+
+char *ap_vendorexts[][3] = {
+    { "NONE", "SBRIDGES" },            /* ATMEL410 exts */
+    { "NONE" },                                /* NWN exts */
+    { "NONE", "TELLUS", "VERNET" }     /* ATMEL12350 exts */
+};
+
+rdprops regdom_types[] = {
+    { 0x10, "FCC (USA)", 1, 11 },
+    { 0x20, "DOC (Canada)", 1, 11 },
+    { 0x30, "ETSI (Europe)", 1, 13 },
+    { 0x31, "Spain", 10, 2 },
+    { 0x32, "France", 10, 4 },
+    { 0x40, "MKK (Japan)", 14, 1 },
+    { 0x41, "MKK1 (Japan)", 1, 14 },
+    { 0x42, "Israel", 3, 7 },
+    { 0x00, "unknown", 1, 14 } /* hopefully 0x00 is not taken by any? */
+};
+
+char *channels[] = {
+    "01", "02", "03", "04", "05", "06", "07",
+    "08", "09", "10", "11", "12", "13", "14"
+};
+
 extern WINDOW *main_sub;
 extern char *community, *prog_title;
-extern short ap_type;
+short ap_type, ap_vendorext;
 extern int sockfd;
 extern struct in_addr ap_ip;
-extern char *ap_types[];
 
 void about()
 {
-    int nrow = 12, ncol = 47, brow = (LINES - 4 - nrow) / 2, bcol =
+    int nrow = 14, ncol = 47, brow = (LINES - 5 - nrow) / 2, bcol =
        (COLS - MCOLS - 2 - ncol) / 2, i;
     char message[100];
 
     noecho();
     curs_set(0);
 
-    print_title(_("About"));
+    print_top(NULL, _("About"));
 
     /* drawing the box */
     mvwaddch(main_sub, brow, bcol, ACS_ULCORNER);
@@ -73,13 +104,17 @@ void about()
     mvwaddstr(main_sub, brow + 5, bcol + 2,
              _("Written by Roman Festchook roma@polesye.net"));
     mvwaddstr(main_sub, brow + 6, bcol + 2,
-             _("Copyright (c) Roman Festchook 2001-2004"));
-    mvwaddstr(main_sub, brow + 7, bcol + 2, "http://ap-utils.polesye.net/");
-    mvwaddstr(main_sub, brow + 9, bcol + 2,
+             _("Portions by Jan Rafaj aputils@cedric.unob.cz"));
+    mvwaddstr(main_sub, brow + 7, bcol + 2,
+             _("Copyright (c) 2001-2004"));
+    mvwaddstr(main_sub, brow + 8, bcol + 2,
+             _("Roman Festchook and Jan Rafaj"));
+    mvwaddstr(main_sub, brow + 9, bcol + 2, "http://ap-utils.polesye.net/");
+    mvwaddstr(main_sub, brow + 11, bcol + 2,
              _("This program is distributed under the terms"));
-    mvwaddstr(main_sub, brow +10, bcol + 2,
+    mvwaddstr(main_sub, brow +12, bcol + 2,
              _("of the GNU General Public License version 2."));
-    mvwaddstr(main_sub, brow + 11, bcol + 2,
+    mvwaddstr(main_sub, brow + 13, bcol + 2,
              _("See the included COPYING file for details."));
 
 
@@ -88,27 +123,32 @@ void about()
     print_help(ANY_KEY);
     getch();
     print_help("");
-    print_title("");
+    print_top(NULL, NULL);
     clear_main(0);
     return;
 }
 
 void connect_options(unsigned long int ip, int type)
 {
-    int i;
+    /*
+     * operAccessPointName OIDs used to retrieve AP NAME [in order of
+     * corresponding AP MIB types: ATMEL410, NWN, ATMEL12350]
+     */
+    char operAccessPointName[3][12] = {
+      {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x01, 0x0A, 0x00},
+      {0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x05, 0x00},
+      {0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x01, 0x0A, 0x00}
+    };
+
     struct sockaddr_in client;
-    unsigned char message[16];
-    int fd;
+    extern int atmel410_filter; /* to check is this function called from ap-gl utility */
+    unsigned char message[256];
+    unsigned char label[17];
+    int fd, i;
     char *home_dir;
     char save_settings=1;
-    char sysDescr_NWN[] = { 0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00 };
-    char sysDescr_ATMEL410[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A,
-       0x01, 0x01, 0x01, 0x01, 0x00 };
-    char sysDescr_ATMEL12350[] = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E,
-       0x01, 0x01, 0x01, 0x01, 0x00 };
     varbind varbinds[1];
 
-
     memset(&client, 0, sizeof client);
     client.sin_family = AF_INET;
     client.sin_port = INADDR_ANY;
@@ -132,7 +172,7 @@ void connect_options(unsigned long int ip, int type)
     noecho();
     curs_set(0);
 
-    print_title(_("Connect options"));
+    print_top(NULL, _("Connect options"));
 
 get_all_again:
     mvwaddstr(main_sub, 1, 1, APIP);
@@ -145,80 +185,144 @@ get_all_again:
     }
 
     mvwaddstr(main_sub, 2, 1, APPASS);
-    print_help(_("Entered characters will not be displayed "
-       "for security reason."));
-    get_pass(message, 2, 1 + strlen(APPASS), 16);
-    if (community)
-       free(community);
-    i = strlen(message) + 1;
-    community = (char *) malloc(i);
-    strncpy(community, message, i);
 
+    i = 0;
     print_help("");
-    if (type) {
+
+       print_help(_("Entered characters will not be displayed "
+                    "for security reason."));
+       get_pass(message, 2, 1 + strlen(APPASS), 16);
+       if (community)
+           free(community);
+       i = strlen(message) + 1;
+       community = (char *) malloc(i);
+       strncpy(community, message, i);
+
+
+    if (type && ! atmel410_filter) {
+       /* entered from ap_search() */
+
+       /* community already exists */
+/*     wattrset(main_sub, A_BOLD);
+       for(i = 0; community[i++]; waddch(main_sub, '*'));
+       wattrset(main_sub, A_NORMAL);
+*/
        ap_type = --type;
-       mvwaddstr(main_sub, 3, 1, APTYPE);
+
+       print_menusel(3, 1, APTYPE, ap_types[ap_type]);
+
+       /* well, we already know the MIB type, but lets find out MIB ext */
+       get_mib_details();
+
+       /* marks that we want offer AP name -> AP label later */
+       i = 1;
+
+       mvwaddstr(main_sub, 4, 1, APVENDOREXT);
     } else {
-       mvwaddstr(main_sub, 3, 1, AUTODETECT);
-       wrefresh(main_sub);
-       i = yes_no(3, 1 + strlen(AUTODETECT));
-       clear_main_new(3, 4);
-       mvwaddstr(main_sub, 3, 1, APTYPE);
-       if (i == 2) { /* NO */
-           wrefresh(main_sub);
-           ap_type = menu_choose(3, 1 + strlen(APTYPE), ap_types, 3);
-       } else { /* YES */
-           print_help(_("Determining AP type. Please wait..."));
-           varbinds[0].oid = sysDescr_NWN;
-           varbinds[0].len_oid = sizeof(sysDescr_NWN);
-           varbinds[0].value = NULL;
-           varbinds[0].len_val = 0;
-           varbinds[0].type = NULL_VALUE;
-           if (snmp(varbinds, 1, GET) > 0) {
-               ap_type = NWN;
-           } else {
-               varbinds[0].oid = sysDescr_ATMEL410;
-               varbinds[0].len_oid = sizeof(sysDescr_ATMEL410);
-               varbinds[0].value = NULL;
-               varbinds[0].len_val = 0;
-               varbinds[0].type = NULL_VALUE;
-               if (snmp(varbinds, 1, GET) > 0) {
-                   ap_type = ATMEL410;
-               } else {
-                   varbinds[0].oid = sysDescr_ATMEL12350;
-                   varbinds[0].len_oid = sizeof(sysDescr_ATMEL12350);
-                   varbinds[0].value = NULL;
-                   varbinds[0].len_val = 0;
-                   varbinds[0].type = NULL_VALUE;
-                   if (snmp(varbinds, 1, GET) > 0) {
-                       ap_type = ATMEL12350;
-                   } else {
-                       print_helperr(_("Unable to determine AP type "
-                           "(no response). Press any key."));
-                       getch();
+
+       if (atmel410_filter) {
+               ap_type = --type;
+               print_menusel(3, 1, APTYPE, ap_types[ap_type]);
+               ap_vendorext = NONE; /* no need to choose here, really */
+               /* marks that we want offer AP name -> AP label later */
+               i = 1;
+               mvwaddstr(main_sub, 4, 1, APVENDOREXT);
+       } else {
+               mvwaddstr(main_sub, 3, 1, AUTODETECT);
+               wrefresh(main_sub);
+               i = yes_no(3, 1 + strlen(AUTODETECT));
+               clear_main_new(3, 4);
+               mvwaddstr(main_sub, 3, 1, APTYPE);
+               if (i == 2) { /* NO */
+                   char **p;
+    
+                   wrefresh(main_sub);
+
+                   ap_type = menu_choose(3, 1 + strlen(APTYPE), ap_types, 3);
+                   print_bold(main_sub, ap_types[ap_type]);
+
+                   mvwaddstr(main_sub, 4, 1, APVENDOREXT);
+                   wrefresh(main_sub);
+                   for (i = 0, p = ap_vendorexts[ap_type]; *p++; i++);
+                   if (i == 1)
+                       ap_vendorext = NONE; /* no need to choose here, really */
+                   else
+                       ap_vendorext = menu_choose(4, 1 + strlen(APVENDOREXT),
+                   ap_vendorexts[ap_type], i);
+               } else { /* YES */
+                   if (get_mib_details() == -1) {
                        clear_main_new(1, 4);
                        goto get_all_again;
                    }
+               print_bold(main_sub, ap_types[ap_type]);
+
+           mvwaddstr(main_sub, 4, 1, APVENDOREXT);
+       }
+    }
+    }
+    print_bold(main_sub, ap_vendorexts[ap_type][ap_vendorext]);
+
+    print_help(
+       _("This label will be stored on HDD (independently on AP name!)."));
+    if (i == 1) {
+       /*
+        * (being called from ap_search()) or (YES for AP type autodetection)
+        * => offer possibility to use AP's name as the label
+        */
+       mvwaddstr(main_sub, 5, 1, WANT_SYS_APLABEL);
+       wrefresh(main_sub);
+       if (yes_no(5, 1 + strlen(WANT_SYS_APLABEL)) == 1) { /* YES */
+           varbinds[0].oid = operAccessPointName[ap_type];
+           varbinds[0].len_oid = (ap_type == NWN ?
+               8 : sizeof(operAccessPointName[ap_type]));
+           varbinds[0].type = NULL_VALUE;
+           varbinds[0].len_val = 0;
+
+           print_help(WAIT_RET);
+           if (snmp(varbinds, i, GET) <= 0) {
+               print_helperr(ERR_RET);
+               getch();
+           } else {
+               clear_main_new(5, 6);
+               mvwaddstr(main_sub, 5, 1, APLABEL);
+               wattrset(main_sub, A_BOLD);
+               for (i = 0; i < varbinds[0].len_val && i < 16 &&
+                    *(varbinds[0].value + i); i++) {
+                   label[i] = *(varbinds[0].value + i);
+                   waddch(main_sub, label[i]);
+               }
+               label[++i] = '\0';
+               wattrset(main_sub, A_NORMAL);
+               if (strlen(varbinds[0].value) > 16) {
+                   print_helperr("Warning! AP LABEL truncated to first 16 characters of AP NAME. Press any key.");
+                   getch();
                }
            }
-       }                           
-       wattrset(main_sub, A_BOLD);
+           print_help("");
+           i = -1;
+       }
+    }
+
+    if (i != -1) { /* we have NOT been asked with WANT_SYS_APLABEL */
+       clear_main_new(5, 6);
+       mvwaddstr(main_sub, 5, 1, APLABEL);
+       get_value(message, 5, 1 + strlen(APLABEL), -sizeof(label), ANY_STRING,
+           0, 0, NULL);
+       strncpy(label, message, strlen(message) + 1);
     }
-    waddstr(main_sub, ap_types[ap_type]);
-    wattrset(main_sub, A_NORMAL);
 
-    mvwaddstr(main_sub, 4, 1, SAVESETTINGS);
+    mvwaddstr(main_sub, 6, 1, SAVESETTINGS);
     wrefresh(main_sub);
-    save_settings = on_off(4, 1 + strlen(SAVESETTINGS));
+    save_settings = on_off(6, 1 + strlen(SAVESETTINGS));
 
     print_bottom(inet_ntoa(ap_ip));
 
     if(save_settings == 1) {
        if ((home_dir = getenv("HOME"))) {
            sprintf(message, "%s/.ap-config", home_dir);
-           if ((fd = open(message, O_CREAT | O_WRONLY | O_APPEND, 0600)) != -1) {
-               sprintf(message, "%s:%s:%d\n", inet_ntoa(ap_ip),
-                   community, ap_type);
+           if ((fd = open(message, O_CREAT|O_WRONLY|O_APPEND, 0600)) != -1) {
+               sprintf(message, "%s:%s:%s:%d:%d\n", inet_ntoa(ap_ip),
+                   community, label, ap_type, ap_vendorext);
                write(fd, message, strlen(message));
                close(fd);
            }
@@ -226,11 +330,118 @@ get_all_again:
     }
   exit:
     print_help("");
-    print_title("");
+    print_top(NULL, NULL);
     clear_main(0);
     return;
 }
 
+/*
+ * Determines AP MIB type (fills ap_type), and AP MIB vendor extensions
+ * (changes values of ap_vendorext global). Returns with -1 on error or 0
+ * if everything is OK.
+ */
+int get_mib_details()
+{
+    char sysDescr_NWN[] = {
+       0x2B, 0x06, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00
+    };
+    char sysDescr_ATMEL[] = {
+       0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x01, 0x01, 0x00
+    };
+    char operEthernetAddress_ATMEL[] = {
+        0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x01, 0x02, 0x03, 0x00
+    };
+    char Wireless_ATMEL[] = {
+       0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x03, 0x01, 0x00
+    };
+    varbind varbinds[2];
+    char oui_sbridges[3] = { 0x00, 0x30, 0x1A };
+    char oui_tellus[3] = { 0x00, 0x04, 0xDB };
+
+    print_help(_("Trying to probe AP for MIB properties. Please wait..."));
+
+    /* first, determine the private MIB types according to enterprises ID */
+    varbinds[0].oid = sysDescr_NWN;
+    varbinds[0].len_oid = sizeof(sysDescr_NWN);
+    varbinds[0].value = NULL;
+    varbinds[0].len_val = 0;
+    varbinds[0].type = NULL_VALUE;
+    if (snmp(varbinds, 1, GET) > 0) {
+       ap_type = NWN;
+    } else {
+       varbinds[0].oid = sysDescr_ATMEL;
+       varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
+       varbinds[0].value = NULL;
+       varbinds[0].len_val = 0;
+       varbinds[0].type = NULL_VALUE;
+       if (snmp(varbinds, 1, GET) > 0) {
+           ap_type = ATMEL410;
+       } else {
+           sysDescr_ATMEL[5] = 0xE0;
+           sysDescr_ATMEL[6] = 0x3E;
+           varbinds[0].oid = sysDescr_ATMEL;
+           varbinds[0].len_oid = sizeof(sysDescr_ATMEL);
+           varbinds[0].value = NULL;
+           varbinds[0].len_val = 0;
+           varbinds[0].type = NULL_VALUE;
+           if (snmp(varbinds, 1, GET) > 0) {
+               ap_type = ATMEL12350;
+           } else {
+               print_helperr(_("Unable to determine AP MIB properties "
+                   "(no response from AP). Press any key."));
+               getch();
+               return -1;
+           }
+       }
+    }
+
+    /*
+     * It is best to do the following HERE and FOR ONCE ONLY: find out more
+     * about specific MIB modifications - we'll use them on different places
+     * later.
+     */
+    varbinds[0].type = NULL_VALUE;
+    varbinds[0].oid = operEthernetAddress_ATMEL;
+    varbinds[0].len_oid = sizeof(operEthernetAddress_ATMEL);
+    varbinds[0].len_val = 0;
+    varbinds[1].type = NULL_VALUE;
+    varbinds[1].oid = Wireless_ATMEL;
+    varbinds[1].len_oid = sizeof(Wireless_ATMEL);
+    varbinds[1].len_val = 0;
+    if (ap_type == ATMEL12350) {
+       operEthernetAddress_ATMEL[5] = 0xE0;
+       operEthernetAddress_ATMEL[6] = 0x3E;
+       Wireless_ATMEL[5] = 0xE0;
+       Wireless_ATMEL[6] = 0x3E;
+    }
+    if (snmp(varbinds, 2, GET) <= 0) {
+        print_helperr(ERR_RET);
+       getch();
+        return -1;
+    }
+
+    /*
+     * Detection of different vendor-modified ATMEL private MIBs.
+     * Note that results here are considered mutually exclusive, although
+     * MIBs *may* share a lot of properties - for example, the condition
+     * for TELLUS is matched also with VERNET firmware, but we want
+     * unambiguous results => exactly one type is to be returned each pass
+     * => the order of these conditions is important.
+     */
+    ap_vendorext = NONE;
+
+    if (ap_type == ATMEL410 && (memcmp(oui_sbridges, varbinds[0].value, 3) ==0))
+       ap_vendorext = SBRIDGES;
+
+    if (ap_type == ATMEL12350 && (memcmp(oui_tellus, varbinds[0].value, 3) ==0))
+       ap_vendorext = TELLUS;
+
+    if (ap_type == ATMEL12350 && varbinds[1].len_val == 104)
+       ap_vendorext = VERNET;
+
+    return 0;
+}
+
 void exit_program()
 {
     endwin();
@@ -246,45 +457,18 @@ void exit_shell()
     refresh();
 }
 
-/* 
- * Fill channels list string array using regulation domain
- * restrictions and return number of the channels
+/*
+ * Expects regulatory domain code on input and returns index of a corresponding
+ * regdom_types[] member, that describes the given regulatory domain properties.
  */
-int ch_list(int regulation_domain, char **list)
+int regdom_idx(char regdom)
 {
-    int FIRST_CHANNEL, LAST_CHANNEL, i;
-
-#ifndef NO_REG_DOMAIN
-    switch (regulation_domain) {
-    case 0x10:
-    case 0x20:
-       FIRST_CHANNEL = 1;
-       LAST_CHANNEL = 11;
-       break;
-    case 0x30:
-       FIRST_CHANNEL = 1;
-       LAST_CHANNEL = 13;
-       break;
-    case 0x31:
-       FIRST_CHANNEL = 10;
-       LAST_CHANNEL = 11;
-       break;
-    case 0x32:
-       FIRST_CHANNEL = 10;
-       LAST_CHANNEL = 13;
-       break;
-    default: /* also case 0x40 */
-#endif    
-       FIRST_CHANNEL = 1;
-       LAST_CHANNEL = 14;
-#ifndef NO_REG_DOMAIN
-    }
-#endif    
+    int i;
+
+    for (i = 0; &regdom_types[i]; i++)
+       if (regdom_types[i].code == regdom)
+           return i;
 
-    for (i = 0; i < LAST_CHANNEL - FIRST_CHANNEL + 1; i++) {
-       list[i] = (char *) malloc(3);
-       sprintf(list[i], "%02u", FIRST_CHANNEL + i);
-    }
     return i;
 }