Home | History | Annotate | Line # | Download | only in testprogs
      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 /*
     25  * Tests for pcap_set_nonblock / pcap_get_nonblock:
     26  * - idempotency
     27  * - set/get are symmetric
     28  * - get returns the same before/after activate
     29  * - pcap_breakloop works after setting nonblock on and then off
     30  *
     31  * Really this is meant to
     32  * be run manually under strace, to check for extra
     33  * calls to eventfd or close.
     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 <sys/types.h>
     42 #include <sys/stat.h>
     43 #include <fcntl.h>
     44 
     45 static pcap_t *pd;
     46 static char *program_name = "nonblocktest";
     47 /* Forwards */
     48 static void PCAP_NORETURN usage(void);
     49 static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
     50 static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
     51 
     52 /* VARARGS */
     53 static void
     54 error(const char *fmt, ...)
     55 {
     56 	va_list ap;
     57 
     58 	(void)fprintf(stderr, "%s: ", program_name);
     59 	va_start(ap, fmt);
     60 	(void)vfprintf(stderr, fmt, ap);
     61 	va_end(ap);
     62 	if (*fmt) {
     63 		fmt += strlen(fmt);
     64 		if (fmt[-1] != '\n')
     65 			(void)fputc('\n', stderr);
     66 	}
     67 	exit(1);
     68 	/* NOTREACHED */
     69 }
     70 
     71 /* VARARGS */
     72 static void
     73 warning(const char *fmt, ...)
     74 {
     75 	va_list ap;
     76 
     77 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
     78 	va_start(ap, fmt);
     79 	(void)vfprintf(stderr, fmt, ap);
     80 	va_end(ap);
     81 	if (*fmt) {
     82 		fmt += strlen(fmt);
     83 		if (fmt[-1] != '\n')
     84 			(void)fputc('\n', stderr);
     85 	}
     86 }
     87 
     88 static void
     89 usage(void)
     90 {
     91 	(void)fprintf(stderr, "Usage: %s [ -i interface ]\n",
     92 	    program_name);
     93 	exit(1);
     94 }
     95 
     96 static void
     97 breakme(u_char *user _U_, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
     98 {
     99 	warning("using pcap_breakloop()");
    100 	pcap_breakloop(pd);
    101 }
    102 
    103 int
    104 main(int argc, char **argv)
    105 {
    106 	int status, op, i, ret;
    107 	char *device;
    108 	pcap_if_t *devlist;
    109 	char ebuf[PCAP_ERRBUF_SIZE];
    110 
    111 	device = NULL;
    112 	while ((op = getopt(argc, argv, "i:sptnq")) != -1) {
    113 		switch (op) {
    114 
    115 		case 'i':
    116 			device = optarg;
    117 			break;
    118 
    119 		default:
    120 			usage();
    121 			/* NOTREACHED */
    122 		}
    123 	}
    124 	if (device == NULL) {
    125 		if (pcap_findalldevs(&devlist, ebuf) == -1)
    126 			error("%s", ebuf);
    127 		if (devlist == NULL)
    128 			error("no interfaces available for capture");
    129 		device = strdup(devlist->name);
    130 		warning("listening on %s", device);
    131 		pcap_freealldevs(devlist);
    132 	}
    133 	*ebuf = '\0';
    134 	pd = pcap_create(device, ebuf);
    135 	if (pd == NULL)
    136 		error("%s", ebuf);
    137 	else if (*ebuf)
    138 		warning("%s", ebuf);
    139 	/* set nonblock before activate */
    140 	if (pcap_setnonblock(pd, 1, ebuf) < 0)
    141 		error("pcap_setnonblock failed: %s", ebuf);
    142 	/* getnonblock just returns "not activated yet" */
    143 	ret = pcap_getnonblock(pd, ebuf);
    144 	if (ret != PCAP_ERROR_NOT_ACTIVATED)
    145 		error("pcap_getnonblock unexpectedly succeeded");
    146 	if ((status = pcap_activate(pd)) < 0)
    147 		error("pcap_activate failed");
    148 	ret = pcap_getnonblock(pd, ebuf);
    149 	if (ret != 1)
    150 		error( "pcap_getnonblock did not return nonblocking" );
    151 
    152 	/* Set nonblock multiple times, ensure with strace that it's a noop */
    153 	for (i=0; i<10; i++) {
    154 		if (pcap_setnonblock(pd, 1, ebuf) < 0)
    155 			error("pcap_setnonblock failed: %s", ebuf);
    156 		ret = pcap_getnonblock(pd, ebuf);
    157 		if (ret != 1)
    158 			error( "pcap_getnonblock did not return nonblocking" );
    159 	}
    160 	/* Set block multiple times, ensure with strace that it's a noop */
    161 	for (i=0; i<10; i++) {
    162 		if (pcap_setnonblock(pd, 0, ebuf) < 0)
    163 			error("pcap_setnonblock failed: %s", ebuf);
    164 		ret = pcap_getnonblock(pd, ebuf);
    165 		if (ret != 0)
    166 			error( "pcap_getnonblock did not return blocking" );
    167 	}
    168 
    169 	/* Now pcap_loop forever, with a callback that
    170 	 * uses pcap_breakloop to get out of forever */
    171 	pcap_loop(pd, -1, breakme, NULL);
    172 
    173         /* Now test that pcap_setnonblock fails if we can't open the
    174          * eventfd. */
    175         if (pcap_setnonblock(pd, 1, ebuf) < 0)
    176                 error("pcap_setnonblock failed: %s", ebuf);
    177         while (1) {
    178                 ret = open("/dev/null", O_RDONLY);
    179                 if (ret < 0)
    180                         break;
    181         }
    182         ret = pcap_setnonblock(pd, 0, ebuf);
    183         if (ret == 0)
    184                 error("pcap_setnonblock succeeded even though file table is full");
    185         else
    186                 warning("pcap_setnonblock failed as expected: %s", ebuf);
    187 }
    188