]> git.decadent.org.uk Git - ap-utils.git/blobdiff - lib/common.c
Imported Upstream version 1.5.1~pre3
[ap-utils.git] / lib / common.c
index e8c0b7c116df502a2dddc700ac82d2339ecc8f9a..3c1b359157728c03ae62d61beaff76a18a410663 100644 (file)
@@ -2,6 +2,7 @@
  *      common.c from Access Point SNMP Utils for Linux
  *
  * Copyright (c) 2002 Roman Festchook <roma at polesye dot net>
+ * Copyright (c) 2005 Jan Rafaj <jr-aputils at cedric dot unob dot cz>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License Version 2 from
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/socket.h>
 #include "ap-utils.h"
 
-#define AUTODETECT _("Autodetect AP type? ")
 #define APIP _("Access Point IP-address: ")
 #define APPASS _("Password (community): ")
-#define APNAME _("Access Point name: ")
-#define WANT_APNAME _("Do you want to define name for this AP? ") 
-#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 IS_ATMEL410_SBRIDGES;
-char IS_ATMEL12350_TELLUS;
-char IS_ATMEL12350_VERNET;
+#define POLL_I _("[P] Polling mode interval (tenths of second): ")
+#define POLL_HELP _("P - change polling mode interval; Q - quit to menu")
+
+char *ap_types[] = {
+    "ATMEL410",
+    "NWN",
+    "ATMEL12350"
+};
+
+char *ap_vendorexts[][3] = {
+    { "NONE", "SBRIDGES" },            /* ATMEL410 exts */
+    { "NONE" },                                /* NWN exts */
+    { "NONE", "GEMTEK", "EZYNET" },    /* ATMEL12350 exts */
+    { 0 }                              /* do not delete! */
+};
+
+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;
-extern int sockfd;
 extern struct in_addr ap_ip;
-extern char *ap_types[];
+
+short ap_type, ap_vendorext;
+int poll_delay = 10;
 
 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);
@@ -77,54 +108,53 @@ void about()
     sprintf(message, _("Version %s"), VERSION);
     mvwaddstr(main_sub, brow + 3, bcol + 2, message);
     mvwaddstr(main_sub, brow + 5, bcol + 2,
-             _("Written by Roman Festchook roma@polesye.net"));
+       _("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,
-             _("This program is distributed under the terms"));
-    mvwaddstr(main_sub, brow +10, bcol + 2,
-             _("of the GNU General Public License version 2."));
+       _("and Jan Rafaj jr-aputils@cedric.unob.cz"));
+    mvwaddstr(main_sub, brow + 7, bcol + 2,
+       _("Copyright (c) 2001-2006"));
+    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,
-             _("See the included COPYING file for details."));
-
+       _("This program is distributed under the terms"));
+    mvwaddstr(main_sub, brow +12, bcol + 2,
+       _("of the GNU General Public License version 2."));
+    mvwaddstr(main_sub, brow + 13, bcol + 2,
+       _("See the included COPYING file for details."));
 
     wrefresh(main_sub);
 
     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;
-    struct sockaddr_in client;
+    /*
+     * 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}
+    };
+
+    extern int atmel410_filter; /* boolean; = 1 if we call from ap-gl utility */
     unsigned char message[256];
-    unsigned char name[17];
-    int fd;
+    unsigned char label[17];
+    int fd, i;
     char *home_dir;
     char save_settings=1;
+    varbind varbinds[1];
 
-    memset(&client, 0, sizeof client);
-    client.sin_family = AF_INET;
-    client.sin_port = INADDR_ANY;
-    client.sin_addr.s_addr = INADDR_ANY;
-
-    if (sockfd)
-       close(sockfd);
-
-    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
-       print_helperr(CREATE_SOCKET_ERROR);
-       getch();
-       goto exit;
-    }
-
-    if (bind(sockfd, (struct sockaddr *) &client, SIZE) == -1) {
-       print_helperr(BIND_SOCKET_ERROR);
+    if (reopen_sockfd() == -1) {
+       print_helperr(ERR_SOCKET);
        getch();
        goto exit;
     }
@@ -132,10 +162,12 @@ 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);
+    wrefresh(main_sub);
+    
     if (ip) {
        ap_ip.s_addr = ip;
        mvwaddstr(main_sub, 1, 1 + strlen(APIP), inet_ntoa(ap_ip));
@@ -145,8 +177,12 @@ get_all_again:
     }
 
     mvwaddstr(main_sub, 2, 1, APPASS);
+
+    i = 0;
+    print_help("");
+
     print_help(_("Entered characters will not be displayed "
-       "for security reason."));
+                "for security reasons."));
     get_pass(message, 2, 1 + strlen(APPASS), 16);
     if (community)
        free(community);
@@ -154,74 +190,148 @@ get_all_again:
     community = (char *) malloc(i);
     strncpy(community, message, i);
 
