X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/ee29ee496cf7b09447df631c31d95ac3ea4538b0..8d3c2ed39e1b365da42c3aa5d2c5d6a6a5796bac:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index e91c8f4c..06d3d9b9 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -74,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 @@ -92,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 @@ -132,12 +145,13 @@ 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" #include "print.h" +#include "fptype.h" + #ifndef PATH_MAX #define PATH_MAX 1024 #endif @@ -152,7 +166,9 @@ The Regents of the University of California. All rights reserved.\n"; #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 @@ -178,6 +194,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 */ @@ -186,19 +203,24 @@ 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 lflag; /* line-buffered output */ 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) */ +static int timeout = 1000; /* default timeout = 1000 ms = 1 s */ #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE static int immediate_mode; #endif +static int count_mode; static int infodelay; static int infoprint; @@ -218,7 +240,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); @@ -259,6 +283,9 @@ 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 @@ -477,8 +504,50 @@ 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); @@ -574,6 +643,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 ]" @@ -615,6 +688,10 @@ 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 +#define OPTION_FP_TYPE 135 +#define OPTION_COUNT 136 static const struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) @@ -634,6 +711,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' }, @@ -656,6 +735,8 @@ static const struct option longopts[] = { { "debug-filter-parser", no_argument, NULL, 'Y' }, #endif { "relinquish-privileges", required_argument, NULL, 'Z' }, + { "count", no_argument, NULL, OPTION_COUNT }, + { "fp-type", no_argument, NULL, OPTION_FP_TYPE }, { "number", no_argument, NULL, '#' }, { "print", no_argument, NULL, OPTION_PRINT }, { "version", no_argument, NULL, OPTION_VERSION }, @@ -663,7 +744,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 @@ -674,12 +755,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 @@ -687,50 +762,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(S_ERR_HOST_PROGRAM); - } + 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(S_ERR_HOST_PROGRAM); - } + 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(S_ERR_HOST_PROGRAM); - } 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(S_ERR_HOST_PROGRAM); - } + } 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) @@ -790,7 +853,7 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) if (cnt == 0 && max_chars == 0) strncpy(buffer, filename, PATH_MAX + 1); else - if (nd_snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) + if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) /* Report an error if the filename is too large */ error("too many output files or filename is too long (> %d)", PATH_MAX); free(filename); @@ -800,13 +863,15 @@ static char * get_next_file(FILE *VFile, char *ptr) { char *ret; + size_t len; ret = fgets(ptr, PATH_MAX, VFile); if (!ret) return NULL; - if (ptr[strlen(ptr) - 1] == '\n') - ptr[strlen(ptr) - 1] = '\0'; + len = strlen (ptr); + if (len > 0 && ptr[len - 1] == '\n') + ptr[len - 1] = '\0'; return ret; } @@ -876,7 +941,7 @@ tstamp_precision_to_string(int precision) * necessary to make the standard I/O library work with an fdopen()ed * FILE * from that descriptor. * - * A long time ago, in a galaxy far far away, AT&T decided that, instead + * A long time ago in a galaxy far, far away, AT&T decided that, instead * of providing separate APIs for getting and setting the FD_ flags on a * descriptor, getting and setting the O_ flags on a descriptor, and * locking files, they'd throw them all into a kitchen-sink fcntl() call @@ -947,7 +1012,7 @@ static char * copy_argv(char **argv) { char **p; - u_int len = 0; + size_t len = 0; char *buf; char *src, *dst; @@ -987,7 +1052,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; @@ -1006,7 +1072,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 */ @@ -1074,7 +1140,11 @@ parse_interface_number(const char *device) } static char * -find_interface_by_number(const char *url, 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; @@ -1114,6 +1184,9 @@ find_interface_by_number(const char *url, long devnum) */ 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); @@ -1139,9 +1212,10 @@ find_interface_by_number(const char *url, 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 * @@ -1157,13 +1231,14 @@ 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'; pc = pcap_open(device, ndo->ndo_snaplen, - pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, + pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, timeout, NULL, ebuf); if (pc == NULL) { /* @@ -1205,9 +1280,9 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) 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 @@ -1215,8 +1290,7 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) 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 /* @@ -1246,7 +1320,7 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) error("%s: Can't set monitor mode: %s", device, pcap_statustostr(status)); } - status = pcap_set_timeout(pc, 1000); + status = pcap_set_timeout(pc, timeout); if (status != 0) error("%s: pcap_set_timeout failed: %s", device, pcap_statustostr(status)); @@ -1261,7 +1335,11 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) 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); @@ -1276,10 +1354,8 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) /* * Return an error for our caller to handle. */ - nd_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)", + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)", device, pcap_statustostr(status), cp); - pcap_close(pc); - return (NULL); } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0') error("%s: %s\n(%s)", device, pcap_statustostr(status), cp); @@ -1290,7 +1366,7 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) char sysctl[32]; size_t s = sizeof(parent); - nd_snprintf(sysctl, sizeof(sysctl), + snprintf(sysctl, sizeof(sysctl), "net.wlan.%d.%%parent", atoi(device + 4)); sysctlbyname(sysctl, parent, &s, NULL, 0); strlcpy(newdev, device, sizeof(newdev)); @@ -1310,6 +1386,8 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) else error("%s: %s", device, pcap_statustostr(status)); + pcap_close(pc); + return (NULL); } else if (status > 0) { /* * pcap_activate() succeeded, but it's warning us @@ -1341,8 +1419,8 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) * specified, default to 256KB. */ if (ndo->ndo_snaplen == 0) - ndo->ndo_snaplen = 262144; - pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, 1000, ebuf); + ndo->ndo_snaplen = MAXIMUM_SNAPLEN; + pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, timeout, ebuf); if (pc == NULL) { /* * If this failed with "No such device", that means @@ -1366,7 +1444,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; @@ -1380,8 +1457,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 @@ -1598,6 +1677,7 @@ main(int argc, char **argv) setvbuf(stdout, NULL, _IOLBF, 0); #endif #endif /* _WIN32 */ + lflag = 1; break; case 'K': @@ -1662,10 +1742,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': @@ -1711,6 +1792,12 @@ main(int argc, char **argv) ndo->ndo_packettype = PT_LMP; else if (ascii_strcasecmp(optarg, "resp") == 0) ndo->ndo_packettype = PT_RESP; + else if (ascii_strcasecmp(optarg, "ptp") == 0) + ndo->ndo_packettype = PT_PTP; + else if (ascii_strcasecmp(optarg, "someip") == 0) + ndo->ndo_packettype = PT_SOMEIP; + else if (ascii_strcasecmp(optarg, "domain") == 0) + ndo->ndo_packettype = PT_DOMAIN; else error("unknown packet type `%s'", optarg); break; @@ -1805,6 +1892,31 @@ 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 + + case OPTION_FP_TYPE: + /* + * Print out the type of floating-point arithmetic + * we're doing; it's probably IEEE, unless somebody + * tries to run this on a VAX, but the precision + * may differ (e.g., it might be 32-bit, 64-bit, + * or 80-bit). + */ + float_type_check(0x4e93312d); + return 0; + + case OPTION_COUNT: + count_mode = 1; + break; + default: print_usage(); exit_tcpdump(S_ERR_HOST_PROGRAM); @@ -1820,17 +1932,22 @@ main(int argc, char **argv) show_remote_devices_and_exit(); #endif +#if defined(DLT_LINUX_SLL2) && defined(HAVE_PCAP_SET_DATALINK) +/* Set default linktype DLT_LINUX_SLL2 when capturing on the "any" device */ + if (device != NULL && + strncmp (device, "any", strlen("any")) == 0 + && yflag_dlt == -1) + yflag_dlt = DLT_LINUX_SLL2; +#endif + 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 */ @@ -1844,19 +1961,18 @@ main(int argc, char **argv) if (VFileName != NULL && RFileName != NULL) error("-V and -r are mutually exclusive."); -#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE /* - * If we're printing dissected packets to the standard output - * and the standard output is a terminal, use immediate mode, - * as the user's probably expecting to see packets pop up - * immediately. + * If we're printing dissected packets to the standard output, + * and either the standard output is a terminal or we're doing + * "line" buffering, set the capture timeout to .1 second rather + * than 1 second, as the user's probably expecting to see packets + * pop up immediately shortly after they arrive. * - * XXX - set the timeout to a lower value, instead? If so, - * what value would be appropriate? + * XXX - would there be some value appropriate for all cases, + * based on, say, the buffer size and packet input rate? */ - if ((WFileName == NULL || print) && isatty(1)) - immediate_mode = 1; -#endif + if ((WFileName == NULL || print) && (isatty(1) || lflag)) + timeout = 100; #ifdef WITH_CHROOT /* if run as root, prepare for chrooting */ @@ -1932,15 +2048,41 @@ 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 if (dflag && !device) { + int dump_dlt = DLT_EN10MB; + /* + * We're dumping the compiled code without an explicit + * device specification. (If a device is specified, we + * definitely want to open it to use the DLT of that device.) + * Either default to DLT_EN10MB with a warning, or use + * the user-specified value if supplied. + */ + /* + * If no snapshot length was specified, or a length of 0 was + * specified, default to 256KB. + */ + if (ndo->ndo_snaplen == 0) + ndo->ndo_snaplen = MAXIMUM_SNAPLEN; + /* + * If a DLT was specified with the -y flag, use that instead. + */ + if (yflag_dlt != -1) + dump_dlt = yflag_dlt; + else + fprintf(stderr, "Warning: assuming Ethernet\n"); + pd = pcap_open_dead(dump_dlt, ndo->ndo_snaplen); } else { /* * We're doing a live capture. @@ -2046,7 +2188,8 @@ main(int argc, char **argv) } #endif (void)fprintf(stderr, "%s: data link type %s\n", - program_name, yflag_dlt_name); + program_name, + pcap_datalink_val_to_name(yflag_dlt)); (void)fflush(stderr); } i = pcap_snapshot(pd); @@ -2088,7 +2231,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); @@ -2216,7 +2359,7 @@ DIAG_ON_CLANG(assign-enum) 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 @@ -2327,20 +2470,20 @@ DIAG_ON_CLANG(assign-enum) */ if (!ndo->ndo_vflag && !WFileName) { (void)fprintf(stderr, - "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", + "%s: verbose output suppressed, use -v[v]... for full protocol decode\n", program_name); } else (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); } @@ -2456,20 +2599,24 @@ 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)); } } } while (ret != NULL); + if (count_mode && RFileName != NULL) + fprintf(stderr, "%u packet%s\n", packets_captured, + PLURAL_SUFFIX(packets_captured)); + free(cmdbuf); pcap_freecode(&fcode); exit_tcpdump(status == -1 ? 1 : 0); @@ -2902,7 +3049,8 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) ++infodelay; - pretty_print_packet((netdissect_options *)user, h, sp, packets_captured); + if (!count_mode) + pretty_print_packet((netdissect_options *)user, h, sp, packets_captured); --infodelay; if (infoprint) @@ -2984,15 +3132,14 @@ print_version(void) smi_version_string = nd_smi_version_string(); if (smi_version_string != NULL) (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string); -#ifdef HAVE_DNET_HTOA - (void)fprintf(stderr, "libdnet unknown version\n"); -#endif #if defined(__SANITIZE_ADDRESS__) (void)fprintf (stderr, "Compiled with AddressSanitizer/GCC.\n"); #elif defined(__has_feature) # if __has_feature(address_sanitizer) - (void)fprintf (stderr, "Compiled with AddressSanitizer/CLang.\n"); + (void)fprintf (stderr, "Compiled with AddressSanitizer/Clang.\n"); +# elif __has_feature(memory_sanitizer) + (void)fprintf (stderr, "Compiled with MemorySanitizer/Clang.\n"); # endif #endif /* __SANITIZE_ADDRESS__ or __has_feature */ } @@ -3003,7 +3150,7 @@ print_usage(void) { print_version(); (void)fprintf(stderr, -"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ]\n", program_name); +"Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name); (void)fprintf(stderr, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); (void)fprintf(stderr, @@ -3011,15 +3158,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"); }