b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | /* |
| 2 | * Wireless Tools |
| 3 | * |
| 4 | * Jean II - HPLB '99 |
| 5 | * |
| 6 | * This tool can manipulate the spy list : add addresses and display stat |
| 7 | * You need to link this code against "iwlib.c" and "-lm". |
| 8 | * |
| 9 | * This file is released under the GPL license. |
| 10 | * Copyright (c) 1997-2002 Jean Tourrilhes <jt@hpl.hp.com> |
| 11 | */ |
| 12 | |
| 13 | #include "iwlib.h" /* Header */ |
| 14 | |
| 15 | /* Backward compatibility */ |
| 16 | #ifndef IW_MAX_GET_SPY |
| 17 | #define IW_MAX_GET_SPY 64 |
| 18 | #endif /* IW_MAX_GET_SPY */ |
| 19 | |
| 20 | /************************* DISPLAY ROUTINES **************************/ |
| 21 | |
| 22 | /*------------------------------------------------------------------*/ |
| 23 | /* |
| 24 | * Display the spy list of addresses and the associated stats |
| 25 | */ |
| 26 | static int |
| 27 | print_spy_info(int skfd, |
| 28 | char * ifname, |
| 29 | char * args[], |
| 30 | int count) |
| 31 | { |
| 32 | struct iwreq wrq; |
| 33 | char buffer[(sizeof(struct iw_quality) + |
| 34 | sizeof(struct sockaddr)) * IW_MAX_GET_SPY]; |
| 35 | char temp[128]; |
| 36 | struct sockaddr * hwa; |
| 37 | struct iw_quality * qual; |
| 38 | iwrange range; |
| 39 | int has_range = 0; |
| 40 | int n; |
| 41 | int i; |
| 42 | |
| 43 | /* Avoid "Unused parameter" warning */ |
| 44 | args = args; count = count; |
| 45 | |
| 46 | /* Collect stats */ |
| 47 | wrq.u.data.pointer = (caddr_t) buffer; |
| 48 | wrq.u.data.length = IW_MAX_GET_SPY; |
| 49 | wrq.u.data.flags = 0; |
| 50 | if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) |
| 51 | { |
| 52 | fprintf(stderr, "%-8.8s Interface doesn't support wireless statistic collection\n\n", ifname); |
| 53 | return(-1); |
| 54 | } |
| 55 | |
| 56 | /* Number of addresses */ |
| 57 | n = wrq.u.data.length; |
| 58 | |
| 59 | /* Check if we have valid mac address type */ |
| 60 | if(iw_check_mac_addr_type(skfd, ifname) < 0) |
| 61 | { |
| 62 | fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n\n", ifname); |
| 63 | return(-2); |
| 64 | } |
| 65 | |
| 66 | /* Get range info if we can */ |
| 67 | if(iw_get_range_info(skfd, ifname, &(range)) >= 0) |
| 68 | has_range = 1; |
| 69 | |
| 70 | /* Display it */ |
| 71 | if(n == 0) |
| 72 | printf("%-8.8s No statistics to collect\n", ifname); |
| 73 | else |
| 74 | printf("%-8.8s Statistics collected:\n", ifname); |
| 75 | |
| 76 | /* The two lists */ |
| 77 | hwa = (struct sockaddr *) buffer; |
| 78 | qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n)); |
| 79 | |
| 80 | for(i = 0; i < n; i++) |
| 81 | { |
| 82 | /* Print stats for each address */ |
| 83 | printf(" %s : ", iw_pr_ether(temp, hwa[i].sa_data)); |
| 84 | iw_print_stats(temp, &qual[i], &range, has_range); |
| 85 | printf("%s\n", temp); |
| 86 | } |
| 87 | #if WIRELESS_EXT > 11 |
| 88 | if((n > 0) && (has_range)) |
| 89 | { |
| 90 | iw_print_stats(temp, &range.avg_qual, &range, has_range); |
| 91 | printf(" typical/average : %s\n", temp); |
| 92 | } |
| 93 | #endif /* WIRELESS_EXT > 11 */ |
| 94 | |
| 95 | printf("\n"); |
| 96 | return(0); |
| 97 | } |
| 98 | |
| 99 | /************************* SETTING ROUTINES **************************/ |
| 100 | |
| 101 | /*------------------------------------------------------------------*/ |
| 102 | /* |
| 103 | * Set list of addresses specified on command line in the driver. |
| 104 | */ |
| 105 | static int |
| 106 | set_spy_info(int skfd, /* The socket */ |
| 107 | char * args[], /* Command line args */ |
| 108 | int count, /* Args count */ |
| 109 | char * ifname) /* Dev name */ |
| 110 | { |
| 111 | struct iwreq wrq; |
| 112 | int i; |
| 113 | int nbr; /* Number of valid addresses */ |
| 114 | struct sockaddr hw_address[IW_MAX_SPY]; |
| 115 | |
| 116 | /* Read command line */ |
| 117 | i = 0; /* first arg to read */ |
| 118 | nbr = 0; /* Number of args read so far */ |
| 119 | |
| 120 | /* "off" : disable functionality (set 0 addresses) */ |
| 121 | if(!strcmp(args[0], "off")) |
| 122 | i = 1; /* skip the "off" */ |
| 123 | else |
| 124 | { |
| 125 | /* "+" : add all addresses already in the driver */ |
| 126 | if(!strcmp(args[0], "+")) |
| 127 | { |
| 128 | char buffer[(sizeof(struct iw_quality) + |
| 129 | sizeof(struct sockaddr)) * IW_MAX_SPY]; |
| 130 | |
| 131 | /* Check if we have valid mac address type */ |
| 132 | if(iw_check_mac_addr_type(skfd, ifname) < 0) |
| 133 | { |
| 134 | fprintf(stderr, "%-8.8s Interface doesn't support MAC addresses\n", ifname); |
| 135 | return(-1); |
| 136 | } |
| 137 | |
| 138 | wrq.u.data.pointer = (caddr_t) buffer; |
| 139 | wrq.u.data.length = 0; |
| 140 | wrq.u.data.flags = 0; |
| 141 | if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0) |
| 142 | { |
| 143 | fprintf(stderr, "Interface doesn't accept reading addresses...\n"); |
| 144 | fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno)); |
| 145 | return(-1); |
| 146 | } |
| 147 | |
| 148 | /* Copy old addresses */ |
| 149 | nbr = wrq.u.data.length; |
| 150 | memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr)); |
| 151 | |
| 152 | i = 1; /* skip the "+" */ |
| 153 | } |
| 154 | |
| 155 | /* Read other args on command line */ |
| 156 | while((i < count) && (nbr < IW_MAX_SPY)) |
| 157 | { |
| 158 | /* Get the address and check if the interface supports it */ |
| 159 | if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0) |
| 160 | continue; |
| 161 | nbr++; |
| 162 | } |
| 163 | |
| 164 | /* Check the number of addresses */ |
| 165 | if(nbr == 0) |
| 166 | { |
| 167 | fprintf(stderr, "No valid addresses found : exiting...\n"); |
| 168 | return(-1); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | /* Check if there is some remaining arguments */ |
| 173 | if(i < count) |
| 174 | { |
| 175 | fprintf(stderr, "Got only the first %d arguments, remaining discarded\n", i); |
| 176 | } |
| 177 | |
| 178 | /* Time to do send addresses to the driver */ |
| 179 | wrq.u.data.pointer = (caddr_t) hw_address; |
| 180 | wrq.u.data.length = nbr; |
| 181 | wrq.u.data.flags = 0; |
| 182 | if(iw_set_ext(skfd, ifname, SIOCSIWSPY, &wrq) < 0) |
| 183 | { |
| 184 | fprintf(stderr, "Interface doesn't accept addresses...\n"); |
| 185 | fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno)); |
| 186 | return(-1); |
| 187 | } |
| 188 | |
| 189 | return(0); |
| 190 | } |
| 191 | |
| 192 | /******************************* MAIN ********************************/ |
| 193 | |
| 194 | /*------------------------------------------------------------------*/ |
| 195 | /* |
| 196 | * The main ! |
| 197 | */ |
| 198 | int |
| 199 | main(int argc, |
| 200 | char ** argv) |
| 201 | { |
| 202 | int skfd; /* generic raw socket desc. */ |
| 203 | int goterr = 0; |
| 204 | |
| 205 | /* Create a channel to the NET kernel. */ |
| 206 | if((skfd = iw_sockets_open()) < 0) |
| 207 | { |
| 208 | perror("socket"); |
| 209 | return(-1); |
| 210 | } |
| 211 | |
| 212 | /* No argument : show the list of all device + info */ |
| 213 | if(argc == 1) |
| 214 | iw_enum_devices(skfd, &print_spy_info, NULL, 0); |
| 215 | else |
| 216 | /* Special cases take one... */ |
| 217 | /* Help */ |
| 218 | if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) |
| 219 | fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n"); |
| 220 | else |
| 221 | /* Version */ |
| 222 | if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) |
| 223 | goterr = iw_print_version_info("iwspy"); |
| 224 | else |
| 225 | /* The device name must be the first argument */ |
| 226 | /* Name only : show spy list for that device only */ |
| 227 | if(argc == 2) |
| 228 | print_spy_info(skfd, argv[1], NULL, 0); |
| 229 | else |
| 230 | /* Otherwise, it's a list of address to set in the spy list */ |
| 231 | goterr = set_spy_info(skfd, argv + 2, argc - 2, argv[1]); |
| 232 | |
| 233 | /* Close the socket. */ |
| 234 | close(skfd); |
| 235 | |
| 236 | return(goterr); |
| 237 | } |