home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / mobile / wi.44.patches / wicontrol.c < prev    next >
C/C++ Source or Header  |  2002-01-17  |  21KB  |  913 lines

  1. /*
  2.  * Copyright (c) 1997, 1998, 1999
  3.  *    Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by Bill Paul.
  16.  * 4. Neither the name of the author nor the names of any co-contributors
  17.  *    may be used to endorse or promote products derived from this software
  18.  *    without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
  21.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
  24.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  30.  * THE POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * $FreeBSD: src/usr.sbin/wicontrol/wicontrol.c,v 1.9.2.4 2001/07/02 17:23:38 brooks Exp $
  33.  */
  34.  
  35. #include <sys/types.h>
  36. #include <sys/cdefs.h>
  37. #include <sys/param.h>
  38. #include <sys/socket.h>
  39. #include <sys/ioctl.h>
  40. #include <sys/socket.h>
  41.  
  42. #include <net/if.h>
  43. #include <net/if_var.h>
  44. #include <net/ethernet.h>
  45.  
  46. #include <machine/if_wavelan_ieee.h>
  47.  
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <stdlib.h>
  51. #include <unistd.h>
  52. #include <ctype.h>
  53. #include <errno.h>
  54. #include <err.h>
  55.  
  56. #if !defined(lint)
  57. static const char copyright[] = "@(#) Copyright (c) 1997, 1998, 1999\
  58.     Bill Paul. All rights reserved.";
  59. static const char rcsid[] =
  60.     "@(#) $FreeBSD: src/usr.sbin/wicontrol/wicontrol.c,v 1.9.2.4 2001/07/02 17:23:38 brooks Exp $";
  61. #endif
  62.  
  63. static void wi_getval        __P((char *, struct wi_req *));
  64. static void wi_setval        __P((char *, struct wi_req *));
  65. static void wi_printstr        __P((struct wi_req *));
  66. static void wi_setstr        __P((char *, int, char *));
  67. static void wi_setbytes        __P((char *, int, char *, int));
  68. static void wi_setword        __P((char *, int, int));
  69. static void wi_sethex        __P((char *, int, char *));
  70. static void wi_printwords    __P((struct wi_req *));
  71. static void wi_printbool    __P((struct wi_req *));
  72. static void wi_printhex        __P((struct wi_req *));
  73. static void wi_dumpinfo        __P((char *));
  74. static void wi_setkeys        __P((char *, char *, int));
  75. static void wi_printkeys    __P((struct wi_req *));
  76. static void usage        __P((char *));
  77.  
  78. static void wi_getval(iface, wreq)
  79.     char            *iface;
  80.     struct wi_req        *wreq;
  81. {
  82.     struct ifreq        ifr;
  83.     int            s;
  84.  
  85.     bzero((char *)&ifr, sizeof(ifr));
  86.  
  87.     strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
  88.     ifr.ifr_data = (caddr_t)wreq;
  89.  
  90.     s = socket(AF_INET, SOCK_DGRAM, 0);
  91.  
  92.     if (s == -1)
  93.         err(1, "socket");
  94.  
  95.     if (ioctl(s, SIOCGWAVELAN, &ifr) == -1)
  96.         err(1, "SIOCGWAVELAN");
  97.  
  98.     close(s);
  99.  
  100.     return;
  101. }
  102.  
  103. static void wi_setval(iface, wreq)
  104.     char            *iface;
  105.     struct wi_req        *wreq;
  106. {
  107.     struct ifreq        ifr;
  108.     int            s;
  109.  
  110.     bzero((char *)&ifr, sizeof(ifr));
  111.  
  112.     strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
  113.     ifr.ifr_data = (caddr_t)wreq;
  114.  
  115.     s = socket(AF_INET, SOCK_DGRAM, 0);
  116.  
  117.     if (s == -1)
  118.         err(1, "socket");
  119.  
  120.     if (ioctl(s, SIOCSWAVELAN, &ifr) == -1)
  121.         err(1, "SIOCSWAVELAN");
  122.  
  123.     close(s);
  124.  
  125.     return;
  126. }
  127.  
  128. void wi_printstr(wreq)
  129.     struct wi_req        *wreq;
  130. {
  131.     char            *ptr;
  132.     int            i;
  133.  
  134.     if (wreq->wi_type == WI_RID_SERIALNO) {
  135.         ptr = (char *)&wreq->wi_val;
  136.         for (i = 0; i < (wreq->wi_len - 1) * 2; i++) {
  137.             if (ptr[i] == '\0')
  138.                 ptr[i] = ' ';
  139.         }
  140.     } else {
  141.         ptr = (char *)&wreq->wi_val[1];
  142.         for (i = 0; i < wreq->wi_val[0]; i++) {
  143.             if (ptr[i] == '\0')
  144.                 ptr[i] = ' ';
  145.         }
  146.     }
  147.  
  148.     ptr[i] = '\0';
  149.     printf("[ %s ]", ptr);
  150.  
  151.     return;
  152. }
  153.  
  154. void wi_setstr(iface, code, str)
  155.     char            *iface;
  156.     int            code;
  157.     char            *str;
  158. {
  159.     struct wi_req        wreq;
  160.  
  161.     if (iface == NULL)
  162.         errx(1, "must specify interface name");
  163.  
  164.     if (str == NULL)
  165.         errx(1, "must specify string");
  166.  
  167.     bzero((char *)&wreq, sizeof(wreq));
  168.  
  169.     if (strlen(str) > 30)
  170.         errx(1, "string too long");
  171.  
  172.     wreq.wi_type = code;
  173.     wreq.wi_len = 18;
  174.     wreq.wi_val[0] = strlen(str);
  175.     bcopy(str, (char *)&wreq.wi_val[1], strlen(str));
  176.  
  177.     wi_setval(iface, &wreq);
  178.  
  179.     return;
  180. }
  181.  
  182. void wi_setbytes(iface, code, bytes, len)
  183.     char            *iface;
  184.     int            code;
  185.     char            *bytes;
  186.     int            len;
  187. {
  188.     struct wi_req        wreq;
  189.  
  190.     if (iface == NULL)
  191.         errx(1, "must specify interface name");
  192.  
  193.     bzero((char *)&wreq, sizeof(wreq));
  194.  
  195.     wreq.wi_type = code;
  196.     wreq.wi_len = (len / 2) + 1;
  197.     bcopy(bytes, (char *)&wreq.wi_val[0], len);
  198.  
  199.     wi_setval(iface, &wreq);
  200.  
  201.     return;
  202. }
  203.  
  204. void wi_setword(iface, code, word)
  205.     char            *iface;
  206.     int            code;
  207.     int            word;
  208. {
  209.     struct wi_req        wreq;
  210.  
  211.     bzero((char *)&wreq, sizeof(wreq));
  212.  
  213.     wreq.wi_type = code;
  214.     wreq.wi_len = 2;
  215.     wreq.wi_val[0] = word;
  216.  
  217.     wi_setval(iface, &wreq);
  218.  
  219.     return;
  220. }
  221.  
  222. void wi_sethex(iface, code, str)
  223.     char            *iface;
  224.     int            code;
  225.     char            *str;
  226. {
  227.     struct ether_addr    *addr;
  228.  
  229.     if (str == NULL)
  230.         errx(1, "must specify address");
  231.  
  232.     addr = ether_aton(str);
  233.  
  234.     if (addr == NULL)
  235.         errx(1, "badly formatted address");
  236.  
  237.     wi_setbytes(iface, code, (char *)addr, ETHER_ADDR_LEN);
  238.  
  239.     return;
  240. }
  241.  
  242. static int wi_hex2int(c)
  243.     char            c;
  244. {
  245.     if (c >= '0' && c <= '9')
  246.         return (c - '0');
  247.     if (c >= 'A' && c <= 'F')
  248.         return (c - 'A' + 10);
  249.     if (c >= 'a' && c <= 'f')
  250.         return (c - 'a' + 10);
  251.  
  252.     return (0); 
  253. }
  254.  
  255. static void wi_str2key(s, k)
  256.     char            *s;
  257.     struct wi_key        *k;
  258. {
  259.     int            n, i;
  260.     char            *p;
  261.  
  262.     /* Is this a hex string? */
  263.     if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
  264.         /* Yes, convert to int. */
  265.         n = 0;
  266.         p = (char *)&k->wi_keydat[0];
  267.         for (i = 2; i < strlen(s); i+= 2) {
  268.             *p++ = (wi_hex2int(s[i]) << 4) + wi_hex2int(s[i + 1]);
  269.             n++;
  270.         }
  271.         k->wi_keylen = n;
  272.     } else {
  273.         /* No, just copy it in. */
  274.         bcopy(s, k->wi_keydat, strlen(s));
  275.         k->wi_keylen = strlen(s);
  276.     }
  277.  
  278.     return;
  279. }
  280.  
  281. static void wi_setkeys(iface, key, idx)
  282.     char            *iface;
  283.     char            *key;
  284.     int            idx;
  285. {
  286.     int            keylen;
  287.     struct wi_req        wreq;
  288.     struct wi_ltv_keys    *keys;
  289.     struct wi_key        *k;
  290.  
  291.     bzero((char *)&wreq, sizeof(wreq));
  292.     wreq.wi_len = WI_MAX_DATALEN;
  293.     wreq.wi_type = WI_RID_WEP_AVAIL;
  294.  
  295.     wi_getval(iface, &wreq);
  296.     if (wreq.wi_val[0] == 0)
  297.         errx(1, "no WEP option available on this card");
  298.  
  299.     bzero((char *)&wreq, sizeof(wreq));
  300.     wreq.wi_len = WI_MAX_DATALEN;
  301.     wreq.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
  302.  
  303.     wi_getval(iface, &wreq);
  304.     keys = (struct wi_ltv_keys *)&wreq;
  305.  
  306.     keylen = strlen(key);
  307.     if (key[0] == '0' && (key[1] == 'x' || key[1] == 'X')) {
  308.         if(keylen != 2 && keylen != 12 && keylen != 28) {
  309.             errx(1, "encryption key must be 0, 10, or 26 "
  310.                 "hex digits long");
  311.         }
  312.     } else {
  313.         if (keylen != 0 && keylen != 5 && keylen != 13) {
  314.             errx(1, "encryption key must be 0, 5, or 13 "
  315.                 "bytes long");
  316.         }
  317.     }
  318.  
  319.     if (idx > 3)
  320.         errx(1, "only 4 encryption keys available");
  321.  
  322.     k = &keys->wi_keys[idx];
  323.     wi_str2key(key, k);
  324.  
  325.     wreq.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
  326.     wreq.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
  327.     wi_setval(iface, &wreq);
  328.  
  329.     return;
  330. }
  331.  
  332. static void wi_printkeys(wreq)
  333.     struct wi_req        *wreq;
  334. {
  335.     int            i, j;
  336.     int            isprintable;
  337.     struct wi_key        *k;
  338.     struct wi_ltv_keys    *keys;
  339.     char            *ptr;
  340.  
  341.     keys = (struct wi_ltv_keys *)wreq;
  342.  
  343.     for (i = 0; i < 4; i++) {
  344.         k = &keys->wi_keys[i];
  345.         ptr = (char *)k->wi_keydat;
  346.         isprintable = 1;
  347.         for (j = 0; j < k->wi_keylen; j++) {
  348.             if (!isprint(ptr[j])) {
  349.                 isprintable = 0;
  350.                 break;
  351.             }
  352.         }
  353.         if(isprintable) {
  354.             ptr[j] = '\0';
  355.             printf("[ %s ]", ptr);
  356.         } else {
  357.             printf("[ 0x");
  358.             for (j = 0; j < k->wi_keylen; j++) {
  359.                 printf("%02x", ptr[j] & 0xFF);
  360.             }
  361.             printf(" ]");
  362.                     
  363.         }
  364.     }
  365.  
  366.     return;
  367. };
  368.  
  369. void wi_printwords(wreq)
  370.     struct wi_req        *wreq;
  371. {
  372.     int            i;
  373.  
  374.     printf("[ ");
  375.     for (i = 0; i < wreq->wi_len - 1; i++)
  376.         printf("%d ", wreq->wi_val[i]);
  377.     printf("]");
  378.  
  379.     return;
  380. }
  381.  
  382. void wi_printbool(wreq)
  383.     struct wi_req        *wreq;
  384. {
  385.     if (wreq->wi_val[0])
  386.         printf("[ On ]");
  387.     else
  388.         printf("[ Off ]");
  389.  
  390.     return;
  391. }
  392.  
  393. void wi_printhex(wreq)
  394.     struct wi_req        *wreq;
  395. {
  396.     int            i;
  397.     unsigned char        *c;
  398.  
  399.     c = (unsigned char *)&wreq->wi_val;
  400.  
  401.     printf("[ ");
  402.     for (i = 0; i < (wreq->wi_len - 1) * 2; i++) {
  403.         printf("%02x", c[i]);
  404.         if (i < ((wreq->wi_len - 1) * 2) - 1)
  405.             printf(":");
  406.     }
  407.  
  408.     printf(" ]");
  409.     return;
  410. }
  411.  
  412. #define WI_STRING        0x01
  413. #define WI_BOOL            0x02
  414. #define WI_WORDS        0x03
  415. #define WI_HEXBYTES        0x04
  416. #define WI_KEYSTRUCT        0x05
  417.  
  418. struct wi_table {
  419.     int            wi_code;
  420.     int            wi_type;
  421.     char            *wi_str;
  422. };
  423.  
  424. static struct wi_table wi_table[] = {
  425.     { WI_RID_SERIALNO, WI_STRING, "NIC serial number:\t\t\t" },
  426.     { WI_RID_NODENAME, WI_STRING, "Station name:\t\t\t\t" },
  427.     { WI_RID_OWN_SSID, WI_STRING, "SSID for IBSS creation:\t\t\t" },
  428.     { WI_RID_CURRENT_SSID, WI_STRING, "Current netname (SSID):\t\t\t" },
  429.     { WI_RID_DESIRED_SSID, WI_STRING, "Desired netname (SSID):\t\t\t" },
  430.     { WI_RID_CURRENT_BSSID, WI_HEXBYTES, "Current BSSID:\t\t\t\t" },
  431.     { WI_RID_CHANNEL_LIST, WI_WORDS, "Channel list:\t\t\t\t" },
  432.     { WI_RID_OWN_CHNL, WI_WORDS, "IBSS channel:\t\t\t\t" },
  433.     { WI_RID_CURRENT_CHAN, WI_WORDS, "Current channel:\t\t\t" },
  434.     { WI_RID_COMMS_QUALITY, WI_WORDS, "Comms quality/signal/noise:\t\t" },
  435.     { WI_RID_PROMISC, WI_BOOL, "Promiscuous mode:\t\t\t" },
  436.     { WI_RID_PORTTYPE, WI_WORDS, "Port type (1=BSS, 3=ad-hoc):\t\t"},
  437.     { WI_RID_MAC_NODE, WI_HEXBYTES, "MAC address:\t\t\t\t"},
  438.     { WI_RID_TX_RATE, WI_WORDS, "TX rate (selection):\t\t\t"},
  439.     { WI_RID_CUR_TX_RATE, WI_WORDS, "TX rate (actual speed):\t\t\t"},
  440.     { WI_RID_RTS_THRESH, WI_WORDS, "RTS/CTS handshake threshold:\t\t"},
  441.     { WI_RID_CREATE_IBSS, WI_BOOL, "Create IBSS:\t\t\t\t" },
  442.     { WI_RID_SYSTEM_SCALE, WI_WORDS, "Access point density:\t\t\t" },
  443.     { WI_RID_PM_ENABLED, WI_WORDS, "Power Mgmt (1=on, 0=off):\t\t" },
  444.     { WI_RID_MAX_SLEEP, WI_WORDS, "Max sleep time:\t\t\t\t" },
  445.     { 0, NULL }
  446. };
  447.  
  448. static struct wi_table wi_crypt_table[] = {
  449.     { WI_RID_ENCRYPTION, WI_BOOL, "WEP encryption:\t\t\t\t" },
  450.     { WI_RID_TX_CRYPT_KEY, WI_WORDS, "TX encryption key:\t\t\t" },
  451.     { WI_RID_DEFLT_CRYPT_KEYS, WI_KEYSTRUCT, "Encryption keys:\t\t\t" },
  452.     { 0, NULL }
  453. };
  454.  
  455. static void wi_dumpinfo(iface)
  456.     char            *iface;
  457. {
  458.     struct wi_req        wreq;
  459.     int            i, has_wep;
  460.     struct wi_table        *w;
  461.  
  462.     bzero((char *)&wreq, sizeof(wreq));
  463.  
  464.     wreq.wi_len = WI_MAX_DATALEN;
  465.     wreq.wi_type = WI_RID_WEP_AVAIL;
  466.  
  467.     wi_getval(iface, &wreq);
  468.     has_wep = wreq.wi_val[0];
  469.  
  470.     w = wi_table;
  471.  
  472.     for (i = 0; w[i].wi_type; i++) {
  473.         bzero((char *)&wreq, sizeof(wreq));
  474.  
  475.         wreq.wi_len = WI_MAX_DATALEN;
  476.         wreq.wi_type = w[i].wi_code;
  477.  
  478.         wi_getval(iface, &wreq);
  479.         printf("%s", w[i].wi_str);
  480.         switch(w[i].wi_type) {
  481.         case WI_STRING:
  482.             wi_printstr(&wreq);
  483.             break;
  484.         case WI_WORDS:
  485.             wi_printwords(&wreq);
  486.             break;
  487.         case WI_BOOL:
  488.             wi_printbool(&wreq);
  489.             break;
  490.         case WI_HEXBYTES:
  491.             wi_printhex(&wreq);
  492.             break;
  493.         default:
  494.             break;
  495.         }    
  496.         printf("\n");
  497.     }
  498.  
  499.     if (has_wep) {
  500.         w = wi_crypt_table;
  501.         for (i = 0; w[i].wi_type; i++) {
  502.             bzero((char *)&wreq, sizeof(wreq));
  503.  
  504.             wreq.wi_len = WI_MAX_DATALEN;
  505.             wreq.wi_type = w[i].wi_code;
  506.  
  507.             wi_getval(iface, &wreq);
  508.             printf("%s", w[i].wi_str);
  509.             switch(w[i].wi_type) {
  510.             case WI_STRING:
  511.                 wi_printstr(&wreq);
  512.                 break;
  513.             case WI_WORDS:
  514.                 if (wreq.wi_type == WI_RID_TX_CRYPT_KEY)
  515.                     wreq.wi_val[0]++;
  516.                 wi_printwords(&wreq);
  517.                 break;
  518.             case WI_BOOL:
  519.                 wi_printbool(&wreq);
  520.                 break;
  521.             case WI_HEXBYTES:
  522.                 wi_printhex(&wreq);
  523.                 break;
  524.             case WI_KEYSTRUCT:
  525.                 wi_printkeys(&wreq);
  526.                 break;
  527.             default:
  528.                 break;
  529.             }    
  530.             printf("\n");
  531.         }
  532.     }
  533.  
  534.     return;
  535. }
  536.  
  537. static void wi_dumpstats(iface)
  538.     char            *iface;
  539. {
  540.     struct wi_req        wreq;
  541.     struct wi_counters    *c;
  542.  
  543.     if (iface == NULL)
  544.         errx(1, "must specify interface name");
  545.  
  546.     bzero((char *)&wreq, sizeof(wreq));
  547.     wreq.wi_len = WI_MAX_DATALEN;
  548.     wreq.wi_type = WI_RID_IFACE_STATS;
  549.  
  550.     wi_getval(iface, &wreq);
  551.  
  552.     c = (struct wi_counters *)&wreq.wi_val;
  553.  
  554.     printf("Transmitted unicast frames:\t\t%d\n",
  555.         c->wi_tx_unicast_frames);
  556.     printf("Transmitted multicast frames:\t\t%d\n",
  557.         c->wi_tx_multicast_frames);
  558.     printf("Transmitted fragments:\t\t\t%d\n",
  559.         c->wi_tx_fragments);
  560.     printf("Transmitted unicast octets:\t\t%d\n",
  561.         c->wi_tx_unicast_octets);
  562.     printf("Transmitted multicast octets:\t\t%d\n",
  563.         c->wi_tx_multicast_octets);
  564.     printf("Single transmit retries:\t\t%d\n",
  565.         c->wi_tx_single_retries);
  566.     printf("Multiple transmit retries:\t\t%d\n",
  567.         c->wi_tx_multi_retries);
  568.     printf("Transmit retry limit exceeded:\t\t%d\n",
  569.         c->wi_tx_retry_limit);
  570.     printf("Transmit discards:\t\t\t%d\n",
  571.         c->wi_tx_discards);
  572.     printf("Transmit discards due to wrong SA:\t%d\n",
  573.         c->wi_tx_discards_wrong_sa);
  574.     printf("Received unicast frames:\t\t%d\n",
  575.         c->wi_rx_unicast_frames);
  576.     printf("Received multicast frames:\t\t%d\n",
  577.         c->wi_rx_multicast_frames);
  578.     printf("Received fragments:\t\t\t%d\n",
  579.         c->wi_rx_fragments);
  580.     printf("Received unicast octets:\t\t%d\n",
  581.         c->wi_rx_unicast_octets);
  582.     printf("Received multicast octets:\t\t%d\n",
  583.         c->wi_rx_multicast_octets);
  584.     printf("Receive FCS errors:\t\t\t%d\n",
  585.         c->wi_rx_fcs_errors);
  586.     printf("Receive discards due to no buffer:\t%d\n",
  587.         c->wi_rx_discards_nobuf);
  588.     printf("Can't decrypt WEP frame:\t\t%d\n",
  589.         c->wi_rx_WEP_cant_decrypt);
  590.     printf("Received message fragments:\t\t%d\n",
  591.         c->wi_rx_msg_in_msg_frags);
  592.     printf("Received message bad fragments:\t\t%d\n",
  593.         c->wi_rx_msg_in_bad_msg_frags);
  594.  
  595.     return;
  596. }
  597.  
  598. static void usage(p)
  599.     char            *p;
  600. {
  601.     fprintf(stderr, "usage:  %s -i iface\n", p);
  602.     fprintf(stderr, "\t%s -i iface -o\n", p);
  603.     fprintf(stderr, "\t%s -i iface -t tx rate\n", p);
  604.     fprintf(stderr, "\t%s -i iface -n network name\n", p);
  605.     fprintf(stderr, "\t%s -i iface -s station name\n", p);
  606.     fprintf(stderr, "\t%s -i iface -c 0|1\n", p);
  607.     fprintf(stderr, "\t%s -i iface -q SSID\n", p);
  608.     fprintf(stderr, "\t%s -i iface -p port type\n", p);
  609.     fprintf(stderr, "\t%s -i iface -a access point density\n", p);
  610.     fprintf(stderr, "\t%s -i iface -m mac address\n", p);
  611.     fprintf(stderr, "\t%s -i iface -d max data length\n", p);
  612.     fprintf(stderr, "\t%s -i iface -e 0|1\n", p);
  613.     fprintf(stderr, "\t%s -i iface -k encryption key [-v 1|2|3|4]\n", p);
  614.     fprintf(stderr, "\t%s -i iface -r RTS threshold\n", p);
  615.     fprintf(stderr, "\t%s -i iface -f frequency\n", p);
  616.     fprintf(stderr, "\t%s -i iface -P 0|1t\n", p);
  617.     fprintf(stderr, "\t%s -i iface -S max sleep duration\n", p);
  618.     fprintf(stderr, "\t%s -i iface -T 1|2|3|4\n", p);
  619. #ifdef WICACHE
  620.     fprintf(stderr, "\t%s -i iface -Z zero out signal cache\n", p);
  621.     fprintf(stderr, "\t%s -i iface -C print signal cache\n", p);
  622. #endif
  623.     fprintf(stderr, "\t%s -i iface -A scan access points\n", p);
  624.  
  625.     exit(1);
  626. }
  627.  
  628. static void wi_apscan(iface)
  629.     char            *iface;
  630. {
  631.     int s;
  632.     struct wi_req        wreq;
  633.     struct ifreq        ifr;
  634.     int naps;
  635.     int retries = 10;    /* number of seconds to retry */
  636.     struct wi_apinfo *w;
  637.     int i, j;
  638.  
  639.     if (iface == NULL)
  640.         errx(1, "must specify interface name");
  641.  
  642.     bzero((char *)&wreq, sizeof(wreq));
  643.  
  644.     wreq.wi_type = WI_RID_SCAN_APS;
  645.     wreq.wi_len = 4;
  646.     /* note chan. 1 is the least significant bit */
  647.     wreq.wi_val[0] = 0x7ff;  /* 1 bit per channel, 1-11 */
  648.     wreq.wi_val[1] = 3;      /* tx rate */
  649.  
  650.     /* write the request
  651.     */
  652.     wi_setval(iface, &wreq);
  653.  
  654.     /* now poll for a result
  655.     */
  656.     bzero((char *)&wreq, sizeof(wreq));
  657.     wreq.wi_len = WI_MAX_DATALEN;
  658.     wreq.wi_type = WI_RID_READ_APS;
  659.  
  660.     /* we have to do this ourself as opposed to
  661.      * using setval, because we cannot bail if
  662.      * the ioctl fails
  663.      */
  664.     strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
  665.     ifr.ifr_data = (caddr_t)&wreq;
  666.  
  667.     s = socket(AF_INET, SOCK_DGRAM, 0);
  668.  
  669.     if (s == -1)
  670.         err(1, "socket");
  671.  
  672.     setbuf(stdout, NULL);
  673.     printf("scanning ...");
  674.     while (ioctl(s, SIOCGWAVELAN, &ifr) == -1) {
  675.         retries--;
  676.  
  677.         if (retries >= 0) {
  678.             printf(".");
  679.             sleep(1);
  680.         }
  681.         else {
  682.             break;
  683.         }
  684.         errno = 0;
  685.     }
  686.  
  687.     close(s);
  688.     if (errno) {
  689.         perror("ioctl");
  690.         exit(1);
  691.     }
  692.     printf("\n");
  693.  
  694.     naps = (int) wreq.wi_val[0]; 
  695.     w =  (struct wi_apinfo *) (((char *)&wreq.wi_val) + sizeof(int));
  696.     for ( i = 0; i < naps; i++, w++) {
  697.         printf("ap[%d]:\n", i);
  698.         printf("\tnetname: ");
  699.                 for (j = 0; j < w->namelen; j++) {
  700.                         printf("%c", w->name[j]);
  701.                 }
  702.                 printf("\n");
  703.         printf("\tchannel: %d\n", w->channel);
  704.         printf("\tquality/signal/noise: %d %d %d \n", 
  705.             w->quality, w->signal, w->noise);
  706.                 printf("\tBSSID - %x:%x:%x:%x:%x:%x\n",
  707.                         w->bssid[0]&0xff, w->bssid[1]&0xff,
  708.                         w->bssid[2]&0xff, w->bssid[3]&0xff,
  709.                         w->bssid[4]&0xff, w->bssid[5]&0xff);
  710.                 printf("\tbeacon interval: %d\n", w->interval); 
  711.                 printf("\tcapinfo: %x\n", w->capinfo); 
  712.     }
  713. }
  714.  
  715. #ifdef WICACHE
  716. static void wi_zerocache(iface)
  717.     char            *iface;
  718. {
  719.     struct wi_req        wreq;
  720.  
  721.     if (iface == NULL)
  722.         errx(1, "must specify interface name");
  723.  
  724.     bzero((char *)&wreq, sizeof(wreq));
  725.     wreq.wi_len = 0;
  726.     wreq.wi_type = WI_RID_ZERO_CACHE;
  727.  
  728.     wi_getval(iface, &wreq);
  729. }
  730.  
  731. static void wi_readcache(iface)
  732.     char            *iface;
  733. {
  734.     struct wi_req        wreq;
  735.     int             *wi_sigitems;
  736.     struct wi_sigcache     *sc;
  737.     char *            pt;
  738.     int             i;
  739.  
  740.     if (iface == NULL)
  741.         errx(1, "must specify interface name");
  742.  
  743.     bzero((char *)&wreq, sizeof(wreq));
  744.     wreq.wi_len = WI_MAX_DATALEN;
  745.     wreq.wi_type = WI_RID_READ_CACHE;
  746.  
  747.     wi_getval(iface, &wreq);
  748.  
  749.     wi_sigitems = (int *) &wreq.wi_val; 
  750.     pt = ((char *) &wreq.wi_val);
  751.     pt += sizeof(int);
  752.     sc = (struct wi_sigcache *) pt;
  753.  
  754.     for (i = 0; i < *wi_sigitems; i++) {
  755.         printf("[%d/%d]:", i+1, *wi_sigitems);
  756.         printf(" %02x:%02x:%02x:%02x:%02x:%02x,",
  757.                           sc->macsrc[0]&0xff,
  758.                           sc->macsrc[1]&0xff,
  759.                            sc->macsrc[2]&0xff,
  760.                        sc->macsrc[3]&0xff,
  761.                        sc->macsrc[4]&0xff,
  762.                        sc->macsrc[5]&0xff);
  763.             printf(" %d.%d.%d.%d,",((sc->ipsrc >> 0) & 0xff),
  764.                         ((sc->ipsrc >> 8) & 0xff),
  765.                         ((sc->ipsrc >> 16) & 0xff),
  766.                         ((sc->ipsrc >> 24) & 0xff));
  767.         printf(" sig: %d, noise: %d, qual: %d\n",
  768.                        sc->signal,
  769.                        sc->noise,
  770.                        sc->quality);
  771.         sc++;
  772.     }
  773.  
  774.     return;
  775. }
  776. #endif
  777.  
  778. int main(argc, argv)
  779.     int            argc;
  780.     char            *argv[];
  781. {
  782.     int            ch;
  783.     char            *iface = NULL;
  784.     char            *p = argv[0];
  785.     char            *key = NULL;
  786.     int            modifier = 0;
  787.  
  788.     /* Get the interface name */
  789.     opterr = 0;
  790.     ch = getopt(argc, argv, "i:");
  791.     if (ch == 'i') {
  792.         iface = optarg;
  793.     } else {
  794.         iface = "wi0";
  795.         optreset = 1;
  796.         optind = 1;
  797.     }
  798.     opterr = 1;
  799.         
  800.     while((ch = getopt(argc, argv,
  801.         "a:hoc:d:e:f:i:k:p:r:q:t:n:s:m:v:P:S:T:ZCA")) != -1) {
  802.         switch(ch) {
  803.         case 'A':
  804.             wi_apscan(iface);
  805.             exit(0);    
  806.         case 'Z':
  807. #ifdef WICACHE
  808.             wi_zerocache(iface);
  809.             exit(0);
  810. #else
  811.             printf("WICACHE not available\n");
  812. #endif
  813.             break;
  814.         case 'C':
  815. #ifdef WICACHE
  816.             wi_readcache(iface);
  817. #else
  818.             printf("WICACHE not available\n");
  819. #endif
  820.             exit(0);
  821.             break;
  822.         case 'o':
  823.             wi_dumpstats(iface);
  824.             exit(0);
  825.             break;
  826.         case 'c':
  827.             wi_setword(iface, WI_RID_CREATE_IBSS, atoi(optarg));
  828.             exit(0);
  829.             break;
  830.         case 'd':
  831.             wi_setword(iface, WI_RID_MAX_DATALEN, atoi(optarg));
  832.             exit(0);
  833.             break;
  834.         case 'e':
  835.             wi_setword(iface, WI_RID_ENCRYPTION, atoi(optarg));
  836.             exit(0);
  837.             break;
  838.         case 'f':
  839.             wi_setword(iface, WI_RID_OWN_CHNL, atoi(optarg));
  840.             exit(0);
  841.             break;
  842.         case 'k':
  843.             key = optarg;
  844.             break;
  845.         case 'p':
  846.             wi_setword(iface, WI_RID_PORTTYPE, atoi(optarg));
  847.             exit(0);
  848.             break;
  849.         case 'r':
  850.             wi_setword(iface, WI_RID_RTS_THRESH, atoi(optarg));
  851.             exit(0);
  852.             break;
  853.         case 't':
  854.             wi_setword(iface, WI_RID_TX_RATE, atoi(optarg));
  855.             exit(0);
  856.             break;
  857.         case 'n':
  858.             wi_setstr(iface, WI_RID_DESIRED_SSID, optarg);
  859.             exit(0);
  860.             break;
  861.         case 's':
  862.             wi_setstr(iface, WI_RID_NODENAME, optarg);
  863.             exit(0);
  864.             break;
  865.         case 'm':
  866.             wi_sethex(iface, WI_RID_MAC_NODE, optarg);
  867.             exit(0);
  868.             break;
  869.         case 'q':
  870.             wi_setstr(iface, WI_RID_OWN_SSID, optarg);
  871.             exit(0);
  872.             break;
  873.         case 'S':
  874.             wi_setword(iface, WI_RID_MAX_SLEEP, atoi(optarg));
  875.             exit(0);
  876.             break;
  877.         case 'T':
  878.             wi_setword(iface,
  879.                 WI_RID_TX_CRYPT_KEY, atoi(optarg) - 1);
  880.             exit(0);
  881.             break;
  882.         case 'P':
  883.             wi_setword(iface, WI_RID_PM_ENABLED, atoi(optarg));
  884.             exit(0);
  885.             break;
  886.         case 'a':
  887.             wi_setword(iface, WI_RID_SYSTEM_SCALE, atoi(optarg));
  888.             exit(0);
  889.             break;
  890.         case 'v':
  891.             modifier = atoi(optarg);
  892.             modifier--;
  893.             break;
  894.         case 'h':
  895.         default:
  896.             usage(p);
  897.             break;
  898.         }
  899.     }
  900.  
  901.     if (iface == NULL)
  902.         usage(p);
  903.  
  904.     if (key != NULL) {
  905.         wi_setkeys(iface, key, modifier);
  906.         exit(0);
  907.     }
  908.  
  909.     wi_dumpinfo(iface);
  910.  
  911.     exit(0);
  912. }
  913.