-    print_help(_("Display name for the Access point "
-       "(NOT the name defined inside the AP!)"));
-    mvwaddstr(main_sub, 3, 1, WANT_APNAME);
-    wrefresh(main_sub);
-    i = yes_no(3, 1 + strlen(WANT_APNAME));
-    if (i == 2) { /* NO */
-       name[0] = '\0';
-       mvwaddstr(main_sub, 3, 1 + strlen(WANT_APNAME), "No");
-    } else { /* YES */
-       clear_main_new(3, 4);
-       mvwaddstr(main_sub, 3, 1, APNAME);
-       get_value(message, 3, 1 + strlen(APNAME), sizeof(name),
-           ANY_STRING, 0, 0, NULL);
-       strncpy(name, message, strlen(message) + 1);
-    }
+    if (type && !atmel410_filter) {
+       /* entered from ap_search() */
 
-    print_help("");
-    if (type) {
+       /* 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, 4, 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, 4, 1, AUTODETECT);
-       wrefresh(main_sub);
-       i = yes_no(4, 1 + strlen(AUTODETECT));
-       clear_main_new(4, 5);
-       mvwaddstr(main_sub, 4, 1, APTYPE);
-       if (i == 2) { /* NO */
+       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);
-           ap_type = menu_choose(4, 1 + strlen(APTYPE), ap_types, 3);
-       } else { /* YES */
-           print_help(_("Determining AP type. Please wait..."));
-           if (get_mib_details() == -1) {
-               clear_main_new(1, 5);
-               goto get_all_again;
+           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);
+               print_bold(main_sub, ap_types[ap_type]);
+               mvwaddstr(main_sub, 4, 1, APVENDOREXT);
+               wrefresh(main_sub);
+               for (i = 0; ap_vendorexts[ap_type][i]; 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);
            }
        }
-       wattrset(main_sub, A_BOLD);
     }
-    waddstr(main_sub, ap_types[ap_type]);
-    wattrset(main_sub, A_NORMAL);
+    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;
 
-    mvwaddstr(main_sub, 5, 1, SAVESETTINGS);
+           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();
+               }
+           }
+           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);
+        wrefresh(main_sub);
+       get_value(message, 5, 1 + strlen(APLABEL), -sizeof(label), ANY_STRING,
+           0, 0, NULL);
+       strncpy(label, message, strlen(message) + 1);
+    }
+
+    mvwaddstr(main_sub, 6, 1, SAVESETTINGS);
     wrefresh(main_sub);
-    save_settings = on_off(5, 1 + strlen(SAVESETTINGS));
+    save_settings = on_off(6, 1 + strlen(SAVESETTINGS));
+    clear_main_new(6, 7);
+    print_menusel(6, 1, SAVESETTINGS, (save_settings == 1) ? ON : OFF);
 
     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:%s:%d\n", inet_ntoa(ap_ip),
-                   community, name, 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);
-           }
+               wbkgd(main_sub, A_NORMAL);
+               wrefresh(main_sub);
+               print_help(DONE_WRITING_APCONF);
+           } else
+               print_helperr(ERR_WRITING_APCONF);
+
+           getch();
        }
     }
   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 IS_ATMEL* globals). Returns with -1 on error or 0
+ * Determines AP MIB type (fills ap_type global), and AP MIB vendor extensions
+ * (fills ap_vendorext global). Returns with -1 on error or 0
  * if everything is OK.
  */
 int get_mib_details()
@@ -232,15 +342,27 @@ int get_mib_details()
     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
+    /*
+     * ATMEL410: SMARTBRIDGES MIB define this with length 4 (IpAddress); others
+     * (hopefully) do not define this but eventually return (hopefully)
+     * different value than 4.
+     */
+    char AuthRadiusIP_ATMEL[] = {
+       0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x06, 0x03, 0x00
+    };
+    /* ATMEL12350: GEMTEK and EZYNET MIBs define length 160, others 92 or 128 */
+    char sysDeviceInfo_ATMEL[] = {
+       0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x01, 0x01, 0x05, 0x00
     };
