X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/1afd3f308e25f7bf070f3932a28ed6b2be8173f6..d00d1670cec6b90d8b8e94c2b6b37f5a08d0ce17:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index c43ab854..739f9c8a 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -87,8 +87,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 @@ -105,6 +105,9 @@ 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 Pflag = -1; /* Restrict captured packet by sent/receive direction */ +#endif static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ static int infodelay; @@ -330,6 +333,9 @@ static struct ndo_printer ndo_printers[] = { #endif #ifdef DLT_NETANALYZER_TRANSPARENT { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, +#endif +#ifdef DLT_NFLOG + { nflog_if_print, DLT_NFLOG}, #endif { NULL, 0 }, }; @@ -517,6 +523,12 @@ show_dlts_and_exit(const char *device, pcap_t *pd) #define U_FLAG #endif +#ifdef HAVE_PCAP_SETDIRECTION +#define P_FLAG "P:" +#else +#define P_FLAG +#endif + #ifndef WIN32 /* Drop root privileges and chroot if necessary */ static void @@ -588,9 +600,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,17 +616,17 @@ 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); } @@ -632,7 +644,9 @@ static int tcpdump_printf(netdissect_options *ndo _U_, return ret; } -struct print_info get_print_info(int type) { +static struct print_info +get_print_info(int type) +{ struct print_info printinfo; printinfo.ndo_type = 1; @@ -653,10 +667,12 @@ struct print_info get_print_info(int type) { return (printinfo); } -char *get_next_file(FILE *VFile, char *ptr) { +static char * +get_next_file(FILE *VFile, char *ptr) +{ char *ret; - ret = fgets(ptr, NAME_MAX, VFile); + ret = fgets(ptr, PATH_MAX, VFile); if (!ret) return NULL; @@ -685,10 +701,11 @@ main(int argc, char **argv) struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; - char VFileLine[NAME_MAX + 1]; + 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; @@ -714,7 +731,9 @@ main(int argc, char **argv) infile = NULL; RFileName = NULL; VFileName = NULL; + VFile = NULL; WFileName = NULL; + dlt = -1; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else @@ -728,7 +747,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 "V: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:nNOp" P_FLAG "qr:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:")) != -1) switch (op) { case 'a': @@ -844,7 +863,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"); @@ -949,7 +969,18 @@ main(int argc, char **argv) case 'p': ++pflag; break; - +#ifdef HAVE_PCAP_SETDIRECTION + case 'P': + if (strcasecmp(optarg, "in") == 0) + Pflag = PCAP_D_IN; + else if (strcasecmp(optarg, "out") == 0) + Pflag = PCAP_D_OUT; + else if (strcasecmp(optarg, "inout") == 0) + Pflag = PCAP_D_INOUT; + else + error("unknown capture direction `%s'", optarg); + break; +#endif /* HAVE_PCAP_SETDIRECTION */ case 'q': ++qflag; ++suppress_default_print; @@ -963,9 +994,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) @@ -973,7 +1002,6 @@ main(int argc, char **argv) else if (snaplen == 0) snaplen = MAXIMUM_SNAPLEN; break; - } case 'S': ++Sflag; @@ -1006,6 +1034,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; @@ -1138,6 +1176,15 @@ main(int argc, char **argv) #endif 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 @@ -1183,14 +1230,21 @@ main(int argc, char **argv) localnet = 0; netmask = 0; } 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 @@ -1279,6 +1333,14 @@ main(int argc, char **argv) warning("%s: %s", device, pcap_statustostr(status)); } +#ifdef HAVE_PCAP_SETDIRECTION + if (Pflag != -1) { + status = pcap_setdirection(pd, Pflag); + if (status != 0) + error("%s: pcap_setdirection() failed: %s", + device, pcap_geterr(pd)); + } +#endif #else *ebuf = '\0'; pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); @@ -1412,8 +1474,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"); @@ -1479,6 +1541,11 @@ main(int argc, char **argv) #ifndef WIN32 if (RFileName == NULL) { + /* + * 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", @@ -1515,6 +1582,14 @@ main(int argc, char **argv) } (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. @@ -1761,7 +1836,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); /* 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"); /* @@ -1813,7 +1888,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); @@ -2051,6 +2126,10 @@ 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[ -P in|out|inout ]\n"); +#endif (void)fprintf(stderr, "\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]\n"); (void)fprintf(stderr,