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