1*57e22627SCy Schubert /* 2*57e22627SCy Schubert * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 3*57e22627SCy Schubert * The Regents of the University of California. All rights reserved. 4*57e22627SCy Schubert * 5*57e22627SCy Schubert * Redistribution and use in source and binary forms, with or without 6*57e22627SCy Schubert * modification, are permitted provided that: (1) source code distributions 7*57e22627SCy Schubert * retain the above copyright notice and this paragraph in its entirety, (2) 8*57e22627SCy Schubert * distributions including binary code include the above copyright notice and 9*57e22627SCy Schubert * this paragraph in its entirety in the documentation or other materials 10*57e22627SCy Schubert * provided with the distribution, and (3) all advertising materials mentioning 11*57e22627SCy Schubert * features or use of this software display the following acknowledgement: 12*57e22627SCy Schubert * ``This product includes software developed by the University of California, 13*57e22627SCy Schubert * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14*57e22627SCy Schubert * the University nor the names of its contributors may be used to endorse 15*57e22627SCy Schubert * or promote products derived from this software without specific prior 16*57e22627SCy Schubert * written permission. 17*57e22627SCy Schubert * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18*57e22627SCy Schubert * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19*57e22627SCy Schubert * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20*57e22627SCy Schubert */ 21*57e22627SCy Schubert 22*57e22627SCy Schubert #include "varattrs.h" 23*57e22627SCy Schubert 24*57e22627SCy Schubert #ifndef lint 25*57e22627SCy Schubert static const char copyright[] _U_ = 26*57e22627SCy Schubert "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ 27*57e22627SCy Schubert The Regents of the University of California. All rights reserved.\n"; 28*57e22627SCy Schubert #endif 29*57e22627SCy Schubert 30*57e22627SCy Schubert #include <stdio.h> 31*57e22627SCy Schubert #include <stdlib.h> 32*57e22627SCy Schubert #include <string.h> 33*57e22627SCy Schubert #include <stdarg.h> 34*57e22627SCy Schubert #include <limits.h> 35*57e22627SCy Schubert #ifdef _WIN32 36*57e22627SCy Schubert #include <winsock2.h> 37*57e22627SCy Schubert #include <windows.h> 38*57e22627SCy Schubert 39*57e22627SCy Schubert #define THREAD_HANDLE HANDLE 40*57e22627SCy Schubert #define THREAD_FUNC_ARG_TYPE LPVOID 41*57e22627SCy Schubert #define THREAD_FUNC_RETURN_TYPE DWORD __stdcall 42*57e22627SCy Schubert 43*57e22627SCy Schubert #include "getopt.h" 44*57e22627SCy Schubert #else 45*57e22627SCy Schubert #include <pthread.h> 46*57e22627SCy Schubert #include <signal.h> 47*57e22627SCy Schubert #include <unistd.h> 48*57e22627SCy Schubert 49*57e22627SCy Schubert #define THREAD_HANDLE pthread_t 50*57e22627SCy Schubert #define THREAD_FUNC_ARG_TYPE void * 51*57e22627SCy Schubert #define THREAD_FUNC_RETURN_TYPE void * 52*57e22627SCy Schubert #endif 53*57e22627SCy Schubert #include <errno.h> 54*57e22627SCy Schubert #include <sys/types.h> 55*57e22627SCy Schubert 56*57e22627SCy Schubert #include <pcap.h> 57*57e22627SCy Schubert 58*57e22627SCy Schubert #include "pcap/funcattrs.h" 59*57e22627SCy Schubert 60*57e22627SCy Schubert #ifdef _WIN32 61*57e22627SCy Schubert #include "portability.h" 62*57e22627SCy Schubert #endif 63*57e22627SCy Schubert 64*57e22627SCy Schubert static char *program_name; 65*57e22627SCy Schubert 66*57e22627SCy Schubert /* Forwards */ 67*57e22627SCy Schubert static void countme(u_char *, const struct pcap_pkthdr *, const u_char *); 68*57e22627SCy Schubert static void PCAP_NORETURN usage(void); 69*57e22627SCy Schubert static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2); 70*57e22627SCy Schubert static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2); 71*57e22627SCy Schubert static char *copy_argv(char **); 72*57e22627SCy Schubert 73*57e22627SCy Schubert static pcap_t *pd; 74*57e22627SCy Schubert 75*57e22627SCy Schubert #ifdef _WIN32 76*57e22627SCy Schubert /* 77*57e22627SCy Schubert * Generate a string for a Win32-specific error (i.e. an error generated when 78*57e22627SCy Schubert * calling a Win32 API). 79*57e22627SCy Schubert * For errors occurred during standard C calls, we still use pcap_strerror() 80*57e22627SCy Schubert */ 81*57e22627SCy Schubert #define ERRBUF_SIZE 1024 82*57e22627SCy Schubert static const char * 83*57e22627SCy Schubert win32_strerror(DWORD error) 84*57e22627SCy Schubert { 85*57e22627SCy Schubert static char errbuf[ERRBUF_SIZE+1]; 86*57e22627SCy Schubert size_t errlen; 87*57e22627SCy Schubert 88*57e22627SCy Schubert FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, 89*57e22627SCy Schubert ERRBUF_SIZE, NULL); 90*57e22627SCy Schubert 91*57e22627SCy Schubert /* 92*57e22627SCy Schubert * "FormatMessage()" "helpfully" sticks CR/LF at the end of the 93*57e22627SCy Schubert * message. Get rid of it. 94*57e22627SCy Schubert */ 95*57e22627SCy Schubert errlen = strlen(errbuf); 96*57e22627SCy Schubert if (errlen >= 2) { 97*57e22627SCy Schubert errbuf[errlen - 1] = '\0'; 98*57e22627SCy Schubert errbuf[errlen - 2] = '\0'; 99*57e22627SCy Schubert errlen -= 2; 100*57e22627SCy Schubert } 101*57e22627SCy Schubert return errbuf; 102*57e22627SCy Schubert } 103*57e22627SCy Schubert #else 104*57e22627SCy Schubert static void 105*57e22627SCy Schubert catch_sigusr1(int sig _U_) 106*57e22627SCy Schubert { 107*57e22627SCy Schubert printf("Got SIGUSR1\n"); 108*57e22627SCy Schubert } 109*57e22627SCy Schubert #endif 110*57e22627SCy Schubert 111*57e22627SCy Schubert static void 112*57e22627SCy Schubert sleep_secs(int secs) 113*57e22627SCy Schubert { 114*57e22627SCy Schubert #ifdef _WIN32 115*57e22627SCy Schubert Sleep(secs*1000); 116*57e22627SCy Schubert #else 117*57e22627SCy Schubert unsigned secs_remaining; 118*57e22627SCy Schubert 119*57e22627SCy Schubert if (secs <= 0) 120*57e22627SCy Schubert return; 121*57e22627SCy Schubert secs_remaining = secs; 122*57e22627SCy Schubert while (secs_remaining != 0) 123*57e22627SCy Schubert secs_remaining = sleep(secs_remaining); 124*57e22627SCy Schubert #endif 125*57e22627SCy Schubert } 126*57e22627SCy Schubert 127*57e22627SCy Schubert static THREAD_FUNC_RETURN_TYPE 128*57e22627SCy Schubert capture_thread_func(THREAD_FUNC_ARG_TYPE arg) 129*57e22627SCy Schubert { 130*57e22627SCy Schubert char *device = arg; 131*57e22627SCy Schubert int packet_count; 132*57e22627SCy Schubert int status; 133*57e22627SCy Schubert #ifndef _WIN32 134*57e22627SCy Schubert struct sigaction action; 135*57e22627SCy Schubert sigset_t mask; 136*57e22627SCy Schubert #endif 137*57e22627SCy Schubert 138*57e22627SCy Schubert #ifndef _WIN32 139*57e22627SCy Schubert sigemptyset(&mask); 140*57e22627SCy Schubert action.sa_handler = catch_sigusr1; 141*57e22627SCy Schubert action.sa_mask = mask; 142*57e22627SCy Schubert action.sa_flags = 0; 143*57e22627SCy Schubert if (sigaction(SIGUSR1, &action, NULL) == -1) 144*57e22627SCy Schubert error("Can't catch SIGUSR1: %s", strerror(errno)); 145*57e22627SCy Schubert #endif 146*57e22627SCy Schubert 147*57e22627SCy Schubert printf("Listening on %s\n", device); 148*57e22627SCy Schubert for (;;) { 149*57e22627SCy Schubert packet_count = 0; 150*57e22627SCy Schubert status = pcap_dispatch(pd, -1, countme, 151*57e22627SCy Schubert (u_char *)&packet_count); 152*57e22627SCy Schubert if (status < 0) 153*57e22627SCy Schubert break; 154*57e22627SCy Schubert if (status != 0) { 155*57e22627SCy Schubert printf("%d packets seen, %d packets counted after pcap_dispatch returns\n", 156*57e22627SCy Schubert status, packet_count); 157*57e22627SCy Schubert } else 158*57e22627SCy Schubert printf("No packets seen by pcap_dispatch\n"); 159*57e22627SCy Schubert } 160*57e22627SCy Schubert if (status == -2) { 161*57e22627SCy Schubert /* 162*57e22627SCy Schubert * We got interrupted, so perhaps we didn't 163*57e22627SCy Schubert * manage to finish a line we were printing. 164*57e22627SCy Schubert * Print an extra newline, just in case. 165*57e22627SCy Schubert */ 166*57e22627SCy Schubert putchar('\n'); 167*57e22627SCy Schubert printf("Loop got broken\n"); 168*57e22627SCy Schubert } 169*57e22627SCy Schubert (void)fflush(stdout); 170*57e22627SCy Schubert if (status == -1) { 171*57e22627SCy Schubert /* 172*57e22627SCy Schubert * Error. Report it. 173*57e22627SCy Schubert */ 174*57e22627SCy Schubert (void)fprintf(stderr, "%s: pcap_loop: %s\n", 175*57e22627SCy Schubert program_name, pcap_geterr(pd)); 176*57e22627SCy Schubert } 177*57e22627SCy Schubert return 0; 178*57e22627SCy Schubert } 179*57e22627SCy Schubert 180*57e22627SCy Schubert int 181*57e22627SCy Schubert main(int argc, char **argv) 182*57e22627SCy Schubert { 183*57e22627SCy Schubert register int op; 184*57e22627SCy Schubert register char *cp, *cmdbuf, *device; 185*57e22627SCy Schubert int immediate = 0; 186*57e22627SCy Schubert pcap_if_t *devlist; 187*57e22627SCy Schubert bpf_u_int32 localnet, netmask; 188*57e22627SCy Schubert struct bpf_program fcode; 189*57e22627SCy Schubert char ebuf[PCAP_ERRBUF_SIZE]; 190*57e22627SCy Schubert int status; 191*57e22627SCy Schubert THREAD_HANDLE capture_thread; 192*57e22627SCy Schubert #ifndef _WIN32 193*57e22627SCy Schubert void *retval; 194*57e22627SCy Schubert #endif 195*57e22627SCy Schubert 196*57e22627SCy Schubert device = NULL; 197*57e22627SCy Schubert if ((cp = strrchr(argv[0], '/')) != NULL) 198*57e22627SCy Schubert program_name = cp + 1; 199*57e22627SCy Schubert else 200*57e22627SCy Schubert program_name = argv[0]; 201*57e22627SCy Schubert 202*57e22627SCy Schubert opterr = 0; 203*57e22627SCy Schubert while ((op = getopt(argc, argv, "i:")) != -1) { 204*57e22627SCy Schubert switch (op) { 205*57e22627SCy Schubert 206*57e22627SCy Schubert case 'i': 207*57e22627SCy Schubert device = optarg; 208*57e22627SCy Schubert break; 209*57e22627SCy Schubert 210*57e22627SCy Schubert default: 211*57e22627SCy Schubert usage(); 212*57e22627SCy Schubert /* NOTREACHED */ 213*57e22627SCy Schubert } 214*57e22627SCy Schubert } 215*57e22627SCy Schubert 216*57e22627SCy Schubert if (device == NULL) { 217*57e22627SCy Schubert if (pcap_findalldevs(&devlist, ebuf) == -1) 218*57e22627SCy Schubert error("%s", ebuf); 219*57e22627SCy Schubert if (devlist == NULL) 220*57e22627SCy Schubert error("no interfaces available for capture"); 221*57e22627SCy Schubert device = strdup(devlist->name); 222*57e22627SCy Schubert pcap_freealldevs(devlist); 223*57e22627SCy Schubert } 224*57e22627SCy Schubert *ebuf = '\0'; 225*57e22627SCy Schubert pd = pcap_create(device, ebuf); 226*57e22627SCy Schubert if (pd == NULL) 227*57e22627SCy Schubert error("%s", ebuf); 228*57e22627SCy Schubert status = pcap_set_snaplen(pd, 65535); 229*57e22627SCy Schubert if (status != 0) 230*57e22627SCy Schubert error("%s: pcap_set_snaplen failed: %s", 231*57e22627SCy Schubert device, pcap_statustostr(status)); 232*57e22627SCy Schubert if (immediate) { 233*57e22627SCy Schubert status = pcap_set_immediate_mode(pd, 1); 234*57e22627SCy Schubert if (status != 0) 235*57e22627SCy Schubert error("%s: pcap_set_immediate_mode failed: %s", 236*57e22627SCy Schubert device, pcap_statustostr(status)); 237*57e22627SCy Schubert } 238*57e22627SCy Schubert status = pcap_set_timeout(pd, 5*60*1000); 239*57e22627SCy Schubert if (status != 0) 240*57e22627SCy Schubert error("%s: pcap_set_timeout failed: %s", 241*57e22627SCy Schubert device, pcap_statustostr(status)); 242*57e22627SCy Schubert status = pcap_activate(pd); 243*57e22627SCy Schubert if (status < 0) { 244*57e22627SCy Schubert /* 245*57e22627SCy Schubert * pcap_activate() failed. 246*57e22627SCy Schubert */ 247*57e22627SCy Schubert error("%s: %s\n(%s)", device, 248*57e22627SCy Schubert pcap_statustostr(status), pcap_geterr(pd)); 249*57e22627SCy Schubert } else if (status > 0) { 250*57e22627SCy Schubert /* 251*57e22627SCy Schubert * pcap_activate() succeeded, but it's warning us 252*57e22627SCy Schubert * of a problem it had. 253*57e22627SCy Schubert */ 254*57e22627SCy Schubert warning("%s: %s\n(%s)", device, 255*57e22627SCy Schubert pcap_statustostr(status), pcap_geterr(pd)); 256*57e22627SCy Schubert } 257*57e22627SCy Schubert if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 258*57e22627SCy Schubert localnet = 0; 259*57e22627SCy Schubert netmask = 0; 260*57e22627SCy Schubert warning("%s", ebuf); 261*57e22627SCy Schubert } 262*57e22627SCy Schubert cmdbuf = copy_argv(&argv[optind]); 263*57e22627SCy Schubert 264*57e22627SCy Schubert if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0) 265*57e22627SCy Schubert error("%s", pcap_geterr(pd)); 266*57e22627SCy Schubert 267*57e22627SCy Schubert if (pcap_setfilter(pd, &fcode) < 0) 268*57e22627SCy Schubert error("%s", pcap_geterr(pd)); 269*57e22627SCy Schubert 270*57e22627SCy Schubert #ifdef _WIN32 271*57e22627SCy Schubert capture_thread = CreateThread(NULL, 0, capture_thread_func, device, 272*57e22627SCy Schubert 0, NULL); 273*57e22627SCy Schubert if (capture_thread == NULL) 274*57e22627SCy Schubert error("Can't create capture thread: %s", 275*57e22627SCy Schubert win32_strerror(GetLastError())); 276*57e22627SCy Schubert #else 277*57e22627SCy Schubert status = pthread_create(&capture_thread, NULL, capture_thread_func, 278*57e22627SCy Schubert device); 279*57e22627SCy Schubert if (status != 0) 280*57e22627SCy Schubert error("Can't create capture thread: %s", strerror(status)); 281*57e22627SCy Schubert #endif 282*57e22627SCy Schubert sleep_secs(60); 283*57e22627SCy Schubert pcap_breakloop(pd); 284*57e22627SCy Schubert #ifdef _WIN32 285*57e22627SCy Schubert printf("Setting event\n"); 286*57e22627SCy Schubert if (!SetEvent(pcap_getevent(pd))) 287*57e22627SCy Schubert error("Can't set event for pcap_t: %s", 288*57e22627SCy Schubert win32_strerror(GetLastError())); 289*57e22627SCy Schubert if (WaitForSingleObject(capture_thread, INFINITE) == WAIT_FAILED) 290*57e22627SCy Schubert error("Wait for thread termination failed: %s", 291*57e22627SCy Schubert win32_strerror(GetLastError())); 292*57e22627SCy Schubert CloseHandle(capture_thread); 293*57e22627SCy Schubert #else 294*57e22627SCy Schubert printf("Sending SIGUSR1\n"); 295*57e22627SCy Schubert status = pthread_kill(capture_thread, SIGUSR1); 296*57e22627SCy Schubert if (status != 0) 297*57e22627SCy Schubert warning("Can't interrupt capture thread: %s", strerror(status)); 298*57e22627SCy Schubert status = pthread_join(capture_thread, &retval); 299*57e22627SCy Schubert if (status != 0) 300*57e22627SCy Schubert error("Wait for thread termination failed: %s", 301*57e22627SCy Schubert strerror(status)); 302*57e22627SCy Schubert #endif 303*57e22627SCy Schubert 304*57e22627SCy Schubert pcap_close(pd); 305*57e22627SCy Schubert pcap_freecode(&fcode); 306*57e22627SCy Schubert exit(status == -1 ? 1 : 0); 307*57e22627SCy Schubert } 308*57e22627SCy Schubert 309*57e22627SCy Schubert static void 310*57e22627SCy Schubert countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_) 311*57e22627SCy Schubert { 312*57e22627SCy Schubert int *counterp = (int *)user; 313*57e22627SCy Schubert 314*57e22627SCy Schubert (*counterp)++; 315*57e22627SCy Schubert } 316*57e22627SCy Schubert 317*57e22627SCy Schubert static void 318*57e22627SCy Schubert usage(void) 319*57e22627SCy Schubert { 320*57e22627SCy Schubert (void)fprintf(stderr, "Usage: %s [ -m ] [ -i interface ] [ -t timeout] [expression]\n", 321*57e22627SCy Schubert program_name); 322*57e22627SCy Schubert exit(1); 323*57e22627SCy Schubert } 324*57e22627SCy Schubert 325*57e22627SCy Schubert /* VARARGS */ 326*57e22627SCy Schubert static void 327*57e22627SCy Schubert error(const char *fmt, ...) 328*57e22627SCy Schubert { 329*57e22627SCy Schubert va_list ap; 330*57e22627SCy Schubert 331*57e22627SCy Schubert (void)fprintf(stderr, "%s: ", program_name); 332*57e22627SCy Schubert va_start(ap, fmt); 333*57e22627SCy Schubert (void)vfprintf(stderr, fmt, ap); 334*57e22627SCy Schubert va_end(ap); 335*57e22627SCy Schubert if (*fmt) { 336*57e22627SCy Schubert fmt += strlen(fmt); 337*57e22627SCy Schubert if (fmt[-1] != '\n') 338*57e22627SCy Schubert (void)fputc('\n', stderr); 339*57e22627SCy Schubert } 340*57e22627SCy Schubert exit(1); 341*57e22627SCy Schubert /* NOTREACHED */ 342*57e22627SCy Schubert } 343*57e22627SCy Schubert 344*57e22627SCy Schubert /* VARARGS */ 345*57e22627SCy Schubert static void 346*57e22627SCy Schubert warning(const char *fmt, ...) 347*57e22627SCy Schubert { 348*57e22627SCy Schubert va_list ap; 349*57e22627SCy Schubert 350*57e22627SCy Schubert (void)fprintf(stderr, "%s: WARNING: ", program_name); 351*57e22627SCy Schubert va_start(ap, fmt); 352*57e22627SCy Schubert (void)vfprintf(stderr, fmt, ap); 353*57e22627SCy Schubert va_end(ap); 354*57e22627SCy Schubert if (*fmt) { 355*57e22627SCy Schubert fmt += strlen(fmt); 356*57e22627SCy Schubert if (fmt[-1] != '\n') 357*57e22627SCy Schubert (void)fputc('\n', stderr); 358*57e22627SCy Schubert } 359*57e22627SCy Schubert } 360*57e22627SCy Schubert 361*57e22627SCy Schubert /* 362*57e22627SCy Schubert * Copy arg vector into a new buffer, concatenating arguments with spaces. 363*57e22627SCy Schubert */ 364*57e22627SCy Schubert static char * 365*57e22627SCy Schubert copy_argv(register char **argv) 366*57e22627SCy Schubert { 367*57e22627SCy Schubert register char **p; 368*57e22627SCy Schubert register u_int len = 0; 369*57e22627SCy Schubert char *buf; 370*57e22627SCy Schubert char *src, *dst; 371*57e22627SCy Schubert 372*57e22627SCy Schubert p = argv; 373*57e22627SCy Schubert if (*p == 0) 374*57e22627SCy Schubert return 0; 375*57e22627SCy Schubert 376*57e22627SCy Schubert while (*p) 377*57e22627SCy Schubert len += strlen(*p++) + 1; 378*57e22627SCy Schubert 379*57e22627SCy Schubert buf = (char *)malloc(len); 380*57e22627SCy Schubert if (buf == NULL) 381*57e22627SCy Schubert error("copy_argv: malloc"); 382*57e22627SCy Schubert 383*57e22627SCy Schubert p = argv; 384*57e22627SCy Schubert dst = buf; 385*57e22627SCy Schubert while ((src = *p++) != NULL) { 386*57e22627SCy Schubert while ((*dst++ = *src++) != '\0') 387*57e22627SCy Schubert ; 388*57e22627SCy Schubert dst[-1] = ' '; 389*57e22627SCy Schubert } 390*57e22627SCy Schubert dst[-1] = '\0'; 391*57e22627SCy Schubert 392*57e22627SCy Schubert return buf; 393*57e22627SCy Schubert } 394