X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/4943adfb5f2768c06ce08bcf402ec6d9dd226b3c..66f29e001c608bf8ca3ed25f492fbd88e23e1b5e:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index ecd41fc2..84f30f2d 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -87,6 +87,9 @@ The Regents of the University of California. All rights reserved.\n"; #include #endif /* HAVE_CASPER */ #endif /* HAVE_CAPSICUM */ +#ifdef HAVE_PCAP_OPEN +#define HAVE_REMOTE +#endif #include #include #include @@ -94,7 +97,10 @@ The Regents of the University of California. All rights reserved.\n"; #include #include #include -#ifndef _WIN32 +#ifdef _WIN32 +#include +#else +#include #include #include #include @@ -139,13 +145,19 @@ The Regents of the University of California. All rights reserved.\n"; #endif static int Bflag; /* buffer size */ -#ifdef HAVE_PCAP_FTELL64 +#ifdef HAVE_PCAP_DUMP_FTELL64 static int64_t Cflag; /* rotate dump files after this many bytes */ #else static long Cflag; /* rotate dump files after this many bytes */ #endif static int Cflag_count; /* Keep track of which file number we're writing */ +#ifdef HAVE_PCAP_FINDALLDEVS static int Dflag; /* list available devices and exit */ +#endif +#ifdef HAVE_PCAP_FINDALLDEVS_EX +static char *remote_interfaces_source; /* list available devices from this source and exit */ +#endif + /* * This is exported because, in some versions of libpcap, if libpcap * is built with optimizer debugging code (which is *NOT* the default @@ -201,6 +213,9 @@ static NORETURN void show_dlts_and_exit(pcap_t *, const char *device); #ifdef HAVE_PCAP_FINDALLDEVS static NORETURN void show_devices_and_exit(void); #endif +#ifdef HAVE_PCAP_FINDALLDEVS_EX +static NORETURN void show_remote_devices_and_exit(void); +#endif static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); @@ -211,13 +226,12 @@ static void droproot(const char *, const char *); void requestinfo(int); #endif -#if defined(USE_WIN32_MM_TIMER) - #include - static UINT timer_id; - static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); -#elif defined(HAVE_ALARM) +#ifdef _WIN32 + static HANDLE timer_handle = INVALID_HANDLE_VALUE; + static void CALLBACK verbose_stats_dump(PVOID param, BOOLEAN timer_fired); +#else /* _WIN32 */ static void verbose_stats_dump(int sig); -#endif +#endif /* _WIN32 */ static void info(int); static u_int packets_captured; @@ -436,7 +450,7 @@ show_dlts_and_exit(pcap_t *pc, const char *device) #ifdef HAVE_PCAP_FINDALLDEVS static void -show_devices_and_exit (void) +show_devices_and_exit(void) { pcap_if_t *dev, *devlist; char ebuf[PCAP_ERRBUF_SIZE]; @@ -457,6 +471,30 @@ show_devices_and_exit (void) } #endif /* HAVE_PCAP_FINDALLDEVS */ +#ifdef HAVE_PCAP_FINDALLDEVS_EX +static void +show_remote_devices_and_exit(void) +{ + pcap_if_t *dev, *devlist; + char ebuf[PCAP_ERRBUF_SIZE]; + int i; + + if (pcap_findalldevs_ex(remote_interfaces_source, NULL, &devlist, + ebuf) < 0) + error("%s", ebuf); + for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) { + 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)); + printf("\n"); + } + pcap_freealldevs(devlist); + exit_tcpdump(0); +} +#endif /* HAVE_PCAP_FINDALLDEVS */ + /* * Short options. * @@ -499,6 +537,12 @@ show_devices_and_exit (void) #define B_FLAG_USAGE #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ +#ifdef HAVE_PCAP_FINDALLDEVS +#define D_FLAG "D" +#else +#define D_FLAG +#endif + #ifdef HAVE_PCAP_CREATE #define I_FLAG "I" #else /* HAVE_PCAP_CREATE */ @@ -515,10 +559,12 @@ show_devices_and_exit (void) #define J_FLAG #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ -#ifdef HAVE_PCAP_FINDALLDEVS -#define D_FLAG "D" +#ifdef HAVE_PCAP_SETDIRECTION +#define Q_FLAG "Q:" +#define Q_FLAG_USAGE " [ -Q in|out|inout ]" #else -#define D_FLAG +#define Q_FLAG +#define Q_FLAG_USAGE #endif #ifdef HAVE_PCAP_DUMP_FLUSH @@ -527,12 +573,6 @@ show_devices_and_exit (void) #define U_FLAG #endif -#ifdef HAVE_PCAP_SETDIRECTION -#define Q_FLAG "Q:" -#else -#define Q_FLAG -#endif - #define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#" /* @@ -555,16 +595,20 @@ show_devices_and_exit (void) * component of the entry for the long option, and have a case for that * option in the switch statement. */ -#define OPTION_VERSION 128 -#define OPTION_TSTAMP_PRECISION 129 -#define OPTION_IMMEDIATE_MODE 130 -#define OPTION_PRINT 131 +#define OPTION_VERSION 128 +#define OPTION_TSTAMP_PRECISION 129 +#define OPTION_IMMEDIATE_MODE 130 +#define OPTION_PRINT 131 +#define OPTION_LIST_REMOTE_INTERFACES 132 static const struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) { "buffer-size", required_argument, NULL, 'B' }, #endif { "list-interfaces", no_argument, NULL, 'D' }, +#ifdef HAVE_PCAP_FINDALLDEVS_EX + { "list-remote-interfaces", required_argument, NULL, OPTION_LIST_REMOTE_INTERFACES }, +#endif { "help", no_argument, NULL, 'h' }, { "interface", required_argument, NULL, 'i' }, #ifdef HAVE_PCAP_CREATE @@ -603,6 +647,24 @@ static const struct option longopts[] = { { NULL, 0, NULL, 0 } }; +#ifdef HAVE_PCAP_FINDALLDEVS_EX +#define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]" +#else +#define LIST_REMOTE_INTERFACES_USAGE +#endif + +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE +#define IMMEDIATE_MODE_USAGE " [ --immediate-mode ]" +#else +#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 @@ -656,6 +718,7 @@ droproot(const char *username, const char *chroot_dir) } #ifdef HAVE_LIBCAP_NG /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */ +DIAG_OFF_CLANG(assign-enum) capng_updatev( CAPNG_DROP, CAPNG_EFFECTIVE | CAPNG_PERMITTED, @@ -663,6 +726,7 @@ droproot(const char *username, const char *chroot_dir) CAP_SETGID, CAP_SYS_CHROOT, -1); +DIAG_ON_CLANG(assign-enum) capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ @@ -865,10 +929,10 @@ set_dumper_capsicum_rights(pcap_dumper_t *p) * Copy arg vector into a new buffer, concatenating arguments with spaces. */ static char * -copy_argv(register char **argv) +copy_argv(char **argv) { - register char **p; - register u_int len = 0; + char **p; + u_int len = 0; char *buf; char *src, *dst; @@ -908,8 +972,8 @@ copy_argv(register char **argv) static char * read_infile(char *fname) { - register int i, fd, cc; - register char *cp; + int i, fd, cc; + char *cp; struct stat buf; fd = open(fname, O_RDONLY|O_BINARY); @@ -992,6 +1056,13 @@ find_interface_by_number(long devnum) } #endif +#ifdef HAVE_PCAP_OPEN +/* + * Prefix for rpcap URLs. + */ +static char rpcap_prefix[] = "rpcap://"; +#endif + static pcap_t * open_interface(const char *device, netdissect_options *ndo, char *ebuf) { @@ -1001,6 +1072,36 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) char *cp; #endif +#ifdef HAVE_PCAP_OPEN + /* + * Is this an rpcap URL? + */ + if (strncmp(device, rpcap_prefix, sizeof(rpcap_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 + * 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) + return (NULL); + error("%s", ebuf); + } + if (*ebuf) + warning("%s", ebuf); + return (pc); + } +#endif /* HAVE_PCAP_OPEN */ + #ifdef HAVE_PCAP_CREATE pc = pcap_create(device, ebuf); if (pc == NULL) { @@ -1181,10 +1282,10 @@ open_interface(const char *device, netdissect_options *ndo, char *ebuf) int main(int argc, char **argv) { - register int cnt, op, i; + int cnt, op, i; bpf_u_int32 localnet = 0, netmask = 0; int timezone_offset = 0; - register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; + char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; char *endp; pcap_handler callback; int dlt; @@ -1288,7 +1389,7 @@ main(int argc, char **argv) case 'C': errno = 0; -#ifdef HAVE_PCAP_FTELL64 +#ifdef HAVE_PCAP_DUMP_FTELL64 Cflag = strtoint64_t(optarg, &endp, 10); #else Cflag = strtol(optarg, &endp, 10); @@ -1299,8 +1400,8 @@ main(int argc, char **argv) /* * Will multiplying it by 1000000 overflow? */ -#ifdef HAVE_PCAP_FTELL64 - if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffffU) / 1000000) +#ifdef HAVE_PCAP_DUMP_FTELL64 + if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / 1000000) #else if (Cflag > LONG_MAX / 1000000) #endif @@ -1312,9 +1413,17 @@ main(int argc, char **argv) ++dflag; break; +#ifdef HAVE_PCAP_FINDALLDEVS case 'D': Dflag++; break; +#endif + +#ifdef HAVE_PCAP_FINDALLDEVS_EX + case OPTION_LIST_REMOTE_INTERFACES: + remote_interfaces_source = optarg; + break; +#endif case 'L': Lflag++; @@ -1621,6 +1730,10 @@ main(int argc, char **argv) if (Dflag) show_devices_and_exit(); #endif +#ifdef HAVE_PCAP_FINDALLDEVS_EX + if (remote_interfaces_source != NULL) + show_remote_devices_and_exit(); +#endif switch (ndo->ndo_tflag) { @@ -1895,8 +2008,8 @@ main(int argc, char **argv) #ifndef _WIN32 (void)setsignal(SIGPIPE, cleanup); (void)setsignal(SIGTERM, cleanup); - (void)setsignal(SIGINT, cleanup); #endif /* _WIN32 */ + (void)setsignal(SIGINT, cleanup); #if defined(HAVE_FORK) || defined(HAVE_VFORK) (void)setsignal(SIGCHLD, child_cleanup); #endif @@ -1930,27 +2043,33 @@ main(int argc, char **argv) /* Initialize capng */ capng_clear(CAPNG_SELECT_BOTH); if (username) { +DIAG_OFF_CLANG(assign-enum) capng_updatev( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_SETUID, CAP_SETGID, -1); +DIAG_ON_CLANG(assign-enum) } if (chroot_dir) { +DIAG_OFF_CLANG(assign-enum) capng_update( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_SYS_CHROOT ); +DIAG_ON_CLANG(assign-enum) } if (WFileName) { +DIAG_OFF_CLANG(assign-enum) capng_update( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE ); +DIAG_ON_CLANG(assign-enum) } capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ @@ -2085,14 +2204,32 @@ main(int argc, char **argv) *"-v" means tcpdump should, once per second, * "v"erbosely report the number of packets captured. */ -#ifdef USE_WIN32_MM_TIMER - /* call verbose_stats_dump() each 1000 +/-100msec */ - timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); +#ifdef _WIN32 + /* + * https://blogs.msdn.microsoft.com/oldnewthing/20151230-00/?p=92741 + * + * suggests that this dates back to W2K. + * + * I don't know what a "long wait" is, but we'll assume + * that printing the stats could be a "long wait". + */ + CreateTimerQueueTimer(&timer_handle, NULL, + verbose_stats_dump, NULL, 1000, 1000, + WT_EXECUTEDEFAULT|WT_EXECUTELONGFUNCTION); setvbuf(stderr, NULL, _IONBF, 0); -#elif defined(HAVE_ALARM) +#else /* _WIN32 */ + /* + * Assume this is UN*X, and that it has setitimer(); that + * dates back to UNIX 95. + */ + struct itimerval timer; (void)setsignal(SIGALRM, verbose_stats_dump); - alarm(1); -#endif + timer.it_interval.tv_sec = 1; + timer.it_interval.tv_usec = 0; + timer.it_value.tv_sec = 1; + timer.it_value.tv_usec = 1; + setitimer(ITIMER_REAL, &timer, NULL); +#endif /* _WIN32 */ } if (RFileName == NULL) { @@ -2276,13 +2413,21 @@ static void static void cleanup(int signo _U_) { -#ifdef USE_WIN32_MM_TIMER - if (timer_id) - timeKillEvent(timer_id); - timer_id = 0; -#elif defined(HAVE_ALARM) - alarm(0); -#endif +#ifdef _WIN32 + if (timer_handle != INVALID_HANDLE_VALUE) { + DeleteTimerQueueTimer(NULL, timer_handle, NULL); + CloseHandle(timer_handle); + timer_handle = INVALID_HANDLE_VALUE; + } +#else /* _WIN32 */ + struct itimerval timer; + + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = 0; + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &timer, NULL); +#endif /* _WIN32 */ #ifdef HAVE_PCAP_BREAKLOOP /* @@ -2326,7 +2471,7 @@ child_cleanup(int signo _U_) #endif /* HAVE_FORK && HAVE_VFORK */ static void -info(register int verbose) +info(int verbose) { struct pcap_stat stats; @@ -2549,7 +2694,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s * file could put it over Cflag. */ if (Cflag != 0) { -#ifdef HAVE_PCAP_FTELL64 +#ifdef HAVE_PCAP_DUMP_FTELL64 int64_t size = pcap_dump_ftell64(dump_info->p); #else /* @@ -2677,33 +2822,6 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) info(0); } -#ifdef _WIN32 - /* - * XXX - there should really be libpcap calls to get the version - * number as a string (the string would be generated from #defines - * at run time, so that it's not generated from string constants - * in the library, as, on many UNIX systems, those constants would - * be statically linked into the application executable image, and - * would thus reflect the version of libpcap on the system on - * which the application was *linked*, not the system on which it's - * *running*. - * - * That routine should be documented, unlike the "version[]" - * string, so that UNIX vendors providing their own libpcaps - * don't omit it (as a couple of vendors have...). - * - * Packet.dll should perhaps also export a routine to return the - * version number of the Packet.dll code, to supply the - * "Wpcap_version" information on Windows. - */ - char WDversion[]="current-git.tcpdump.org"; -#if !defined(HAVE_GENERATED_VERSION) - char version[]="current-git.tcpdump.org"; -#endif - char pcap_version[]="current-git.tcpdump.org"; - char Wpcap_version[]="3.1"; -#endif - #ifdef SIGNAL_REQ_INFO void requestinfo(int signo _U_) { @@ -2729,36 +2847,35 @@ print_packets_captured (void) /* * Called once each second in verbose mode while dumping to file */ -#ifdef USE_WIN32_MM_TIMER -void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, - DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) +#ifdef _WIN32 +static void CALLBACK verbose_stats_dump(PVOID param _U_, + BOOLEAN timer_fired _U_) { print_packets_captured(); } -#elif defined(HAVE_ALARM) +#else /* _WIN32 */ static void verbose_stats_dump(int sig _U_) { print_packets_captured(); - alarm(1); } -#endif +#endif /* _WIN32 */ USES_APPLE_DEPRECATED_API static void print_version(void) { #ifndef HAVE_PCAP_LIB_VERSION -#if defined(_WIN32) || defined(HAVE_PCAP_VERSION) + #ifdef HAVE_PCAP_VERSION extern char pcap_version[]; -#else /* defined(_WIN32) || defined(HAVE_PCAP_VERSION) */ + #else /* HAVE_PCAP_VERSION */ static char pcap_version[] = "unknown"; -#endif /* defined(_WIN32) || defined(HAVE_PCAP_VERSION) */ + #endif /* HAVE_PCAP_VERSION */ #endif /* HAVE_PCAP_LIB_VERSION */ const char *smi_version_string; (void)fprintf(stderr, "%s version " PACKAGE_VERSION "\n", program_name); #ifdef HAVE_PCAP_LIB_VERSION - (void)fprintf(stderr, "%s\n",pcap_lib_version()); + (void)fprintf(stderr, "%s\n", pcap_lib_version()); #else /* HAVE_PCAP_LIB_VERSION */ (void)fprintf(stderr, "libpcap version %s\n", pcap_version); #endif /* HAVE_PCAP_LIB_VERSION */ @@ -2793,29 +2910,21 @@ print_usage(void) (void)fprintf(stderr, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); (void)fprintf(stderr, -"\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ] [ --number ]\n"); - (void)fprintf(stderr, -"\t\t[ --print ]"); -#ifdef HAVE_PCAP_SETDIRECTION +"\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n"); +#ifdef HAVE_PCAP_FINDALLDEVS_EX (void)fprintf(stderr, -" [ -Q in|out|inout ]"); +"\t\t" LIST_REMOTE_INTERFACES_USAGE "\n"); #endif (void)fprintf(stderr, -" [ -r file ] [ -s snaplen ]\n"); -#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION +"\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n"); (void)fprintf(stderr, -"\t\t[ --time-stamp-precision precision ]\n"); +"\t\t[ -r file ] [ -s snaplen ]" TIME_STAMP_PRECISION_USAGE "\n"); (void)fprintf(stderr, -"\t\t"); -#endif -#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE - (void)fprintf(stderr, "[ --immediate-mode ] "); -#endif - (void)fprintf(stderr, "[ -T type ] [ --version ] [ -V file ]\n"); +"\t\t[ -T type ] [ --version ] [ -V file ] [ -w file ]\n"); (void)fprintf(stderr, -"\t\t[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ]\n"); +"\t\t[ -W filecount ] [ -y datalinktype ]\n"); (void)fprintf(stderr, -"\t\t[ -Z user ] [ expression ]\n"); +"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n"); } /* * Local Variables: