selpolltest.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that: (1) source code distributions
  7. * retain the above copyright notice and this paragraph in its entirety, (2)
  8. * distributions including binary code include the above copyright notice and
  9. * this paragraph in its entirety in the documentation or other materials
  10. * provided with the distribution, and (3) all advertising materials mentioning
  11. * features or use of this software display the following acknowledgement:
  12. * ``This product includes software developed by the University of California,
  13. * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14. * the University nor the names of its contributors may be used to endorse
  15. * or promote products derived from this software without specific prior
  16. * written permission.
  17. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20. */
  21. #include "varattrs.h"
  22. #ifndef lint
  23. static const char copyright[] _U_ =
  24. "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
  25. The Regents of the University of California. All rights reserved.\n";
  26. #endif
  27. /*
  28. * Tests how select() and poll() behave on the selectable file descriptor
  29. * for a pcap_t.
  30. *
  31. * This would be significantly different on Windows, as it'd test
  32. * how WaitForMultipleObjects() would work on the event handle for a
  33. * pcap_t.
  34. */
  35. #include <pcap.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <stdarg.h>
  40. #include <unistd.h>
  41. #include <errno.h>
  42. #include <sys/types.h>
  43. #ifdef HAVE_SYS_SELECT_H
  44. #include <sys/select.h>
  45. #else
  46. #include <sys/time.h> /* older UN*Xes */
  47. #endif
  48. #include <poll.h>
  49. #include "pcap/funcattrs.h"
  50. static char *program_name;
  51. /* Forwards */
  52. static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
  53. static void PCAP_NORETURN usage(void);
  54. static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
  55. static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
  56. static char *copy_argv(char **);
  57. static pcap_t *pd;
  58. int
  59. main(int argc, char **argv)
  60. {
  61. register int op;
  62. bpf_u_int32 localnet, netmask;
  63. register char *cp, *cmdbuf, *device;
  64. int doselect, dopoll, dotimeout, dononblock;
  65. const char *mechanism;
  66. struct bpf_program fcode;
  67. char ebuf[PCAP_ERRBUF_SIZE];
  68. pcap_if_t *devlist;
  69. int selectable_fd;
  70. struct timeval *required_timeout;
  71. int status;
  72. int packet_count;
  73. device = NULL;
  74. doselect = 0;
  75. dopoll = 0;
  76. mechanism = NULL;
  77. dotimeout = 0;
  78. dononblock = 0;
  79. if ((cp = strrchr(argv[0], '/')) != NULL)
  80. program_name = cp + 1;
  81. else
  82. program_name = argv[0];
  83. opterr = 0;
  84. while ((op = getopt(argc, argv, "i:sptn")) != -1) {
  85. switch (op) {
  86. case 'i':
  87. device = optarg;
  88. break;
  89. case 's':
  90. doselect = 1;
  91. mechanism = "select() and pcap_dispatch()";
  92. break;
  93. case 'p':
  94. dopoll = 1;
  95. mechanism = "poll() and pcap_dispatch()";
  96. break;
  97. case 't':
  98. dotimeout = 1;
  99. break;
  100. case 'n':
  101. dononblock = 1;
  102. break;
  103. default:
  104. usage();
  105. /* NOTREACHED */
  106. }
  107. }
  108. if (doselect && dopoll) {
  109. fprintf(stderr, "selpolltest: choose select (-s) or poll (-p), but not both\n");
  110. return 1;
  111. }
  112. if (dotimeout && !doselect && !dopoll) {
  113. fprintf(stderr, "selpolltest: timeout (-t) requires select (-s) or poll (-p)\n");
  114. return 1;
  115. }
  116. if (device == NULL) {
  117. if (pcap_findalldevs(&devlist, ebuf) == -1)
  118. error("%s", ebuf);
  119. if (devlist == NULL)
  120. error("no interfaces available for capture");
  121. device = strdup(devlist->name);
  122. pcap_freealldevs(devlist);
  123. }
  124. *ebuf = '\0';
  125. pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
  126. if (pd == NULL)
  127. error("%s", ebuf);
  128. else if (*ebuf)
  129. warning("%s", ebuf);
  130. if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
  131. localnet = 0;
  132. netmask = 0;
  133. warning("%s", ebuf);
  134. }
  135. cmdbuf = copy_argv(&argv[optind]);
  136. if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
  137. error("%s", pcap_geterr(pd));
  138. if (pcap_setfilter(pd, &fcode) < 0)
  139. error("%s", pcap_geterr(pd));
  140. if (doselect || dopoll) {
  141. /*
  142. * We need either an FD on which to do select()/poll()
  143. * or, if there isn't one, a timeout to use in select()/
  144. * poll().
  145. */
  146. selectable_fd = pcap_get_selectable_fd(pd);
  147. if (selectable_fd == -1) {
  148. printf("Listening on %s, using %s, with a timeout\n",
  149. device, mechanism);
  150. required_timeout = pcap_get_required_select_timeout(pd);
  151. if (required_timeout == NULL)
  152. error("select()/poll() isn't supported on %s, even with a timeout",
  153. device);
  154. /*
  155. * As we won't be notified by select() or poll()
  156. * that a read can be done, we'll have to periodically
  157. * try reading from the device every time the required
  158. * timeout expires, and we don't want those attempts
  159. * to block if nothing has arrived in that interval,
  160. * so we want to force non-blocking mode.
  161. */
  162. dononblock = 1;
  163. } else {
  164. printf("Listening on %s, using %s\n", device,
  165. mechanism);
  166. required_timeout = NULL;
  167. }
  168. } else
  169. printf("Listening on %s, using pcap_dispatch()\n", device);
  170. if (dononblock) {
  171. if (pcap_setnonblock(pd, 1, ebuf) == -1)
  172. error("pcap_setnonblock failed: %s", ebuf);
  173. }
  174. if (doselect) {
  175. for (;;) {
  176. fd_set setread, setexcept;
  177. struct timeval seltimeout;
  178. FD_ZERO(&setread);
  179. if (selectable_fd != -1) {
  180. FD_SET(selectable_fd, &setread);
  181. FD_ZERO(&setexcept);
  182. FD_SET(selectable_fd, &setexcept);
  183. }
  184. if (dotimeout) {
  185. seltimeout.tv_sec = 0;
  186. if (required_timeout != NULL &&
  187. required_timeout->tv_usec < 1000)
  188. seltimeout.tv_usec = required_timeout->tv_usec;
  189. else
  190. seltimeout.tv_usec = 1000;
  191. status = select(selectable_fd + 1, &setread,
  192. NULL, &setexcept, &seltimeout);
  193. } else if (required_timeout != NULL) {
  194. seltimeout = *required_timeout;
  195. status = select(selectable_fd + 1, &setread,
  196. NULL, &setexcept, &seltimeout);
  197. } else {
  198. status = select((selectable_fd == -1) ?
  199. 0 : selectable_fd + 1, &setread,
  200. NULL, &setexcept, NULL);
  201. }
  202. if (status == -1) {
  203. printf("Select returns error (%s)\n",
  204. strerror(errno));
  205. } else {
  206. if (selectable_fd == -1) {
  207. if (status != 0)
  208. printf("Select returned a descriptor\n");
  209. } else {
  210. if (status == 0)
  211. printf("Select timed out: ");
  212. else
  213. printf("Select returned a descriptor: ");
  214. if (FD_ISSET(selectable_fd, &setread))
  215. printf("readable, ");
  216. else
  217. printf("not readable, ");
  218. if (FD_ISSET(selectable_fd, &setexcept))
  219. printf("exceptional condition\n");
  220. else
  221. printf("no exceptional condition\n");
  222. }
  223. packet_count = 0;
  224. status = pcap_dispatch(pd, -1, countme,
  225. (u_char *)&packet_count);
  226. if (status < 0)
  227. break;
  228. /*
  229. * Don't report this if we're using a
  230. * required timeout and we got no packets,
  231. * because that could be a very short timeout,
  232. * and we don't want to spam the user with
  233. * a ton of "no packets" reports.
  234. */
  235. if (status != 0 || packet_count != 0 ||
  236. required_timeout != NULL) {
  237. printf("%d packets seen, %d packets counted after select returns\n",
  238. status, packet_count);
  239. }
  240. }
  241. }
  242. } else if (dopoll) {
  243. for (;;) {
  244. struct pollfd fd;
  245. int polltimeout;
  246. fd.fd = selectable_fd;
  247. fd.events = POLLIN;
  248. if (dotimeout)
  249. polltimeout = 1;
  250. else if (required_timeout != NULL &&
  251. required_timeout->tv_usec >= 1000)
  252. polltimeout = required_timeout->tv_usec/1000;
  253. else
  254. polltimeout = -1;
  255. status = poll(&fd, (selectable_fd == -1) ? 0 : 1, polltimeout);
  256. if (status == -1) {
  257. printf("Poll returns error (%s)\n",
  258. strerror(errno));
  259. } else {
  260. if (selectable_fd == -1) {
  261. if (status != 0)
  262. printf("Poll returned a descriptor\n");
  263. } else {
  264. if (status == 0)
  265. printf("Poll timed out\n");
  266. else {
  267. printf("Poll returned a descriptor: ");
  268. if (fd.revents & POLLIN)
  269. printf("readable, ");
  270. else
  271. printf("not readable, ");
  272. if (fd.revents & POLLERR)
  273. printf("exceptional condition, ");
  274. else
  275. printf("no exceptional condition, ");
  276. if (fd.revents & POLLHUP)
  277. printf("disconnect, ");
  278. else
  279. printf("no disconnect, ");
  280. if (fd.revents & POLLNVAL)
  281. printf("invalid\n");
  282. else
  283. printf("not invalid\n");
  284. }
  285. }
  286. packet_count = 0;
  287. status = pcap_dispatch(pd, -1, countme,
  288. (u_char *)&packet_count);
  289. if (status < 0)
  290. break;
  291. /*
  292. * Don't report this if we're using a
  293. * required timeout and we got no packets,
  294. * because that could be a very short timeout,
  295. * and we don't want to spam the user with
  296. * a ton of "no packets" reports.
  297. */
  298. if (status != 0 || packet_count != 0 ||
  299. required_timeout != NULL) {
  300. printf("%d packets seen, %d packets counted after poll returns\n",
  301. status, packet_count);
  302. }
  303. }
  304. }
  305. } else {
  306. for (;;) {
  307. packet_count = 0;
  308. status = pcap_dispatch(pd, -1, countme,
  309. (u_char *)&packet_count);
  310. if (status < 0)
  311. break;
  312. printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
  313. status, packet_count);
  314. }
  315. }
  316. if (status == -2) {
  317. /*
  318. * We got interrupted, so perhaps we didn't
  319. * manage to finish a line we were printing.
  320. * Print an extra newline, just in case.
  321. */
  322. putchar('\n');
  323. }
  324. (void)fflush(stdout);
  325. if (status == -1) {
  326. /*
  327. * Error. Report it.
  328. */
  329. (void)fprintf(stderr, "%s: pcap_loop: %s\n",
  330. program_name, pcap_geterr(pd));
  331. }
  332. pcap_close(pd);
  333. exit(status == -1 ? 1 : 0);
  334. }
  335. static void
  336. countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
  337. {
  338. int *counterp = (int *)user;
  339. (*counterp)++;
  340. }
  341. static void
  342. usage(void)
  343. {
  344. (void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
  345. program_name);
  346. exit(1);
  347. }
  348. /* VARARGS */
  349. static void
  350. error(const char *fmt, ...)
  351. {
  352. va_list ap;
  353. (void)fprintf(stderr, "%s: ", program_name);
  354. va_start(ap, fmt);
  355. (void)vfprintf(stderr, fmt, ap);
  356. va_end(ap);
  357. if (*fmt) {
  358. fmt += strlen(fmt);
  359. if (fmt[-1] != '\n')
  360. (void)fputc('\n', stderr);
  361. }
  362. exit(1);
  363. /* NOTREACHED */
  364. }
  365. /* VARARGS */
  366. static void
  367. warning(const char *fmt, ...)
  368. {
  369. va_list ap;
  370. (void)fprintf(stderr, "%s: WARNING: ", program_name);
  371. va_start(ap, fmt);
  372. (void)vfprintf(stderr, fmt, ap);
  373. va_end(ap);
  374. if (*fmt) {
  375. fmt += strlen(fmt);
  376. if (fmt[-1] != '\n')
  377. (void)fputc('\n', stderr);
  378. }
  379. }
  380. /*
  381. * Copy arg vector into a new buffer, concatenating arguments with spaces.
  382. */
  383. static char *
  384. copy_argv(register char **argv)
  385. {
  386. register char **p;
  387. register u_int len = 0;
  388. char *buf;
  389. char *src, *dst;
  390. p = argv;
  391. if (*p == 0)
  392. return 0;
  393. while (*p)
  394. len += strlen(*p++) + 1;
  395. buf = (char *)malloc(len);
  396. if (buf == NULL)
  397. error("copy_argv: malloc");
  398. p = argv;
  399. dst = buf;
  400. while ((src = *p++) != NULL) {
  401. while ((*dst++ = *src++) != '\0')
  402. ;
  403. dst[-1] = ' ';
  404. }
  405. dst[-1] = '\0';
  406. return buf;
  407. }