-    char Wireless_ATMEL[] = {
-       0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1A, 0x01, 0x02, 0x03, 0x01, 0x00
+    /* ATMEL12350: EZYNET MIB defines length 104, others 88 */
+    char wirelessStatistics_ATMEL[] = {
+       0x2B, 0x06, 0x01, 0x04, 0x01, 0xE0, 0x3E, 0x01, 0x02, 0x03, 0x01, 0x00
     };
+
     varbind varbinds[2];
-    char oui_sbridges[3] = { 0x00, 0x30, 0x1A };
-    char oui_tellus[3] = { 0x00, 0x04, 0xDB };
+    int i;
+
+    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;
@@ -269,8 +391,8 @@ int get_mib_details()
            if (snmp(varbinds, 1, GET) > 0) {
                ap_type = ATMEL12350;
            } else {
-               print_helperr(_("Unable to determine AP type "
-                   "(no response). Press any key."));
+               print_helperr(_("Unable to determine AP MIB properties "
+                   "(no response from AP). Press any key."));
                getch();
                return -1;
            }
@@ -279,48 +401,67 @@ int get_mib_details()
 
     /*
      * 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.
+     * about specific MIB vendor extensions - we'll check against them
+     * on different places later.
      */
-    IS_ATMEL410_SBRIDGES = 0;
-    IS_ATMEL12350_TELLUS = 0;
-    IS_ATMEL12350_VERNET = 0;
 
-    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;
+    ap_vendorext = NONE;
+
+    if (ap_type == ATMEL410) {
+       varbinds[0].oid = AuthRadiusIP_ATMEL;
+       varbinds[0].len_oid = sizeof(AuthRadiusIP_ATMEL);
+       varbinds[0].value = NULL;
+       varbinds[0].len_val = 0;
+       varbinds[0].type = NULL_VALUE;
+
+       i = snmp(varbinds, 1, GET);
+       if (i < 0) {
+           print_helperr(ERR_RET);
+           getch();
+           return -1;
+       }
+
+       /*
+        * i == 0 => 'no such variable in the MIB' returned =>
+        * consider 'ap_vendorext = NONE' too.
+        */
+
+       if (varbinds[0].len_val == 4)
+           ap_vendorext = SBRIDGES;
     }
 
-    /* detection of different vendor-modified ATMEL private MIBs */
-    if (ap_type == ATMEL410 && (memcmp(oui_sbridges, varbinds[0].value, 3) ==0))
-       IS_ATMEL410_SBRIDGES = 1;
+    if (ap_type == ATMEL12350) {
+       varbinds[0].oid = sysDeviceInfo_ATMEL;
+       varbinds[0].len_oid = sizeof(sysDeviceInfo_ATMEL);
+       varbinds[0].value = NULL;
+       varbinds[0].len_val = 0;
+       varbinds[0].type = NULL_VALUE;
+       varbinds[1].oid = wirelessStatistics_ATMEL;
+       varbinds[1].len_oid = sizeof(wirelessStatistics_ATMEL);
+       varbinds[1].value = NULL;
+       varbinds[1].len_val = 0;
+       varbinds[1].type = NULL_VALUE;
+
+       if (snmp(varbinds, 2, GET) <= 0) {
+           print_helperr(ERR_RET);
+           getch();
+           return -1;
+       }
 
-    if (ap_type == ATMEL12350 && (memcmp(oui_tellus, varbinds[0].value, 3) ==0))
-       IS_ATMEL12350_TELLUS = 1;
+       if (varbinds[0].len_val == 160)
+           ap_vendorext = GEMTEK;
 
-    if (ap_type == ATMEL12350 && varbinds[1].len_val == 104)
-       IS_ATMEL12350_VERNET = 1;
+       if (varbinds[1].len_val == 104)
+           ap_vendorext = EZYNET;
+    }
 
     return 0;
 }
 
 void exit_program()
 {
+    erase();
+    refresh();
     endwin();
     exit(0);
 }
@@ -334,45 +475,57 @@ void exit_shell()
     refresh();
 }
 
-/* 
- * Fill channels list string array using regulation domain
- * restrictions and return number of the channels
+/*
+ * Sets different-than-default (1 sec.) polling interval for polling-active
+ * modes, from interval <0.1;86400> seconds.
+ * poll_delay is natively in tenths of second.
  */
-int ch_list(int regulation_domain, char **list)
+void polling_interval()
 {
-    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    
+    unsigned char message[256];
+    int c = 0;
+
+    noecho();
+    print_help(POLL_HELP);
 
-    for (i = 0; i < LAST_CHANNEL - FIRST_CHANNEL + 1; i++) {
-       list[i] = (char *) malloc(3);
-       sprintf(list[i], "%02u", FIRST_CHANNEL + i);
+    while (1) {
+       sprintf(message, "%s%u", POLL_I, poll_delay);
+       mvwaddstr(main_sub, 0, 0, message);
+       sprintf(message, _("(%0.1f seconds)"), (float) poll_delay / 10);
+       mvwaddstr(main_sub, 1, strlen(POLL_I), message);
+       wrefresh(main_sub);
+       c = getch();
+       switch (c) {
+           case 'P':
+           case 'p':
+               get_value(message, 0, strlen(POLL_I), 7, INT_STRING, 1, 864000,
+                   POLL_HELP);
+               poll_delay = atoi(message);
+               clear_main_new(0, 2);
+               break;
+           case 'Q':
+           case 'q':
+               goto quit;
+       }
     }
-    return i;
+
+quit:
+    print_help("");
+    clear_main(0);
+    return;
 }
 
+/*
+ * Expects regulatory domain code on input and returns index of a corresponding
+ * regdom_types[] member, that describes the given regulatory domain properties.
+ */
+int regdom_idx(char regdom)
+{
+    int i;
+
+    for (i = 0; &regdom_types[i]; i++)
+       if (regdom_types[i].code == regdom)
+           return i;
+
+    return i;
+}