X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/fb2479d733dbe8a991d11909b319341f7db62ab1..c2d6a5db5b15f08b9e858e3fcf1e6847aaebe26b:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 86c4c150..b0779a7c 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -25,12 +25,6 @@ * Seth Webster */ -#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 - /* * tcpdump - dump traffic on a network * @@ -57,6 +51,16 @@ The Regents of the University of California. All rights reserved.\n"; #include "netdissect-stdinc.h" +/* + * This must appear after including netdissect-stdinc.h, so that _U_ is + * defined. + */ +#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 + #include #ifdef HAVE_FCNTL_H @@ -70,14 +74,14 @@ The Regents of the University of California. All rights reserved.\n"; #ifdef HAVE_GETOPT_LONG #include #else -#include "getopt_long.h" +#include "missing/getopt_long.h" #endif /* Capsicum-specific code requires macros from , which will fail * to compile if has already been included; including the headers * in the opposite order works fine. */ #ifdef HAVE_CAPSICUM -#include +#include #include #include #include @@ -88,6 +92,19 @@ The Regents of the University of California. All rights reserved.\n"; #endif /* HAVE_CASPER */ #endif /* HAVE_CAPSICUM */ #ifdef HAVE_PCAP_OPEN +/* + * We found pcap_open() in the capture library, so we'll be using + * the remote capture APIs; define PCAP_REMOTE before we include pcap.h, + * so we get those APIs declared, and the types and #defines that they + * use defined. + * + * WinPcap's headers require that PCAP_REMOTE be defined in order to get + * remote-capture APIs declared and types and #defines that they use + * defined. + * + * (Versions of libpcap with those APIs, and thus Npcap, which is based on + * those versions of libpcap, don't require it.) + */ #define HAVE_REMOTE #endif #include @@ -128,7 +145,6 @@ The Regents of the University of California. All rights reserved.\n"; #include "interface.h" #include "addrtoname.h" #include "machdep.h" -#include "gmt2local.h" #include "pcap-missing.h" #include "ascii_strcasecmp.h" @@ -138,13 +154,19 @@ The Regents of the University of California. All rights reserved.\n"; #define PATH_MAX 1024 #endif -#ifdef SIGINFO +#if defined(SIGINFO) #define SIGNAL_REQ_INFO SIGINFO -#elif SIGUSR1 +#elif defined(SIGUSR1) #define SIGNAL_REQ_INFO SIGUSR1 #endif +#if defined(HAVE_PCAP_DUMP_FLUSH) && defined(SIGUSR2) +#define SIGNAL_FLUSH_PCAP SIGUSR2 +#endif + +#if defined(HAVE_PCAP_CREATE) || defined(_WIN32) static int Bflag; /* buffer size */ +#endif #ifdef HAVE_PCAP_DUMP_FTELL64 static int64_t Cflag; /* rotate dump files after this many bytes */ #else @@ -170,6 +192,7 @@ static char *remote_interfaces_source; /* list available devices from this sourc * dflag but, instead, *if* built with optimizer debugging code, * *export* a routine to set that flag. */ +extern int dflag; int dflag; /* print filter code */ static int Gflag; /* rotate dump files after this many seconds */ static int Gflag_count; /* number of files created with Gflag rotation */ @@ -178,17 +201,21 @@ static int Lflag; /* list available data link types and exit */ static int Iflag; /* rfmon (monitor) mode */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE static int Jflag; /* list available time stamp types */ -#endif static int jflag = -1; /* packet time stamp source */ +#endif static int pflag; /* don't go promiscuous */ #ifdef HAVE_PCAP_SETDIRECTION static int Qflag = -1; /* restrict captured packet by send/receive direction */ #endif +#ifdef HAVE_PCAP_DUMP_FLUSH static int Uflag; /* "unbuffered" output of dump files */ +#endif static int Wflag; /* recycle output files after this number of files */ static int WflagChars; static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE static int immediate_mode; +#endif static int infodelay; static int infoprint; @@ -208,7 +235,9 @@ static void cleanup(int); static void child_cleanup(int); static void print_version(void); static void print_usage(void); +#ifdef HAVE_PCAP_SET_TSTAMP_TYPE static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device); +#endif static NORETURN void show_dlts_and_exit(pcap_t *, const char *device); #ifdef HAVE_PCAP_FINDALLDEVS static NORETURN void show_devices_and_exit(void); @@ -223,7 +252,11 @@ static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void droproot(const char *, const char *); #ifdef SIGNAL_REQ_INFO -void requestinfo(int); +static void requestinfo(int); +#endif + +#ifdef SIGNAL_FLUSH_PCAP +static void flushpcap(int); #endif #ifdef _WIN32 @@ -245,11 +278,15 @@ static const struct tok status_flags[] = { { PCAP_IF_RUNNING, "Running" }, #endif { PCAP_IF_LOOPBACK, "Loopback" }, +#ifdef PCAP_IF_WIRELESS + { PCAP_IF_WIRELESS, "Wireless" }, +#endif { 0, NULL } }; #endif static pcap_t *pd; +static pcap_dumper_t *pdd = NULL; static int supports_monitor_mode; @@ -261,7 +298,7 @@ struct dump_info { char *WFileName; char *CurrentFileName; pcap_t *pd; - pcap_dumper_t *p; + pcap_dumper_t *pdd; netdissect_options *ndo; #ifdef HAVE_CAPSICUM int dirfd; @@ -334,7 +371,7 @@ error(const char *fmt, ...) if (fmt[-1] != '\n') (void)fputc('\n', stderr); } - exit_tcpdump(1); + exit_tcpdump(S_ERR_HOST_PROGRAM); /* NOTREACHED */ } @@ -378,7 +415,7 @@ show_tstamp_types_and_exit(pcap_t *pc, const char *device) if (n_tstamp_types == 0) { fprintf(stderr, "Time stamp type cannot be set for %s\n", device); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); } fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", device); @@ -392,7 +429,7 @@ show_tstamp_types_and_exit(pcap_t *pc, const char *device) } } pcap_free_tstamp_types(tstamp_types); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); } #endif @@ -445,7 +482,7 @@ show_dlts_and_exit(pcap_t *pc, const char *device) #ifdef HAVE_PCAP_FREE_DATALINKS pcap_free_datalinks(dlts); #endif - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); } #ifdef HAVE_PCAP_FINDALLDEVS @@ -462,12 +499,54 @@ show_devices_and_exit(void) printf("%d.%s", i+1, dev->name); if (dev->description != NULL) printf(" (%s)", dev->description); - if (dev->flags != 0) - printf(" [%s]", bittok2str(status_flags, "none", dev->flags)); + if (dev->flags != 0) { + printf(" ["); + printf("%s", bittok2str(status_flags, "none", dev->flags)); +#ifdef PCAP_IF_WIRELESS + if (dev->flags & PCAP_IF_WIRELESS) { + switch (dev->flags & PCAP_IF_CONNECTION_STATUS) { + + case PCAP_IF_CONNECTION_STATUS_UNKNOWN: + printf(", Association status unknown"); + break; + + case PCAP_IF_CONNECTION_STATUS_CONNECTED: + printf(", Associated"); + break; + + case PCAP_IF_CONNECTION_STATUS_DISCONNECTED: + printf(", Not associated"); + break; + + case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: + break; + } + } else { + switch (dev->flags & PCAP_IF_CONNECTION_STATUS) { + + case PCAP_IF_CONNECTION_STATUS_UNKNOWN: + printf(", Connection status unknown"); + break; + + case PCAP_IF_CONNECTION_STATUS_CONNECTED: + printf(", Connected"); + break; + + case PCAP_IF_CONNECTION_STATUS_DISCONNECTED: + printf(", Disconnected"); + break; + + case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE: + break; + } + } +#endif + printf("]"); + } printf("\n"); } pcap_freealldevs(devlist); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); } #endif /* HAVE_PCAP_FINDALLDEVS */ @@ -491,7 +570,7 @@ show_remote_devices_and_exit(void) printf("\n"); } pcap_freealldevs(devlist); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); } #endif /* HAVE_PCAP_FINDALLDEVS */ @@ -559,6 +638,10 @@ show_remote_devices_and_exit(void) #define J_FLAG #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ +#ifdef USE_LIBSMI +#define m_FLAG_USAGE "[ -m module ] ..." +#endif + #ifdef HAVE_PCAP_SETDIRECTION #define Q_FLAG "Q:" #define Q_FLAG_USAGE " [ -Q in|out|inout ]" @@ -600,6 +683,8 @@ show_remote_devices_and_exit(void) #define OPTION_IMMEDIATE_MODE 130 #define OPTION_PRINT 131 #define OPTION_LIST_REMOTE_INTERFACES 132 +#define OPTION_TSTAMP_MICRO 133 +#define OPTION_TSTAMP_NANO 134 static const struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) @@ -619,6 +704,8 @@ static const struct option longopts[] = { { "list-time-stamp-types", no_argument, NULL, 'J' }, #endif #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + { "micro", no_argument, NULL, OPTION_TSTAMP_MICRO}, + { "nano", no_argument, NULL, OPTION_TSTAMP_NANO}, { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, #endif { "dont-verify-checksums", no_argument, NULL, 'K' }, @@ -648,7 +735,7 @@ static const struct option longopts[] = { }; #ifdef HAVE_PCAP_FINDALLDEVS_EX -#define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]" +#define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]" #else #define LIST_REMOTE_INTERFACES_USAGE #endif @@ -659,12 +746,6 @@ static const struct option longopts[] = { #define IMMEDIATE_MODE_USAGE "" #endif -#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION -#define TIME_STAMP_PRECISION_USAGE " [ --time-stamp-precision precision ]" -#else -#define TIME_STAMP_PRECISION_USAGE -#endif - #ifndef _WIN32 /* Drop root privileges and chroot if necessary */ static void @@ -672,50 +753,38 @@ droproot(const char *username, const char *chroot_dir) { struct passwd *pw = NULL; - if (chroot_dir && !username) { - fprintf(stderr, "%s: Chroot without dropping root is insecure\n", - program_name); - exit_tcpdump(1); - } + if (chroot_dir && !username) + error("Chroot without dropping root is insecure"); pw = getpwnam(username); if (pw) { if (chroot_dir) { - if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { - fprintf(stderr, "%s: Couldn't chroot/chdir to '%.64s': %s\n", - program_name, chroot_dir, pcap_strerror(errno)); - exit_tcpdump(1); - } + if (chroot(chroot_dir) != 0 || chdir ("/") != 0) + error("Couldn't chroot/chdir to '%.64s': %s", + chroot_dir, pcap_strerror(errno)); } #ifdef HAVE_LIBCAP_NG { int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); - if (ret < 0) { - fprintf(stderr, "error : ret %d\n", ret); - } else { + if (ret < 0) + error("capng_change_id(): return %d\n", ret); + else fprintf(stderr, "dropped privs to %s\n", username); - } } #else if (initgroups(pw->pw_name, pw->pw_gid) != 0 || - setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { - fprintf(stderr, "%s: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", - program_name, username, + setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) + error("Couldn't change to '%.32s' uid=%lu gid=%lu: %s", + username, (unsigned long)pw->pw_uid, (unsigned long)pw->pw_gid, pcap_strerror(errno)); - exit_tcpdump(1); - } else { fprintf(stderr, "dropped privs to %s\n", username); } #endif /* HAVE_LIBCAP_NG */ - } - else { - fprintf(stderr, "%s: Couldn't find user '%.32s'\n", - program_name, username); - exit_tcpdump(1); - } + } else + error("Couldn't find user '%.32s'", username); #ifdef HAVE_LIBCAP_NG /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */ DIAG_OFF_CLANG(assign-enum) @@ -932,7 +1001,7 @@ static char * copy_argv(char **argv) { char **p; - u_int len = 0; + size_t len = 0; char *buf; char *src, *dst; @@ -972,7 +1041,8 @@ copy_argv(char **argv) static char * read_infile(char *fname) { - int i, fd, cc; + int i, fd; + ssize_t cc; char *cp; struct stat buf; @@ -991,7 +1061,7 @@ read_infile(char *fname) if (cc < 0) error("read %s: %s", fname, pcap_strerror(errno)); if (cc != buf.st_size) - error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); + error("short read %s (%zd != %d)", fname, cc, (int)buf.st_size); close(fd); /* replace "# comment" with spaces */ @@ -1008,9 +1078,35 @@ read_infile(char *fname) static long parse_interface_number(const char *device) { + const char *p; long devnum; char *end; + /* + * Search for a colon, terminating any scheme at the beginning + * of the device. + */ + p = strchr(device, ':'); + if (p != NULL) { + /* + * We found it. Is it followed by "//"? + */ + p++; /* skip the : */ + if (strncmp(p, "//", 2) == 0) { + /* + * Yes. Search for the next /, at the end of the + * authority part of the URL. + */ + p += 2; /* skip the // */ + p = strchr(p, '/'); + if (p != NULL) { + /* + * OK, past the / is the path. + */ + device = p + 1; + } + } + } devnum = strtol(device, &end, 10); if (device != end && *end == '\0') { /* @@ -1033,14 +1129,61 @@ parse_interface_number(const char *device) } static char * -find_interface_by_number(long devnum) +find_interface_by_number(const char *url +#ifndef HAVE_PCAP_FINDALLDEVS_EX +_U_ +#endif +, long devnum) { pcap_if_t *dev, *devlist; long i; char ebuf[PCAP_ERRBUF_SIZE]; char *device; +#ifdef HAVE_PCAP_FINDALLDEVS_EX + const char *endp; + char *host_url; +#endif + int status; - if (pcap_findalldevs(&devlist, ebuf) < 0) +#ifdef HAVE_PCAP_FINDALLDEVS_EX + /* + * Search for a colon, terminating any scheme at the beginning + * of the URL. + */ + endp = strchr(url, ':'); + if (endp != NULL) { + /* + * We found it. Is it followed by "//"? + */ + endp++; /* skip the : */ + if (strncmp(endp, "//", 2) == 0) { + /* + * Yes. Search for the next /, at the end of the + * authority part of the URL. + */ + endp += 2; /* skip the // */ + endp = strchr(endp, '/'); + } else + endp = NULL; + } + if (endp != NULL) { + /* + * OK, everything from device to endp is a URL to hand + * to pcap_findalldevs_ex(). + */ + endp++; /* Include the trailing / in the URL; pcap_findalldevs_ex() requires it */ + host_url = malloc(endp - url + 1); + if (host_url == NULL && (endp - url + 1) > 0) + error("Invalid allocation for host"); + + memcpy(host_url, url, endp - url); + host_url[endp - url] = '\0'; + status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf); + free(host_url); + } else +#endif + status = pcap_findalldevs(&devlist, ebuf); + if (status < 0) error("%s", ebuf); /* * Look for the devnum-th entry in the list of devices (1-based). @@ -1058,9 +1201,10 @@ find_interface_by_number(long devnum) #ifdef HAVE_PCAP_OPEN /* - * Prefix for rpcap URLs. + * Prefixes for rpcap URLs. */ static char rpcap_prefix[] = "rpcap://"; +static char rpcap_ssl_prefix[] = "rpcaps://"; #endif static pcap_t * @@ -1076,23 +1220,25 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) /* * Is this an rpcap URL? */ - if (strncmp(device, rpcap_prefix, sizeof(rpcap_prefix) - 1) == 0) { + if (strncmp(device, rpcap_prefix, sizeof(rpcap_prefix) - 1) == 0 || + strncmp(device, rpcap_ssl_prefix, sizeof(rpcap_ssl_prefix) - 1) == 0) { /* * Yes. Open it with pcap_open(). */ *ebuf = '\0'; -fprintf(stderr, "Opening %s\n", device); pc = pcap_open(device, ndo->ndo_snaplen, pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, ebuf); if (pc == NULL) { /* - * If this failed with "No such device", that means + * If this failed with "No such device" or "The system + * cannot find the device specified", that means * the interface doesn't exist; return NULL, so that * the caller can see whether the device name is * actually an interface index. */ - if (strstr(ebuf, "No such device") != NULL) + if (strstr(ebuf, "No such device") != NULL || + strstr(ebuf, "The system cannot find the device specified") != NULL) return (NULL); error("%s", ebuf); } @@ -1123,9 +1269,9 @@ fprintf(stderr, "Opening %s\n", device); status = pcap_set_tstamp_precision(pc, ndo->ndo_tstamp_precision); if (status != 0) error("%s: Can't set %ssecond time stamp precision: %s", - device, - tstamp_precision_to_string(ndo->ndo_tstamp_precision), - pcap_statustostr(status)); + device, + tstamp_precision_to_string(ndo->ndo_tstamp_precision), + pcap_statustostr(status)); #endif #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE @@ -1133,8 +1279,7 @@ fprintf(stderr, "Opening %s\n", device); status = pcap_set_immediate_mode(pc, 1); if (status != 0) error("%s: Can't set immediate mode: %s", - device, - pcap_statustostr(status)); + device, pcap_statustostr(status)); } #endif /* @@ -1179,7 +1324,11 @@ fprintf(stderr, "Opening %s\n", device); status = pcap_set_tstamp_type(pc, jflag); if (status < 0) error("%s: Can't set time stamp type: %s", - device, pcap_statustostr(status)); + device, pcap_statustostr(status)); + else if (status > 0) + warning("When trying to set timestamp type '%s' on %s: %s", + pcap_tstamp_type_val_to_name(jflag), device, + pcap_statustostr(status)); } #endif status = pcap_activate(pc); @@ -1284,7 +1433,6 @@ main(int argc, char **argv) { int cnt, op, i; bpf_u_int32 localnet = 0, netmask = 0; - int timezone_offset = 0; char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; char *endp; pcap_handler callback; @@ -1298,8 +1446,10 @@ main(int argc, char **argv) u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; char VFileLine[PATH_MAX + 1]; - char *username = NULL; - char *chroot_dir = NULL; + const char *username = NULL; +#ifndef _WIN32 + const char *chroot_dir = NULL; +#endif char *ret = NULL; char *end; #ifdef HAVE_PCAP_FINDALLDEVS @@ -1323,7 +1473,7 @@ main(int argc, char **argv) /* * Initialize the netdissect code. */ - if (nd_init(ebuf, sizeof ebuf) == -1) + if (nd_init(ebuf, sizeof(ebuf)) == -1) error("%s", ebuf); memset(ndo, 0, sizeof(*ndo)); @@ -1342,10 +1492,13 @@ main(int argc, char **argv) else ndo->program_name = program_name = argv[0]; -#ifdef _WIN32 +#if defined(HAVE_PCAP_WSOCKINIT) if (pcap_wsockinit() != 0) error("Attempting to initialize Winsock failed"); -#endif /* _WIN32 */ +#elif defined(HAVE_WSOCKINIT) + if (wsockinit() != 0) + error("Attempting to initialize Winsock failed"); +#endif /* * On platforms where the CPU doesn't support unaligned loads, @@ -1465,7 +1618,7 @@ main(int argc, char **argv) case 'h': print_usage(); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); break; case 'H': @@ -1521,7 +1674,7 @@ main(int argc, char **argv) case 'm': if (nd_have_smi_support()) { - if (nd_load_smi_module(optarg, ebuf, sizeof ebuf) == -1) + if (nd_load_smi_module(optarg, ebuf, sizeof(ebuf)) == -1) error("%s", ebuf); } else { (void)fprintf(stderr, "%s: ignoring option `-m %s' ", @@ -1577,10 +1730,11 @@ main(int argc, char **argv) break; case 's': - ndo->ndo_snaplen = strtol(optarg, &end, 0); + ndo->ndo_snaplen = (int)strtol(optarg, &end, 0); if (optarg == end || *end != '\0' || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN) - error("invalid snaplen %s", optarg); + error("invalid snaplen %s (must be >= 0 and <= %d)", + optarg, MAXIMUM_SNAPLEN); break; case 'S': @@ -1699,7 +1853,7 @@ main(int argc, char **argv) case OPTION_VERSION: print_version(); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); break; #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION @@ -1720,9 +1874,19 @@ main(int argc, char **argv) print = 1; break; +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION + case OPTION_TSTAMP_MICRO: + ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO; + break; + + case OPTION_TSTAMP_NANO: + ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_NANO; + break; +#endif + default: print_usage(); - exit_tcpdump(1); + exit_tcpdump(S_ERR_HOST_PROGRAM); /* NOTREACHED */ } @@ -1738,14 +1902,11 @@ main(int argc, char **argv) switch (ndo->ndo_tflag) { case 0: /* Default */ - case 4: /* Default + Date*/ - timezone_offset = gmt2local(0); - break; - case 1: /* No time stamp */ case 2: /* Unix timeval style */ - case 3: /* Microseconds since previous packet */ - case 5: /* Microseconds since first packet */ + case 3: /* Microseconds/nanoseconds since previous packet */ + case 4: /* Date + Default */ + case 5: /* Microseconds/nanoseconds since first packet */ break; default: /* Not supported */ @@ -1847,15 +2008,18 @@ main(int argc, char **argv) #endif dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); + fprintf(stderr, "reading from file %s", RFileName); if (dlt_name == NULL) { - fprintf(stderr, "reading from file %s, link-type %u\n", - RFileName, dlt); + fprintf(stderr, ", link-type %u", dlt); } else { - fprintf(stderr, - "reading from file %s, link-type %s (%s)\n", - RFileName, dlt_name, - pcap_datalink_val_to_description(dlt)); + fprintf(stderr, ", link-type %s (%s)", dlt_name, + pcap_datalink_val_to_description(dlt)); } + fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd)); +#ifdef DLT_LINUX_SLL2 + if (dlt == DLT_LINUX_SLL2) + fprintf(stderr, "Warning: interface names might be incorrect\n"); +#endif } else { /* * We're doing a live capture. @@ -1916,7 +2080,7 @@ main(int argc, char **argv) * find_interface_by_number() exits if it * couldn't be found. */ - device = find_interface_by_number(devnum); + device = find_interface_by_number(device, devnum); pd = open_interface(device, ndo, ebuf); if (pd == NULL) error("%s", ebuf); @@ -1995,7 +2159,7 @@ main(int argc, char **argv) pcap_close(pd); free(cmdbuf); pcap_freecode(&fcode); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); } #ifdef HAVE_CASPER @@ -2003,7 +2167,7 @@ main(int argc, char **argv) capdns = capdns_setup(); #endif /* HAVE_CASPER */ - init_print(ndo, localnet, netmask, timezone_offset); + init_print(ndo, localnet, netmask); #ifndef _WIN32 (void)setsignal(SIGPIPE, cleanup); @@ -2082,7 +2246,7 @@ DIAG_ON_CLANG(assign-enum) if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM - if (RFileName == NULL && VFileName == NULL) { + if (RFileName == NULL && VFileName == NULL && pcap_fileno(pd) != -1) { static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF }; /* @@ -2102,7 +2266,6 @@ DIAG_ON_CLANG(assign-enum) } #endif if (WFileName) { - pcap_dumper_t *p; /* Do not exceed the default PATH_MAX for files. */ dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1); @@ -2115,7 +2278,7 @@ DIAG_ON_CLANG(assign-enum) else MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); - p = pcap_dump_open(pd, dumpinfo.CurrentFileName); + pdd = pcap_dump_open(pd, dumpinfo.CurrentFileName); #ifdef HAVE_LIBCAP_NG /* Give up CAP_DAC_OVERRIDE capability. * Only allow it to be restored if the -C or -G flag have been @@ -2129,10 +2292,10 @@ DIAG_ON_CLANG(assign-enum) ); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ - if (p == NULL) + if (pdd == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM - set_dumper_capsicum_rights(p); + set_dumper_capsicum_rights(pdd); #endif if (Cflag != 0 || Gflag != 0) { #ifdef HAVE_CAPSICUM @@ -2162,13 +2325,13 @@ DIAG_ON_CLANG(assign-enum) #endif callback = dump_packet_and_trunc; dumpinfo.pd = pd; - dumpinfo.p = p; + dumpinfo.pdd = pdd; pcap_userdata = (u_char *)&dumpinfo; } else { callback = dump_packet; dumpinfo.WFileName = WFileName; dumpinfo.pd = pd; - dumpinfo.p = p; + dumpinfo.pdd = pdd; pcap_userdata = (u_char *)&dumpinfo; } if (print) { @@ -2180,7 +2343,7 @@ DIAG_ON_CLANG(assign-enum) #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) - pcap_dump_flush(p); + pcap_dump_flush(pdd); #endif } else { dlt = pcap_datalink(pd); @@ -2197,6 +2360,9 @@ DIAG_ON_CLANG(assign-enum) if (RFileName == NULL) (void)setsignal(SIGNAL_REQ_INFO, requestinfo); #endif +#ifdef SIGNAL_FLUSH_PCAP + (void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap); +#endif if (ndo->ndo_vflag > 0 && WFileName && !print) { /* @@ -2246,14 +2412,14 @@ DIAG_ON_CLANG(assign-enum) (void)fprintf(stderr, "%s: ", program_name); dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); + (void)fprintf(stderr, "listening on %s", device); if (dlt_name == NULL) { - (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", - device, dlt, ndo->ndo_snaplen); + (void)fprintf(stderr, ", link-type %u", dlt); } else { - (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", - device, dlt_name, - pcap_datalink_val_to_description(dlt), ndo->ndo_snaplen); + (void)fprintf(stderr, ", link-type %s (%s)", dlt_name, + pcap_datalink_val_to_description(dlt)); } + (void)fprintf(stderr, ", snapshot length %d bytes\n", ndo->ndo_snaplen); (void)fflush(stderr); } @@ -2369,15 +2535,15 @@ DIAG_ON_CLANG(assign-enum) * Report the new file. */ dlt_name = pcap_datalink_val_to_name(dlt); + fprintf(stderr, "reading from file %s", RFileName); if (dlt_name == NULL) { - fprintf(stderr, "reading from file %s, link-type %u\n", - RFileName, dlt); + fprintf(stderr, ", link-type %u", dlt); } else { - fprintf(stderr, - "reading from file %s, link-type %s (%s)\n", - RFileName, dlt_name, - pcap_datalink_val_to_description(dlt)); + fprintf(stderr, ", link-type %s (%s)", + dlt_name, + pcap_datalink_val_to_description(dlt)); } + fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd)); } } } @@ -2454,7 +2620,7 @@ cleanup(int signo _U_) (void)fflush(stdout); info(1); } - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); #endif } @@ -2554,9 +2720,9 @@ compress_savefile(const char *filename) filename, pcap_strerror(errno)); #ifdef HAVE_FORK - exit(1); + exit(S_ERR_HOST_PROGRAM); #else - _exit(1); + _exit(S_ERR_HOST_PROGRAM); #endif } #else /* HAVE_FORK && HAVE_VFORK */ @@ -2612,7 +2778,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s /* * Close the current file and open a new one. */ - pcap_dump_close(dump_info->p); + pcap_dump_close(dump_info->pdd); /* * Compress the file we just closed, if the user asked for it @@ -2628,7 +2794,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s (void)fprintf(stderr, "Maximum file limit reached: %d\n", Wflag); info(1); - exit_tcpdump(0); + exit_tcpdump(S_SUCCESS); /* NOTREACHED */ } if (dump_info->CurrentFileName != NULL) @@ -2672,18 +2838,18 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s error("unable to fdopen file %s", dump_info->CurrentFileName); } - dump_info->p = pcap_dump_fopen(dump_info->pd, fp); + dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp); #else /* !HAVE_CAPSICUM */ - dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); + dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif #ifdef HAVE_LIBCAP_NG capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ - if (dump_info->p == NULL) + if (dump_info->pdd == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM - set_dumper_capsicum_rights(dump_info->p); + set_dumper_capsicum_rights(dump_info->pdd); #endif } } @@ -2695,7 +2861,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s */ if (Cflag != 0) { #ifdef HAVE_PCAP_DUMP_FTELL64 - int64_t size = pcap_dump_ftell64(dump_info->p); + int64_t size = pcap_dump_ftell64(dump_info->pdd); #else /* * XXX - this only handles a Cflag value > 2^31-1 on @@ -2703,7 +2869,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s * Windows) or LLP64 (64-bit Windows) would require * a version of libpcap with pcap_dump_ftell64(). */ - long size = pcap_dump_ftell(dump_info->p); + long size = pcap_dump_ftell(dump_info->pdd); #endif if (size == -1) @@ -2717,7 +2883,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s /* * Close the current file and open a new one. */ - pcap_dump_close(dump_info->p); + pcap_dump_close(dump_info->pdd); /* * Compress the file we just closed, if the user @@ -2753,26 +2919,26 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s error("unable to fdopen file %s", dump_info->CurrentFileName); } - dump_info->p = pcap_dump_fopen(dump_info->pd, fp); + dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp); #else /* !HAVE_CAPSICUM */ - dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); + dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif #ifdef HAVE_LIBCAP_NG capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ - if (dump_info->p == NULL) + if (dump_info->pdd == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM - set_dumper_capsicum_rights(dump_info->p); + set_dumper_capsicum_rights(dump_info->pdd); #endif } } - pcap_dump((u_char *)dump_info->p, h, sp); + pcap_dump((u_char *)dump_info->pdd, h, sp); #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) - pcap_dump_flush(dump_info->p); + pcap_dump_flush(dump_info->pdd); #endif if (dump_info->ndo != NULL) @@ -2794,10 +2960,10 @@ dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) dump_info = (struct dump_info *)user; - pcap_dump((u_char *)dump_info->p, h, sp); + pcap_dump((u_char *)dump_info->pdd, h, sp); #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) - pcap_dump_flush(dump_info->p); + pcap_dump_flush(dump_info->pdd); #endif if (dump_info->ndo != NULL) @@ -2823,7 +2989,8 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) } #ifdef SIGNAL_REQ_INFO -void requestinfo(int signo _U_) +static void +requestinfo(int signo _U_) { if (infodelay) ++infoprint; @@ -2832,6 +2999,15 @@ void requestinfo(int signo _U_) } #endif +#ifdef SIGNAL_FLUSH_PCAP +static void +flushpcap(int signo _U_) +{ + if (pdd != NULL) + pcap_dump_flush(pdd); +} +#endif + static void print_packets_captured (void) { @@ -2914,21 +3090,21 @@ print_usage(void) #ifdef HAVE_PCAP_FINDALLDEVS_EX (void)fprintf(stderr, "\t\t" LIST_REMOTE_INTERFACES_USAGE "\n"); +#endif +#ifdef USE_LIBSMI + (void)fprintf(stderr, +"\t\t" m_FLAG_USAGE "\n"); #endif (void)fprintf(stderr, "\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n"); (void)fprintf(stderr, -"\t\t[ -r file ] [ -s snaplen ]" TIME_STAMP_PRECISION_USAGE "\n"); +"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n"); (void)fprintf(stderr, -"\t\t[ -T type ] [ --version ] [ -V file ] [ -w file ]\n"); +"\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n"); +#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION (void)fprintf(stderr, -"\t\t[ -W filecount ] [ -y datalinktype ]\n"); +"\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n"); +#endif (void)fprintf(stderr, "\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n"); } -/* - * Local Variables: - * c-style: whitesmith - * c-basic-offset: 8 - * End: - */