X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/ffa97fff7a3fe8aa6201af721d94256482dea029..85a2dd977cad3e21b475abbedeb795989207b8db:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 98ec2d5d..6809d005 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -29,8 +29,6 @@ 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"; -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.283 2008-09-25 21:45:50 guy Exp $ (LBL)"; #endif /* @@ -87,8 +85,8 @@ extern int SIZE_BUF; #include "gmt2local.h" #include "pcap-missing.h" -#ifndef NAME_MAX -#define NAME_MAX 255 +#ifndef PATH_MAX +#define PATH_MAX 1024 #endif #ifdef SIGINFO @@ -100,11 +98,15 @@ extern int SIZE_BUF; netdissect_options Gndo; netdissect_options *gndo = &Gndo; +static int Dflag; /* list available devices and exit */ static int dflag; /* print filter code */ static int Lflag; /* list available data link types and exit */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE static int Jflag; /* list available time stamp types */ #endif +#ifdef HAVE_PCAP_SETDIRECTION +int Qflag = -1; /* restrict captured packet by send/receive direction */ +#endif static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ static int infodelay; @@ -126,8 +128,16 @@ static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_ static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void droproot(const char *, const char *); static void ndo_error(netdissect_options *ndo, const char *fmt, ...) - __attribute__ ((noreturn, format (printf, 2, 3))); -static void ndo_warning(netdissect_options *ndo, const char *fmt, ...); + __attribute__((noreturn)) +#ifdef __ATTRIBUTE___FORMAT_OK + __attribute__((format (printf, 2, 3))) +#endif /* __ATTRIBUTE___FORMAT_OK */ + ; +static void ndo_warning(netdissect_options *ndo, const char *fmt, ...) +#ifdef __ATTRIBUTE___FORMAT_OK + __attribute__((format (printf, 2, 3))) +#endif /* __ATTRIBUTE___FORMAT_OK */ + ; #ifdef SIGNAL_REQ_INFO RETSIGTYPE requestinfo(int); @@ -156,21 +166,7 @@ struct ndo_printer { }; -static struct printer printers[] = { - { arcnet_if_print, DLT_ARCNET }, -#ifdef DLT_ARCNET_LINUX - { arcnet_linux_if_print, DLT_ARCNET_LINUX }, -#endif - { token_if_print, DLT_IEEE802 }, -#ifdef DLT_LANE8023 - { lane_if_print, DLT_LANE8023 }, -#endif -#ifdef DLT_CIP - { cip_if_print, DLT_CIP }, -#endif -#ifdef DLT_ATM_CLIP - { cip_if_print, DLT_ATM_CLIP }, -#endif +static const struct printer printers[] = { { sl_if_print, DLT_SLIP }, #ifdef DLT_SLIP_BSDOS { sl_bsdos_if_print, DLT_SLIP_BSDOS }, @@ -182,37 +178,16 @@ static struct printer printers[] = { #ifdef DLT_PPP_BSDOS { ppp_bsdos_if_print, DLT_PPP_BSDOS }, #endif - { fddi_if_print, DLT_FDDI }, - { null_if_print, DLT_NULL }, -#ifdef DLT_LOOP - { null_if_print, DLT_LOOP }, -#endif - { raw_if_print, DLT_RAW }, { atm_if_print, DLT_ATM_RFC1483 }, -#ifdef DLT_C_HDLC - { chdlc_if_print, DLT_C_HDLC }, -#endif -#ifdef DLT_HDLC - { chdlc_if_print, DLT_HDLC }, -#endif #ifdef DLT_PPP_SERIAL { ppp_hdlc_if_print, DLT_PPP_SERIAL }, #endif -#ifdef DLT_PPP_ETHER - { pppoe_if_print, DLT_PPP_ETHER }, -#endif -#ifdef DLT_LINUX_SLL - { sll_if_print, DLT_LINUX_SLL }, -#endif #ifdef DLT_IEEE802_11 { ieee802_11_if_print, DLT_IEEE802_11}, #endif #ifdef DLT_LTALK { ltalk_if_print, DLT_LTALK }, #endif -#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) - { pflog_if_print, DLT_PFLOG }, -#endif #ifdef DLT_FR { fr_if_print, DLT_FR }, #endif @@ -222,9 +197,6 @@ static struct printer printers[] = { #ifdef DLT_SUNATM { sunatm_if_print, DLT_SUNATM }, #endif -#ifdef DLT_IP_OVER_FC - { ipfc_if_print, DLT_IP_OVER_FC }, -#endif #ifdef DLT_PRISM_HEADER { prism_if_print, DLT_PRISM_HEADER }, #endif @@ -234,12 +206,6 @@ static struct printer printers[] = { #ifdef DLT_ENC { enc_if_print, DLT_ENC }, #endif -#ifdef DLT_SYMANTEC_FIREWALL - { symantec_if_print, DLT_SYMANTEC_FIREWALL }, -#endif -#ifdef DLT_APPLE_IP_OVER_IEEE1394 - { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, -#endif #ifdef DLT_IEEE802_11_RADIO_AVS { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, #endif @@ -290,28 +256,11 @@ static struct printer printers[] = { #endif #ifdef DLT_MFR { mfr_if_print, DLT_MFR }, -#endif -#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) - { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, -#endif -#ifdef HAVE_PCAP_USB_H -#ifdef DLT_USB_LINUX - { usb_linux_48_byte_print, DLT_USB_LINUX}, -#endif /* DLT_USB_LINUX */ -#ifdef DLT_USB_LINUX_MMAPPED - { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED}, -#endif /* DLT_USB_LINUX_MMAPPED */ -#endif /* HAVE_PCAP_USB_H */ -#ifdef DLT_IPV4 - { raw_if_print, DLT_IPV4 }, -#endif -#ifdef DLT_IPV6 - { raw_if_print, DLT_IPV6 }, #endif { NULL, 0 }, }; -static struct ndo_printer ndo_printers[] = { +static const struct ndo_printer ndo_printers[] = { { ether_if_print, DLT_EN10MB }, #ifdef DLT_IPNET { ipnet_if_print, DLT_IPNET }, @@ -330,14 +279,89 @@ static struct ndo_printer ndo_printers[] = { #endif #ifdef DLT_NETANALYZER_TRANSPARENT { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, +#endif +#if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) + { nflog_if_print, DLT_NFLOG}, +#endif +#ifdef DLT_CIP + { cip_if_print, DLT_CIP }, +#endif +#ifdef DLT_ATM_CLIP + { cip_if_print, DLT_ATM_CLIP }, +#endif +#ifdef DLT_IP_OVER_FC + { ipfc_if_print, DLT_IP_OVER_FC }, +#endif + { null_if_print, DLT_NULL }, +#ifdef DLT_LOOP + { null_if_print, DLT_LOOP }, +#endif +#ifdef DLT_APPLE_IP_OVER_IEEE1394 + { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, +#endif +#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) + { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, +#endif +#ifdef DLT_LANE8023 + { lane_if_print, DLT_LANE8023 }, +#endif + { arcnet_if_print, DLT_ARCNET }, +#ifdef DLT_ARCNET_LINUX + { arcnet_linux_if_print, DLT_ARCNET_LINUX }, +#endif + { raw_if_print, DLT_RAW }, +#ifdef DLT_IPV4 + { raw_if_print, DLT_IPV4 }, +#endif +#ifdef DLT_IPV6 + { raw_if_print, DLT_IPV6 }, +#endif +#ifdef HAVE_PCAP_USB_H +#ifdef DLT_USB_LINUX + { usb_linux_48_byte_print, DLT_USB_LINUX}, +#endif /* DLT_USB_LINUX */ +#ifdef DLT_USB_LINUX_MMAPPED + { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED}, +#endif /* DLT_USB_LINUX_MMAPPED */ +#endif /* HAVE_PCAP_USB_H */ +#ifdef DLT_SYMANTEC_FIREWALL + { symantec_if_print, DLT_SYMANTEC_FIREWALL }, +#endif +#ifdef DLT_C_HDLC + { chdlc_if_print, DLT_C_HDLC }, +#endif +#ifdef DLT_HDLC + { chdlc_if_print, DLT_HDLC }, +#endif +#ifdef DLT_PPP_ETHER + { pppoe_if_print, DLT_PPP_ETHER }, +#endif +#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) + { pflog_if_print, DLT_PFLOG }, +#endif + { token_if_print, DLT_IEEE802 }, + { fddi_if_print, DLT_FDDI }, +#ifdef DLT_LINUX_SLL + { sll_if_print, DLT_LINUX_SLL }, #endif { NULL, 0 }, }; +static const struct tok status_flags[] = { +#ifdef PCAP_IF_UP + { PCAP_IF_UP, "Up" }, +#endif +#ifdef PCAP_IF_RUNNING + { PCAP_IF_RUNNING, "Running" }, +#endif + { PCAP_IF_LOOPBACK, "Loopback" }, + { 0, NULL } +}; + if_printer lookup_printer(int type) { - struct printer *p; + const struct printer *p; for (p = printers; p->f; ++p) if (type == p->type) @@ -350,7 +374,7 @@ lookup_printer(int type) if_ndo_printer lookup_ndo_printer(int type) { - struct ndo_printer *p; + const struct ndo_printer *p; for (p = ndo_printers; p->f; ++p) if (type == p->type) @@ -471,6 +495,31 @@ show_dlts_and_exit(const char *device, pcap_t *pd) exit(0); } +#ifdef HAVE_PCAP_FINDALLDEVS +static void +show_devices_and_exit (void) +{ + pcap_if_t *devpointer; + char ebuf[PCAP_ERRBUF_SIZE]; + int i; + + if (pcap_findalldevs(&devpointer, ebuf) < 0) + error("%s", ebuf); + else { + for (i = 0; devpointer != NULL; i++) { + printf("%d.%s", i+1, devpointer->name); + if (devpointer->description != NULL) + printf(" (%s)", devpointer->description); + if (devpointer->flags != 0) + printf(" [%s]", bittok2str(status_flags, "none", devpointer->flags)); + printf("\n"); + devpointer = devpointer->next; + } + } + exit(0); +} +#endif /* HAVE_PCAP_FINDALLDEVS */ + /* * Set up flags that might or might not be supported depending on the * version of libpcap we're using. @@ -517,6 +566,12 @@ show_dlts_and_exit(const char *device, pcap_t *pd) #define U_FLAG #endif +#ifdef HAVE_PCAP_SETDIRECTION +#define Q_FLAG "Q:" +#else +#define Q_FLAG +#endif + #ifndef WIN32 /* Drop root privileges and chroot if necessary */ static void @@ -528,7 +583,7 @@ droproot(const char *username, const char *chroot_dir) fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); exit(1); } - + pw = getpwnam(username); if (pw) { if (chroot_dir) { @@ -554,7 +609,7 @@ droproot(const char *username, const char *chroot_dir) if (initgroups(pw->pw_name, pw->pw_gid) != 0 || setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", - username, + username, (unsigned long)pw->pw_uid, (unsigned long)pw->pw_gid, pcap_strerror(errno)); @@ -588,9 +643,9 @@ getWflagChars(int x) static void MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) { - char *filename = malloc(NAME_MAX + 1); + char *filename = malloc(PATH_MAX + 1); if (filename == NULL) - error("Makefilename: malloc); + error("Makefilename: malloc"); /* Process with strftime if Gflag is set. */ if (Gflag != 0) { @@ -604,24 +659,24 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) /* There's no good way to detect an error in strftime since a return * value of 0 isn't necessarily failure. */ - strftime(filename, NAME_MAX, orig_name, local_tm); + strftime(filename, PATH_MAX, orig_name, local_tm); } else { - strncpy(filename, orig_name, NAME_MAX); + strncpy(filename, orig_name, PATH_MAX); } if (cnt == 0 && max_chars == 0) - strncpy(buffer, filename, NAME_MAX + 1); + strncpy(buffer, filename, PATH_MAX + 1); else - if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_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)", NAME_MAX); + error("too many output files or filename is too long (> %d)", PATH_MAX); free(filename); } static int tcpdump_printf(netdissect_options *ndo _U_, const char *fmt, ...) { - + va_list args; int ret; @@ -632,14 +687,55 @@ static int tcpdump_printf(netdissect_options *ndo _U_, return ret; } +static struct print_info +get_print_info(int type) +{ + struct print_info printinfo; + + printinfo.ndo_type = 1; + printinfo.ndo = gndo; + printinfo.p.ndo_printer = lookup_ndo_printer(type); + if (printinfo.p.ndo_printer == NULL) { + printinfo.p.printer = lookup_printer(type); + printinfo.ndo_type = 0; + if (printinfo.p.printer == NULL) { + gndo->ndo_dltname = pcap_datalink_val_to_name(type); + if (gndo->ndo_dltname != NULL) + error("packet printing is not supported for link type %s: use -w", + gndo->ndo_dltname); + else + error("packet printing is not supported for link type %d: use -w", type); + } + } + return (printinfo); +} + +static char * +get_next_file(FILE *VFile, char *ptr) +{ + char *ret; + + ret = fgets(ptr, PATH_MAX, VFile); + if (!ret) + return NULL; + + if (ptr[strlen(ptr) - 1] == '\n') + ptr[strlen(ptr) - 1] = '\0'; + + return ret; +} + int main(int argc, char **argv) { register int cnt, op, i; - bpf_u_int32 localnet, netmask; - register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; + bpf_u_int32 localnet =0 , netmask = 0; + register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; pcap_handler callback; int type; + int dlt; + int new_dlt; + const char *dlt_name; struct bpf_program fcode; #ifndef WIN32 RETSIGTYPE (*oldhandler)(int); @@ -648,13 +744,17 @@ main(int argc, char **argv) struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; + char VFileLine[PATH_MAX + 1]; char *username = NULL; char *chroot_dir = NULL; + char *ret = NULL; + char *end; #ifdef HAVE_PCAP_FINDALLDEVS pcap_if_t *devpointer; int devnum; #endif int status; + FILE *VFile; #ifdef WIN32 if(wsockinit() != 0) return 1; #endif /* WIN32 */ @@ -668,12 +768,15 @@ main(int argc, char **argv) gndo->ndo_error=ndo_error; gndo->ndo_warning=ndo_warning; gndo->ndo_snaplen = DEFAULT_SNAPLEN; - + cnt = -1; device = NULL; infile = NULL; RFileName = NULL; + VFileName = NULL; + VFile = NULL; WFileName = NULL; + dlt = -1; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else @@ -687,7 +790,7 @@ main(int argc, char **argv) #endif while ( - (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1) + (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:")) != -1) switch (op) { case 'a': @@ -726,21 +829,9 @@ main(int argc, char **argv) ++dflag; break; -#ifdef HAVE_PCAP_FINDALLDEVS case 'D': - if (pcap_findalldevs(&devpointer, ebuf) < 0) - error("%s", ebuf); - else { - for (i = 0; devpointer != 0; i++) { - printf("%d.%s", i+1, devpointer->name); - if (devpointer->description != NULL) - printf(" (%s)", devpointer->description); - printf("\n"); - devpointer = devpointer->next; - } - } - return 0; -#endif /* HAVE_PCAP_FINDALLDEVS */ + Dflag++; + break; case 'L': Lflag++; @@ -791,7 +882,7 @@ main(int argc, char **argv) case 'i': if (optarg[0] == '0' && optarg[1] == 0) error("Invalid adapter index"); - + #ifdef HAVE_PCAP_FINDALLDEVS /* * If the argument is a number, treat it as @@ -803,7 +894,8 @@ main(int argc, char **argv) * It can be useful on Windows, where more than * one interface can have the same name. */ - if ((devnum = atoi(optarg)) != 0) { + devnum = strtol(optarg, &end, 10); + if (optarg != end && *end == '\0') { if (devnum < 0) error("Invalid adapter index"); @@ -914,6 +1006,19 @@ main(int argc, char **argv) ++suppress_default_print; break; +#ifdef HAVE_PCAP_SETDIRECTION + case 'Q': + if (strcasecmp(optarg, "in") == 0) + Qflag = PCAP_D_IN; + else if (strcasecmp(optarg, "out") == 0) + Qflag = PCAP_D_OUT; + else if (strcasecmp(optarg, "inout") == 0) + Qflag = PCAP_D_INOUT; + else + error("unknown capture direction `%s'", optarg); + break; +#endif /* HAVE_PCAP_SETDIRECTION */ + case 'r': RFileName = optarg; break; @@ -922,9 +1027,7 @@ main(int argc, char **argv) Rflag = 0; break; - case 's': { - char *end; - + case 's': snaplen = strtol(optarg, &end, 0); if (optarg == end || *end != '\0' || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN) @@ -932,7 +1035,6 @@ main(int argc, char **argv) else if (snaplen == 0) snaplen = MAXIMUM_SNAPLEN; break; - } case 'S': ++Sflag; @@ -965,6 +1067,16 @@ main(int argc, char **argv) packettype = PT_CARP; else if (strcasecmp(optarg, "radius") == 0) packettype = PT_RADIUS; + else if (strcasecmp(optarg, "zmtp1") == 0) + packettype = PT_ZMTP1; + else if (strcasecmp(optarg, "vxlan") == 0) + packettype = PT_VXLAN; + else if (strcasecmp(optarg, "pgm") == 0) + packettype = PT_PGM; + else if (strcasecmp(optarg, "pgm_zmtp1") == 0) + packettype = PT_PGM_ZMTP1; + else if (strcasecmp(optarg, "lmp") == 0) + packettype = PT_LMP; else error("unknown packet type `%s'", optarg); break; @@ -983,13 +1095,17 @@ main(int argc, char **argv) ++vflag; break; + case 'V': + VFileName = optarg; + break; + case 'w': WFileName = optarg; break; case 'W': Wflag = atoi(optarg); - if (Wflag < 0) + if (Wflag < 0) error("invalid number of output files %s", optarg); WflagChars = getWflagChars(Wflag); break; @@ -1027,22 +1143,11 @@ main(int argc, char **argv) break; #endif case 'z': - if (optarg) { - zflag = strdup(optarg); - } else { - usage(); - /* NOTREACHED */ - } + zflag = strdup(optarg); break; case 'Z': - if (optarg) { - username = strdup(optarg); - } - else { - usage(); - /* NOTREACHED */ - } + username = strdup(optarg); break; default: @@ -1050,6 +1155,11 @@ main(int argc, char **argv) /* NOTREACHED */ } +#ifdef HAVE_PCAP_FINDALLDEVS + if (Dflag) + show_devices_and_exit(); +#endif + switch (tflag) { case 0: /* Default */ @@ -1068,6 +1178,12 @@ main(int argc, char **argv) break; } + if (fflag != 0 && (VFileName != NULL || RFileName != NULL)) + error("-f can not be used with -V or -r"); + + if (VFileName != NULL && RFileName != NULL) + error("-V and -r are mutually exclusive."); + #ifdef WITH_CHROOT /* if run as root, prepare for chrooting */ if (getuid() == 0 || geteuid() == 0) { @@ -1080,16 +1196,22 @@ main(int argc, char **argv) #ifdef WITH_USER /* if run as root, prepare for dropping root privileges */ if (getuid() == 0 || geteuid() == 0) { - /* Run with '-Z root' to restore old behaviour */ + /* Run with '-Z root' to restore old behaviour */ if (!username) username = WITH_USER; } #endif - if (RFileName != NULL) { - int dlt; - const char *dlt_name; - + if (RFileName != NULL || VFileName != NULL) { + /* + * If RFileName is non-null, it's the pathname of a + * savefile to read. If VFileName is non-null, it's + * the pathname of a file containing a list of pathnames + * (one per line) of savefiles to read. + * + * In either case, we're reading a savefile, not doing + * a live capture. + */ #ifndef WIN32 /* * We don't need network access, so relinquish any set-UID @@ -1103,6 +1225,21 @@ main(int argc, char **argv) if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) fprintf(stderr, "Warning: setgid/setuid failed !\n"); #endif /* WIN32 */ + if (VFileName != NULL) { + if (VFileName[0] == '-' && VFileName[1] == '\0') + VFile = stdin; + else + VFile = fopen(VFileName, "r"); + + if (VFile == NULL) + error("Unable to open file: %s\n", strerror(errno)); + + ret = get_next_file(VFile, VFileLine); + if (!ret) + error("Nothing in %s\n", VFileName); + RFileName = VFileLine; + } + pd = pcap_open_offline(RFileName, ebuf); if (pd == NULL) error("%s", ebuf); @@ -1117,19 +1254,22 @@ main(int argc, char **argv) RFileName, dlt_name, pcap_datalink_val_to_description(dlt)); } - localnet = 0; - netmask = 0; - if (fflag != 0) - error("-f and -r options are incompatible"); } else { + /* + * We're doing a live capture. + */ if (device == NULL) { device = pcap_lookupdev(ebuf); if (device == NULL) error("%s", ebuf); } #ifdef WIN32 - if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char - { //a Unicode string has a \0 as second byte (so strlen() is 1) + /* + * Print a message to the standard error on Windows. + * XXX - why do it here, with a different message? + */ + if(strlen(device) == 1) /* we assume that an ASCII string is always longer than 1 char */ + { /* a Unicode string has a \0 as second byte (so strlen() is 1) */ fprintf(stderr, "%s: listening on %ws\n", program_name, device); } else @@ -1137,7 +1277,7 @@ main(int argc, char **argv) fprintf(stderr, "%s: listening on %s\n", program_name, device); } - fflush(stderr); + fflush(stderr); #endif /* WIN32 */ #ifdef HAVE_PCAP_CREATE pd = pcap_create(device, ebuf); @@ -1218,6 +1358,14 @@ main(int argc, char **argv) warning("%s: %s", device, pcap_statustostr(status)); } +#ifdef HAVE_PCAP_SETDIRECTION + if (Qflag != -1) { + status = pcap_setdirection(pd, Qflag); + if (status != 0) + error("%s: pcap_setdirection() failed: %s", + device, pcap_geterr(pd)); + } +#endif /* HAVE_PCAP_SETDIRECTION */ #else *ebuf = '\0'; pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); @@ -1265,11 +1413,12 @@ main(int argc, char **argv) warning("snaplen raised from %d to %d", snaplen, i); snaplen = i; } - if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { - localnet = 0; - netmask = 0; - warning("%s", ebuf); - } + if(fflag != 0) { + if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { + warning("foreign (-f) flag used but: %s", ebuf); + } + } + } if (infile) cmdbuf = read_infile(infile); @@ -1278,16 +1427,16 @@ main(int argc, char **argv) if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); - free(cmdbuf); if (dflag) { bpf_dump(&fcode, dflag); pcap_close(pd); + free(cmdbuf); exit(0); } init_addrtoname(localnet, netmask); init_checksum(); -#ifndef WIN32 +#ifndef WIN32 (void)setsignal(SIGPIPE, cleanup); (void)setsignal(SIGTERM, cleanup); (void)setsignal(SIGINT, cleanup); @@ -1296,7 +1445,7 @@ main(int argc, char **argv) (void)setsignal(SIGCHLD, child_cleanup); #endif /* Cooperate with nohup(1) */ -#ifndef WIN32 +#ifndef WIN32 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) (void)setsignal(SIGHUP, oldhandler); #endif /* WIN32 */ @@ -1351,8 +1500,8 @@ main(int argc, char **argv) error("%s", pcap_geterr(pd)); if (WFileName) { pcap_dumper_t *p; - /* Do not exceed the default NAME_MAX for files. */ - dumpinfo.CurrentFileName = (char *)malloc(NAME_MAX + 1); + /* Do not exceed the default PATH_MAX for files. */ + dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dumpinfo.CurrentFileName == NULL) error("malloc of dumpinfo.CurrentFileName"); @@ -1386,21 +1535,7 @@ main(int argc, char **argv) #endif } else { type = pcap_datalink(pd); - printinfo.ndo_type = 1; - printinfo.ndo = gndo; - printinfo.p.ndo_printer = lookup_ndo_printer(type); - if (printinfo.p.ndo_printer == NULL) { - printinfo.p.printer = lookup_printer(type); - printinfo.ndo_type = 0; - if (printinfo.p.printer == NULL) { - gndo->ndo_dltname = pcap_datalink_val_to_name(type); - if (gndo->ndo_dltname != NULL) - error("packet printing is not supported for link type %s: use -w", - gndo->ndo_dltname); - else - error("packet printing is not supported for link type %d: use -w", type); - } - } + printinfo = get_print_info(type); callback = print_packet; pcap_userdata = (u_char *)&printinfo; } @@ -1432,9 +1567,11 @@ main(int argc, char **argv) #ifndef WIN32 if (RFileName == NULL) { - int dlt; - const char *dlt_name; - + /* + * Live capture (if -V was specified, we set RFileName + * to a file from the -V file). Print a message to + * the standard error on UN*X. + */ if (!vflag && !WFileName) { (void)fprintf(stderr, "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", @@ -1454,37 +1591,77 @@ main(int argc, char **argv) (void)fflush(stderr); } #endif /* WIN32 */ - status = pcap_loop(pd, cnt, callback, pcap_userdata); - if (WFileName == NULL) { - /* - * We're printing packets. Flush the printed output, - * so it doesn't get intermingled with error output. - */ - if (status == -2) { + do { + status = pcap_loop(pd, cnt, callback, pcap_userdata); + if (WFileName == NULL) { /* - * We got interrupted, so perhaps we didn't - * manage to finish a line we were printing. - * Print an extra newline, just in case. + * We're printing packets. Flush the printed output, + * so it doesn't get intermingled with error output. */ - putchar('\n'); + if (status == -2) { + /* + * 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'); + } + (void)fflush(stdout); + } + if (status == -2) { + /* + * We got interrupted. If we are reading multiple + * files (via -V) set these so that we stop. + */ + VFileName = NULL; + ret = NULL; + } + if (status == -1) { + /* + * Error. Report it. + */ + (void)fprintf(stderr, "%s: pcap_loop: %s\n", + program_name, pcap_geterr(pd)); + } + if (RFileName == NULL) { + /* + * We're doing a live capture. Report the capture + * statistics. + */ + info(1); + } + pcap_close(pd); + if (VFileName != NULL) { + ret = get_next_file(VFile, VFileLine); + if (ret) { + RFileName = VFileLine; + pd = pcap_open_offline(RFileName, ebuf); + if (pd == NULL) + error("%s", ebuf); + new_dlt = pcap_datalink(pd); + if (WFileName && new_dlt != dlt) + error("%s: new dlt does not match original", RFileName); + printinfo = get_print_info(new_dlt); + dlt_name = pcap_datalink_val_to_name(new_dlt); + if (dlt_name == NULL) { + fprintf(stderr, "reading from file %s, link-type %u\n", + RFileName, new_dlt); + } else { + fprintf(stderr, + "reading from file %s, link-type %s (%s)\n", + RFileName, dlt_name, + pcap_datalink_val_to_description(new_dlt)); + } + if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) + error("%s", pcap_geterr(pd)); + if (pcap_setfilter(pd, &fcode) < 0) + error("%s", pcap_geterr(pd)); + } } - (void)fflush(stdout); - } - if (status == -1) { - /* - * Error. Report it. - */ - (void)fprintf(stderr, "%s: pcap_loop: %s\n", - program_name, pcap_geterr(pd)); - } - if (RFileName == NULL) { - /* - * We're doing a live capture. Report the capture - * statistics. - */ - info(1); } - pcap_close(pd); + while (ret != NULL); + + free(cmdbuf); exit(status == -1 ? 1 : 0); } @@ -1685,9 +1862,16 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s if (dump_info->CurrentFileName != NULL) free(dump_info->CurrentFileName); /* Allocate space for max filename + \0. */ - dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1); + dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dump_info->CurrentFileName == NULL) error("dump_packet_and_trunc: malloc"); + /* + * Gflag was set otherwise we wouldn't be here. Reset the count + * so multiple files would end with 1,2,3 in the filename. + * The counting is handled with the -C flow after this. + */ + Cflag_count = 0; + /* * This is always the first file in the Cflag * rotation: e.g. 0 @@ -1737,7 +1921,7 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s } if (dump_info->CurrentFileName != NULL) free(dump_info->CurrentFileName); - dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1); + dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dump_info->CurrentFileName == NULL) error("dump_packet_and_trunc: malloc"); MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); @@ -1780,6 +1964,7 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { struct print_info *print_info; u_int hdrlen; + netdissect_options *ndo; ++packets_captured; @@ -1787,29 +1972,30 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) ts_print(&h->ts); print_info = (struct print_info *)user; + ndo = print_info->ndo; /* * Some printers want to check that they're not walking off the * end of the packet. * Rather than pass it all the way down, we set this global. */ - snapend = sp + h->caplen; + ndo->ndo_snapend = sp + h->caplen; if(print_info->ndo_type) { hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp); } else { hdrlen = (*print_info->p.printer)(h, sp); } - - if (Xflag) { + + if (ndo->ndo_Xflag) { /* * Print the raw packet data in hex and ASCII. */ - if (Xflag > 1) { + if (ndo->ndo_Xflag > 1) { /* * Include the link-layer header. */ - hex_and_ascii_print("\n\t", sp, h->caplen); + hex_and_ascii_print(ndo, "\n\t", sp, h->caplen); } else { /* * Don't include the link-layer header - and if @@ -1817,18 +2003,18 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) * print nothing. */ if (h->caplen > hdrlen) - hex_and_ascii_print("\n\t", sp + hdrlen, + hex_and_ascii_print(ndo, "\n\t", sp + hdrlen, h->caplen - hdrlen); } - } else if (xflag) { + } else if (ndo->ndo_xflag) { /* * Print the raw packet data in hex. */ - if (xflag > 1) { + if (ndo->ndo_xflag > 1) { /* * Include the link-layer header. */ - hex_print("\n\t", sp, h->caplen); + hex_print(ndo, "\n\t", sp, h->caplen); } else { /* * Don't include the link-layer header - and if @@ -1836,14 +2022,14 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) * print nothing. */ if (h->caplen > hdrlen) - hex_print("\n\t", sp + hdrlen, - h->caplen - hdrlen); + hex_print(ndo, "\n\t", sp + hdrlen, + h->caplen - hdrlen); } - } else if (Aflag) { + } else if (ndo->ndo_Aflag) { /* * Print the raw packet data in ASCII. */ - if (Aflag > 1) { + if (ndo->ndo_Aflag > 1) { /* * Include the link-layer header. */ @@ -1885,11 +2071,11 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) * version number of the Packet.dll code, to supply the * "Wpcap_version" information on Windows. */ - char WDversion[]="current-cvs.tcpdump.org"; + char WDversion[]="current-git.tcpdump.org"; #if !defined(HAVE_GENERATED_VERSION) - char version[]="current-cvs.tcpdump.org"; + char version[]="current-git.tcpdump.org"; #endif - char pcap_version[]="current-cvs.tcpdump.org"; + char pcap_version[]="current-git.tcpdump.org"; char Wpcap_version[]="3.1"; #endif @@ -1897,9 +2083,9 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) * By default, print the specified data out in hex and ASCII. */ static void -ndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length) +ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length) { - hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */ + hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and identation string */ } void @@ -1975,8 +2161,12 @@ usage(void) "\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 ]\n"); +#ifdef HAVE_PCAP_SETDIRECTION (void)fprintf(stderr, -"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n"); +"\t\t[ -Q in|out|inout ]\n"); +#endif + (void)fprintf(stderr, +"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]\n"); (void)fprintf(stderr, "\t\t[ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); (void)fprintf(stderr, @@ -2021,3 +2211,9 @@ ndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) (void)fputc('\n', stderr); } } +/* + * Local Variables: + * c-style: whitesmith + * c-basic-offset: 8 + * End: + */