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