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 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <stdarg.h> 34 #include <limits.h> 35 #ifdef _WIN32 36 #include "getopt.h" 37 #else 38 #include <unistd.h> 39 #endif 40 #include <errno.h> 41 #include <sys/types.h> 42 43 #include <pcap.h> 44 45 #include "pcap/funcattrs.h" 46 47 #ifdef _WIN32 48 #include "portability.h" 49 #endif 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 register char *cp, *cmdbuf, *device; 67 long longarg; 68 char *p; 69 int timeout = 1000; 70 int immediate = 0; 71 int nonblock = 0; 72 pcap_if_t *devlist; 73 bpf_u_int32 localnet, netmask; 74 struct bpf_program fcode; 75 char ebuf[PCAP_ERRBUF_SIZE]; 76 int status; 77 int packet_count; 78 79 device = NULL; 80 if ((cp = strrchr(argv[0], '/')) != NULL) 81 program_name = cp + 1; 82 else 83 program_name = argv[0]; 84 85 opterr = 0; 86 while ((op = getopt(argc, argv, "i:mnt:")) != -1) { 87 switch (op) { 88 89 case 'i': 90 device = optarg; 91 break; 92 93 case 'm': 94 immediate = 1; 95 break; 96 97 case 'n': 98 nonblock = 1; 99 break; 100 101 case 't': 102 longarg = strtol(optarg, &p, 10); 103 if (p == optarg || *p != '\0') { 104 error("Timeout value \"%s\" is not a number", 105 optarg); 106 /* NOTREACHED */ 107 } 108 if (longarg < 0) { 109 error("Timeout value %ld is negative", longarg); 110 /* NOTREACHED */ 111 } 112 if (longarg > INT_MAX) { 113 error("Timeout value %ld is too large (> %d)", 114 longarg, INT_MAX); 115 /* NOTREACHED */ 116 } 117 timeout = (int)longarg; 118 break; 119 120 default: 121 usage(); 122 /* NOTREACHED */ 123 } 124 } 125 126 if (device == NULL) { 127 if (pcap_findalldevs(&devlist, ebuf) == -1) 128 error("%s", ebuf); 129 if (devlist == NULL) 130 error("no interfaces available for capture"); 131 device = strdup(devlist->name); 132 pcap_freealldevs(devlist); 133 } 134 *ebuf = '\0'; 135 pd = pcap_create(device, ebuf); 136 if (pd == NULL) 137 error("%s", ebuf); 138 status = pcap_set_snaplen(pd, 65535); 139 if (status != 0) 140 error("%s: pcap_set_snaplen failed: %s", 141 device, pcap_statustostr(status)); 142 if (immediate) { 143 status = pcap_set_immediate_mode(pd, 1); 144 if (status != 0) 145 error("%s: pcap_set_immediate_mode failed: %s", 146 device, pcap_statustostr(status)); 147 } 148 status = pcap_set_timeout(pd, timeout); 149 if (status != 0) 150 error("%s: pcap_set_timeout failed: %s", 151 device, pcap_statustostr(status)); 152 status = pcap_activate(pd); 153 if (status < 0) { 154 /* 155 * pcap_activate() failed. 156 */ 157 error("%s: %s\n(%s)", device, 158 pcap_statustostr(status), pcap_geterr(pd)); 159 } else if (status > 0) { 160 /* 161 * pcap_activate() succeeded, but it's warning us 162 * of a problem it had. 163 */ 164 warning("%s: %s\n(%s)", device, 165 pcap_statustostr(status), pcap_geterr(pd)); 166 } 167 if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 168 localnet = 0; 169 netmask = 0; 170 warning("%s", ebuf); 171 } 172 cmdbuf = copy_argv(&argv[optind]); 173 174 if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0) 175 error("%s", pcap_geterr(pd)); 176 177 if (pcap_setfilter(pd, &fcode) < 0) 178 error("%s", pcap_geterr(pd)); 179 if (pcap_setnonblock(pd, nonblock, ebuf) == -1) 180 error("pcap_setnonblock failed: %s", ebuf); 181 printf("Listening on %s\n", device); 182 for (;;) { 183 packet_count = 0; 184 status = pcap_dispatch(pd, -1, countme, 185 (u_char *)&packet_count); 186 if (status < 0) 187 break; 188 if (status != 0) { 189 printf("%d packets seen, %d packets counted after pcap_dispatch returns\n", 190 status, packet_count); 191 } 192 } 193 if (status == -2) { 194 /* 195 * We got interrupted, so perhaps we didn't 196 * manage to finish a line we were printing. 197 * Print an extra newline, just in case. 198 */ 199 putchar('\n'); 200 } 201 (void)fflush(stdout); 202 if (status == -1) { 203 /* 204 * Error. Report it. 205 */ 206 (void)fprintf(stderr, "%s: pcap_loop: %s\n", 207 program_name, pcap_geterr(pd)); 208 } 209 pcap_close(pd); 210 pcap_freecode(&fcode); 211 free(cmdbuf); 212 exit(status == -1 ? 1 : 0); 213 } 214 215 static void 216 countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_) 217 { 218 int *counterp = (int *)user; 219 220 (*counterp)++; 221 } 222 223 static void 224 usage(void) 225 { 226 (void)fprintf(stderr, "Usage: %s [ -mn ] [ -i interface ] [ -t timeout] [expression]\n", 227 program_name); 228 exit(1); 229 } 230 231 /* VARARGS */ 232 static void 233 error(const char *fmt, ...) 234 { 235 va_list ap; 236 237 (void)fprintf(stderr, "%s: ", program_name); 238 va_start(ap, fmt); 239 (void)vfprintf(stderr, fmt, ap); 240 va_end(ap); 241 if (*fmt) { 242 fmt += strlen(fmt); 243 if (fmt[-1] != '\n') 244 (void)fputc('\n', stderr); 245 } 246 exit(1); 247 /* NOTREACHED */ 248 } 249 250 /* VARARGS */ 251 static void 252 warning(const char *fmt, ...) 253 { 254 va_list ap; 255 256 (void)fprintf(stderr, "%s: WARNING: ", program_name); 257 va_start(ap, fmt); 258 (void)vfprintf(stderr, fmt, ap); 259 va_end(ap); 260 if (*fmt) { 261 fmt += strlen(fmt); 262 if (fmt[-1] != '\n') 263 (void)fputc('\n', stderr); 264 } 265 } 266 267 /* 268 * Copy arg vector into a new buffer, concatenating arguments with spaces. 269 */ 270 static char * 271 copy_argv(register char **argv) 272 { 273 register char **p; 274 register u_int len = 0; 275 char *buf; 276 char *src, *dst; 277 278 p = argv; 279 if (*p == 0) 280 return 0; 281 282 while (*p) 283 len += strlen(*p++) + 1; 284 285 buf = (char *)malloc(len); 286 if (buf == NULL) 287 error("copy_argv: malloc"); 288 289 p = argv; 290 dst = buf; 291 while ((src = *p++) != NULL) { 292 while ((*dst++ = *src++) != '\0') 293 ; 294 dst[-1] = ' '; 295 } 296 dst[-1] = '\0'; 297 298 return buf; 299 } 300