/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "varattrs.h"
#ifndef lint
static const char copyright[] _U_ =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
The Regents of the University of California. All rights reserved.\n";
#endif
#ifdef _WIN32
/*
* Generate a string for a Win32-specific error (i.e. an error generated when
* calling a Win32 API).
* For errors occurred during standard C calls, we still use pcap_strerror()
*/
#define ERRBUF_SIZE 1024
static const char *
win32_strerror(DWORD error)
{
static char errbuf[ERRBUF_SIZE+1];
size_t errlen;
printf("Listening on %s\n", device);
for (;;) {
packet_count = 0;
status = pcap_dispatch(pd, -1, countme,
(u_char *)&packet_count);
if (status < 0)
break;
if (status != 0) {
printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
status, packet_count);
} else
printf("No packets seen by pcap_dispatch\n");
}
if (status == PCAP_ERROR_BREAK) {
/*
* We got interrupted, so perhaps we didn't
* manage to finish a line we were printing.
* Print an extra newline, just in case.
*/
putchar('\n');
printf("Loop got broken\n");
}
(void)fflush(stdout);
if (status == PCAP_ERROR) {
/*
* Error. Report it.
*/
(void)fprintf(stderr, "%s: pcap_dispatch: %s\n",
program_name, pcap_geterr(pd));
}
return 0;
}
int
main(int argc, char **argv)
{
register int op;
register char *cp, *cmdbuf, *device;
int do_wakeup = 1;
pcap_if_t *devlist;
bpf_u_int32 localnet, netmask;
struct bpf_program fcode;
char ebuf[PCAP_ERRBUF_SIZE];
int status;
THREAD_HANDLE capture_thread;
#ifndef _WIN32
void *retval;
#endif
if (device == NULL) {
if (pcap_findalldevs(&devlist, ebuf) == -1)
error("%s", ebuf);
if (devlist == NULL)
error("no interfaces available for capture");
device = strdup(devlist->name);
pcap_freealldevs(devlist);
}
*ebuf = '\0';
pd = pcap_create(device, ebuf);
if (pd == NULL)
error("%s", ebuf);
status = pcap_set_snaplen(pd, 65535);
if (status != 0)
error("%s: pcap_set_snaplen failed: %s",
device, pcap_statustostr(status));
status = pcap_set_timeout(pd, 5*60*1000);
if (status != 0)
error("%s: pcap_set_timeout failed: %s",
device, pcap_statustostr(status));
status = pcap_activate(pd);
if (status < 0) {
/*
* pcap_activate() failed.
*/
error("%s: %s\n(%s)", device,
pcap_statustostr(status), pcap_geterr(pd));
} else if (status > 0) {
/*
* pcap_activate() succeeded, but it's warning us
* of a problem it had.
*/
warning("%s: %s\n(%s)", device,
pcap_statustostr(status), pcap_geterr(pd));
}
if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
localnet = 0;
netmask = 0;
warning("%s", ebuf);
}
cmdbuf = copy_argv(&argv[optind]);
if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
error("%s", pcap_geterr(pd));
if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd));
#ifdef _WIN32
capture_thread = CreateThread(NULL, 0, capture_thread_func, device,
0, NULL);
if (capture_thread == NULL)
error("Can't create capture thread: %s",
win32_strerror(GetLastError()));
#else
status = pthread_create(&capture_thread, NULL, capture_thread_func,
device);
if (status != 0)
error("Can't create capture thread: %s", strerror(status));
#endif
sleep_secs(60);
printf("Doing pcap_breakloop()\n");
pcap_breakloop(pd);
if (do_wakeup) {
/*
* Force a wakeup in the capture thread.
*
* On some platforms, with some devices,, pcap_breakloop()
* can't do that itself. On Windows, poke the device's
* event handle; on UN*X, send a SIGUSR1 to the thread.
*/
#ifdef _WIN32
printf("Setting event\n");
if (!SetEvent(pcap_getevent(pd)))
error("Can't set event for pcap_t: %s",
win32_strerror(GetLastError()));
#else
printf("Sending SIGUSR1\n");
status = pthread_kill(capture_thread, SIGUSR1);
if (status != 0)
warning("Can't interrupt capture thread: %s",
strerror(status));
#endif
}
/*
* Now wait for the capture thread to terminate.
*/
#ifdef _WIN32
if (WaitForSingleObject(capture_thread, INFINITE) == WAIT_FAILED)
error("Wait for thread termination failed: %s",
win32_strerror(GetLastError()));
CloseHandle(capture_thread);
#else
status = pthread_join(capture_thread, &retval);
if (status != 0)
error("Wait for thread termination failed: %s",
strerror(status));
#endif