Home | History | Annotate | Download | only in tests
      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 #ifndef lint
     23 static const char copyright[] =
     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 #include <pcap.h>
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <stdarg.h>
     33 #include <unistd.h>
     34 #include <errno.h>
     35 #include <sys/types.h>
     36 #include <sys/select.h>
     37 #include <poll.h>
     38 
     39 char *program_name;
     40 
     41 /* Forwards */
     42 static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
     43 static void usage(void) __attribute__((noreturn));
     44 static void error(const char *, ...);
     45 static void warning(const char *, ...);
     46 static char *copy_argv(char **);
     47 
     48 static pcap_t *pd;
     49 
     50 extern int optind;
     51 extern int opterr;
     52 extern char *optarg;
     53 
     54 int
     55 main(int argc, char **argv)
     56 {
     57 	register int op;
     58 	bpf_u_int32 localnet, netmask;
     59 	register char *cp, *cmdbuf, *device;
     60 	struct bpf_program fcode;
     61 	char ebuf[PCAP_ERRBUF_SIZE];
     62 	int status;
     63 	int packet_count;
     64 
     65 	device = NULL;
     66 	if ((cp = strrchr(argv[0], '/')) != NULL)
     67 		program_name = cp + 1;
     68 	else
     69 		program_name = argv[0];
     70 
     71 	opterr = 0;
     72 	while ((op = getopt(argc, argv, "i:")) != -1) {
     73 		switch (op) {
     74 
     75 		case 'i':
     76 			device = optarg;
     77 			break;
     78 
     79 		default:
     80 			usage();
     81 			/* NOTREACHED */
     82 		}
     83 	}
     84 
     85 	if (device == NULL) {
     86 		device = pcap_lookupdev(ebuf);
     87 		if (device == NULL)
     88 			error("%s", ebuf);
     89 	}
     90 	*ebuf = '\0';
     91 	pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
     92 	if (pd == NULL)
     93 		error("%s", ebuf);
     94 	else if (*ebuf)
     95 		warning("%s", ebuf);
     96 	if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
     97 		localnet = 0;
     98 		netmask = 0;
     99 		warning("%s", ebuf);
    100 	}
    101 	cmdbuf = copy_argv(&argv[optind]);
    102 
    103 	if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
    104 		error("%s", pcap_geterr(pd));
    105 
    106 	if (pcap_setfilter(pd, &fcode) < 0)
    107 		error("%s", pcap_geterr(pd));
    108 	if (pcap_setnonblock(pd, 1, ebuf) == -1)
    109 		error("pcap_setnonblock failed: %s", ebuf);
    110 	printf("Listening on %s\n", device);
    111 	for (;;) {
    112 		packet_count = 0;
    113 		status = pcap_dispatch(pd, -1, countme,
    114 		    (u_char *)&packet_count);
    115 		if (status < 0)
    116 			break;
    117 		if (status != 0) {
    118 			printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
    119 			    status, packet_count);
    120 		}
    121 	}
    122 	if (status == -2) {
    123 		/*
    124 		 * We got interrupted, so perhaps we didn't
    125 		 * manage to finish a line we were printing.
    126 		 * Print an extra newline, just in case.
    127 		 */
    128 		putchar('\n');
    129 	}
    130 	(void)fflush(stdout);
    131 	if (status == -1) {
    132 		/*
    133 		 * Error.  Report it.
    134 		 */
    135 		(void)fprintf(stderr, "%s: pcap_loop: %s\n",
    136 		    program_name, pcap_geterr(pd));
    137 	}
    138 	pcap_close(pd);
    139 	exit(status == -1 ? 1 : 0);
    140 }
    141 
    142 static void
    143 countme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
    144 {
    145 	int *counterp = (int *)user;
    146 
    147 	(*counterp)++;
    148 }
    149 
    150 static void
    151 usage(void)
    152 {
    153 	(void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
    154 	    program_name);
    155 	exit(1);
    156 }
    157 
    158 /* VARARGS */
    159 static void
    160 error(const char *fmt, ...)
    161 {
    162 	va_list ap;
    163 
    164 	(void)fprintf(stderr, "%s: ", program_name);
    165 	va_start(ap, fmt);
    166 	(void)vfprintf(stderr, fmt, ap);
    167 	va_end(ap);
    168 	if (*fmt) {
    169 		fmt += strlen(fmt);
    170 		if (fmt[-1] != '\n')
    171 			(void)fputc('\n', stderr);
    172 	}
    173 	exit(1);
    174 	/* NOTREACHED */
    175 }
    176 
    177 /* VARARGS */
    178 static void
    179 warning(const char *fmt, ...)
    180 {
    181 	va_list ap;
    182 
    183 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
    184 	va_start(ap, fmt);
    185 	(void)vfprintf(stderr, fmt, ap);
    186 	va_end(ap);
    187 	if (*fmt) {
    188 		fmt += strlen(fmt);
    189 		if (fmt[-1] != '\n')
    190 			(void)fputc('\n', stderr);
    191 	}
    192 }
    193 
    194 /*
    195  * Copy arg vector into a new buffer, concatenating arguments with spaces.
    196  */
    197 static char *
    198 copy_argv(register char **argv)
    199 {
    200 	register char **p;
    201 	register u_int len = 0;
    202 	char *buf;
    203 	char *src, *dst;
    204 
    205 	p = argv;
    206 	if (*p == 0)
    207 		return 0;
    208 
    209 	while (*p)
    210 		len += strlen(*p++) + 1;
    211 
    212 	buf = (char *)malloc(len);
    213 	if (buf == NULL)
    214 		error("copy_argv: malloc");
    215 
    216 	p = argv;
    217 	dst = buf;
    218 	while ((src = *p++) != NULL) {
    219 		while ((*dst++ = *src++) != '\0')
    220 			;
    221 		dst[-1] = ' ';
    222 	}
    223 	dst[-1] = '\0';
    224 
    225 	return buf;
    226 }
    227