iwspy.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*
  2. * Wireless Tools
  3. *
  4. * Jean II - HPLB '99 - HPL 99->04
  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-2004 Jean Tourrilhes <jt@hpl.hp.com>
  11. */
  12. #include "iwlib.h" /* Header */
  13. /************************* DISPLAY ROUTINES **************************/
  14. /*------------------------------------------------------------------*/
  15. /*
  16. * Display the spy list of addresses and the associated stats
  17. */
  18. static int
  19. print_spy_info(int skfd,
  20. char * ifname,
  21. char * args[],
  22. int count)
  23. {
  24. struct iwreq wrq;
  25. char buffer[(sizeof(struct iw_quality) +
  26. sizeof(struct sockaddr)) * IW_MAX_SPY];
  27. char temp[128];
  28. struct sockaddr * hwa;
  29. struct iw_quality * qual;
  30. iwrange range;
  31. int has_range = 0;
  32. int n;
  33. int i;
  34. /* Avoid "Unused parameter" warning */
  35. args = args; count = count;
  36. /* Collect stats */
  37. wrq.u.data.pointer = (caddr_t) buffer;
  38. wrq.u.data.length = IW_MAX_SPY;
  39. wrq.u.data.flags = 0;
  40. if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
  41. {
  42. fprintf(stderr, "%-8.16s Interface doesn't support wireless statistic collection\n\n", ifname);
  43. return(-1);
  44. }
  45. /* Number of addresses */
  46. n = wrq.u.data.length;
  47. /* Check if we have valid mac address type */
  48. if(iw_check_mac_addr_type(skfd, ifname) < 0)
  49. {
  50. fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n\n", ifname);
  51. return(-2);
  52. }
  53. /* Get range info if we can */
  54. if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
  55. has_range = 1;
  56. /* Display it */
  57. if(n == 0)
  58. printf("%-8.16s No statistics to collect\n", ifname);
  59. else
  60. printf("%-8.16s Statistics collected:\n", ifname);
  61. /* The two lists */
  62. hwa = (struct sockaddr *) buffer;
  63. qual = (struct iw_quality *) (buffer + (sizeof(struct sockaddr) * n));
  64. for(i = 0; i < n; i++)
  65. {
  66. /* Print stats for each address */
  67. printf(" %s : ", iw_saether_ntop(&hwa[i], temp));
  68. iw_print_stats(temp, sizeof(temp), &qual[i], &range, has_range);
  69. printf("%s\n", temp);
  70. }
  71. if((n > 0) && (has_range) && (range.we_version_compiled > 11))
  72. {
  73. iwstats stats;
  74. /* Get /proc/net/wireless */
  75. if(iw_get_stats(skfd, ifname, &stats, &range, has_range) >= 0)
  76. {
  77. iw_print_stats(temp, sizeof(temp), &stats.qual, &range, has_range);
  78. printf(" Link/Cell/AP : %s\n", temp);
  79. /* Display the static data */
  80. iw_print_stats(temp, sizeof(temp),
  81. &range.avg_qual, &range, has_range);
  82. printf(" Typical/Reference : %s\n", temp);
  83. }
  84. }
  85. printf("\n");
  86. return(0);
  87. }
  88. /*------------------------------------------------------------------*/
  89. /*
  90. * Get spy thresholds from the driver and display
  91. */
  92. static int
  93. get_spy_threshold(int skfd, /* The socket */
  94. char * ifname, /* Dev name */
  95. char * args[], /* Command line args */
  96. int count) /* Args count */
  97. {
  98. struct iwreq wrq;
  99. struct iw_thrspy threshold;
  100. iwrange range;
  101. int has_range = 0;
  102. /* Avoid "Unused parameter" warning */
  103. args = args; count = count;
  104. /* Time to send thresholds to the driver */
  105. wrq.u.data.pointer = (caddr_t) &threshold;
  106. wrq.u.data.length = 1;
  107. wrq.u.data.flags = 0;
  108. if(iw_set_ext(skfd, ifname, SIOCGIWTHRSPY, &wrq) < 0)
  109. {
  110. fprintf(stderr, "Interface doesn't support thresholds...\n");
  111. fprintf(stderr, "SIOCGIWTHRSPY: %s\n", strerror(errno));
  112. return(-1);
  113. }
  114. /* Get range info if we can */
  115. if(iw_get_range_info(skfd, ifname, &(range)) >= 0)
  116. has_range = 1;
  117. /* Display thresholds */
  118. if((has_range) && (threshold.low.level))
  119. {
  120. /* If the statistics are in dBm */
  121. if(threshold.low.level > range.max_qual.level)
  122. {
  123. /* Statistics are in dBm (absolute power measurement) */
  124. printf("%-8.16s Low threshold:%d dBm High threshold:%d dBm\n\n",
  125. ifname,
  126. threshold.low.level - 0x100, threshold.high.level - 0x100);
  127. }
  128. else
  129. {
  130. /* Statistics are relative values (0 -> max) */
  131. printf("%-8.16s Low threshold:%d/%d High threshold:%d/%d\n\n",
  132. ifname,
  133. threshold.low.level, range.max_qual.level,
  134. threshold.high.level, range.max_qual.level);
  135. }
  136. }
  137. else
  138. {
  139. /* We can't read the range, so we don't know... */
  140. printf("%-8.16s Low threshold:%d High threshold:%d\n\n",
  141. ifname,
  142. threshold.low.level, threshold.high.level);
  143. }
  144. return(0);
  145. }
  146. /************************* SETTING ROUTINES **************************/
  147. /*------------------------------------------------------------------*/
  148. /*
  149. * Set list of addresses specified on command line in the driver.
  150. */
  151. static int
  152. set_spy_info(int skfd, /* The socket */
  153. char * ifname, /* Dev name */
  154. char * args[], /* Command line args */
  155. int count) /* Args count */
  156. {
  157. struct iwreq wrq;
  158. int i;
  159. int nbr; /* Number of valid addresses */
  160. struct sockaddr hw_address[IW_MAX_SPY];
  161. /* Read command line */
  162. i = 0; /* first arg to read */
  163. nbr = 0; /* Number of args read so far */
  164. /* "off" : disable functionality (set 0 addresses) */
  165. if(!strcmp(args[0], "off"))
  166. i = 1; /* skip the "off" */
  167. else
  168. {
  169. /* "+" : add all addresses already in the driver */
  170. if(!strcmp(args[0], "+"))
  171. {
  172. char buffer[(sizeof(struct iw_quality) +
  173. sizeof(struct sockaddr)) * IW_MAX_SPY];
  174. /* Check if we have valid mac address type */
  175. if(iw_check_mac_addr_type(skfd, ifname) < 0)
  176. {
  177. fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname);
  178. return(-1);
  179. }
  180. wrq.u.data.pointer = (caddr_t) buffer;
  181. wrq.u.data.length = IW_MAX_SPY;
  182. wrq.u.data.flags = 0;
  183. if(iw_get_ext(skfd, ifname, SIOCGIWSPY, &wrq) < 0)
  184. {
  185. fprintf(stderr, "Interface doesn't accept reading addresses...\n");
  186. fprintf(stderr, "SIOCGIWSPY: %s\n", strerror(errno));
  187. return(-1);
  188. }
  189. /* Copy old addresses */
  190. nbr = wrq.u.data.length;
  191. memcpy(hw_address, buffer, nbr * sizeof(struct sockaddr));
  192. i = 1; /* skip the "+" */
  193. }
  194. /* Read other args on command line */
  195. while((i < count) && (nbr < IW_MAX_SPY))
  196. {
  197. /* Get the address and check if the interface supports it */
  198. if(iw_in_addr(skfd, ifname, args[i++], &(hw_address[nbr])) < 0)
  199. continue;
  200. nbr++;
  201. }
  202. /* Check the number of addresses */
  203. if(nbr == 0)
  204. {
  205. fprintf(stderr, "No valid addresses found : exiting...\n");
  206. return(-1);
  207. }
  208. }
  209. /* Check if there is some remaining arguments */
  210. if(i < count)
  211. {
  212. fprintf(stderr, "Got only the first %d arguments, remaining discarded\n", i);
  213. }
  214. /* Time to do send addresses to the driver */
  215. wrq.u.data.pointer = (caddr_t) hw_address;
  216. wrq.u.data.length = nbr;
  217. wrq.u.data.flags = 0;
  218. if(iw_set_ext(skfd, ifname, SIOCSIWSPY, &wrq) < 0)
  219. {
  220. fprintf(stderr, "Interface doesn't accept addresses...\n");
  221. fprintf(stderr, "SIOCSIWSPY: %s\n", strerror(errno));
  222. return(-1);
  223. }
  224. return(0);
  225. }
  226. /*------------------------------------------------------------------*/
  227. /*
  228. * Set spy thresholds in the driver from command line
  229. */
  230. static int
  231. set_spy_threshold(int skfd, /* The socket */
  232. char * ifname, /* Dev name */
  233. char * args[], /* Command line args */
  234. int count) /* Args count */
  235. {
  236. struct iwreq wrq;
  237. struct iw_thrspy threshold;
  238. int low_thr;
  239. int high_thr;
  240. /* Init */
  241. memset(&threshold, '\0', sizeof(threshold));
  242. /* "off" : disable functionality (set 0 addresses) */
  243. if(!strcmp(args[0], "off"))
  244. {
  245. /* Just send null threshold, will disable it */
  246. }
  247. else
  248. {
  249. /* Try to get our threshold */
  250. if(count < 2)
  251. {
  252. fprintf(stderr, "%-8.16s Need two threshold values\n", ifname);
  253. return(-1);
  254. }
  255. if((sscanf(args[0], "%i", &low_thr) != 1) ||
  256. (sscanf(args[1], "%i", &high_thr) != 1))
  257. {
  258. fprintf(stderr, "%-8.16s Invalid threshold values\n", ifname);
  259. return(-1);
  260. }
  261. /* Basic sanity check */
  262. if(high_thr < low_thr)
  263. {
  264. fprintf(stderr, "%-8.16s Inverted threshold range\n", ifname);
  265. return(-1);
  266. }
  267. /* Copy thresholds */
  268. threshold.low.level = low_thr;
  269. threshold.low.updated = 0x2;
  270. threshold.high.level = high_thr;
  271. threshold.high.updated = 0x2;
  272. }
  273. /* Time to send thresholds to the driver */
  274. wrq.u.data.pointer = (caddr_t) &threshold;
  275. wrq.u.data.length = 1;
  276. wrq.u.data.flags = 0;
  277. if(iw_set_ext(skfd, ifname, SIOCSIWTHRSPY, &wrq) < 0)
  278. {
  279. fprintf(stderr, "Interface doesn't accept thresholds...\n");
  280. fprintf(stderr, "SIOCSIWTHRSPY: %s\n", strerror(errno));
  281. return(-1);
  282. }
  283. return(0);
  284. }
  285. /******************************* MAIN ********************************/
  286. /*------------------------------------------------------------------*/
  287. /*
  288. * The main !
  289. */
  290. int
  291. main(int argc,
  292. char ** argv)
  293. {
  294. int skfd; /* generic raw socket desc. */
  295. int goterr = 0;
  296. /* Create a channel to the NET kernel. */
  297. if((skfd = iw_sockets_open()) < 0)
  298. {
  299. perror("socket");
  300. return(-1);
  301. }
  302. /* No argument : show the list of all device + info */
  303. if(argc == 1)
  304. iw_enum_devices(skfd, &print_spy_info, NULL, 0);
  305. else
  306. /* Special cases take one... */
  307. /* Help */
  308. if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help")))
  309. fprintf(stderr, "Usage: iwspy interface [+] [MAC address] [IP address]\n");
  310. else
  311. /* Version */
  312. if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version"))
  313. goterr = iw_print_version_info("iwspy");
  314. else
  315. /* The device name must be the first argument */
  316. /* Name only : show spy list for that device only */
  317. if(argc == 2)
  318. print_spy_info(skfd, argv[1], NULL, 0);
  319. else
  320. /* Special commands */
  321. if(!strcmp(argv[2], "setthr"))
  322. goterr = set_spy_threshold(skfd, argv[1], argv + 3, argc - 3);
  323. else
  324. if(!strcmp(argv[2], "getthr"))
  325. goterr = get_spy_threshold(skfd, argv[1], argv + 3, argc - 3);
  326. else
  327. /* Otherwise, it's a list of address to set in the spy list */
  328. goterr = set_spy_info(skfd, argv[1], argv + 2, argc - 2);
  329. /* Close the socket. */
  330. iw_sockets_close(skfd);
  331. return(goterr);
  332. }