X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/70bc9330d1b3fd6cd1fbd324ae222cd3fd39fcce..a6df5512cfdf7d7221d63d40d7329eaae6b93481:/tcpdump.c diff --git a/tcpdump.c b/tcpdump.c index 44032842..116f3daa 100644 --- a/tcpdump.c +++ b/tcpdump.c @@ -30,7 +30,7 @@ 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.242 2004-04-07 08:14:10 guy Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.265 2005-12-13 08:37:22 hannes Exp $ (LBL)"; #endif /* @@ -79,18 +79,15 @@ extern int SIZE_BUF; #include "gmt2local.h" #include "pcap-missing.h" +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + netdissect_options Gndo; netdissect_options *gndo = &Gndo; -/* - * Define the maximum number of files for the -C flag, and how many - * characters can be added to a filename for the -C flag (which - * should be enough to handle MAX_CFLAG - 1). - */ -#define MAX_CFLAG 1000000 -#define MAX_CFLAG_CHARS 6 - -int Lflag; /* list available data link types and exit */ +int dflag; /* print filter code */ +int Lflag; /* list available data link types and exit */ static int infodelay; static int infoprint; @@ -105,6 +102,7 @@ static void usage(void) __attribute__((noreturn)); static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn)); static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); +static void ndo_default_print(netdissect_options *, const u_char *, u_int); static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void droproot(const char *, const char *); @@ -154,6 +152,9 @@ static struct printer printers[] = { { sl_bsdos_if_print, DLT_SLIP_BSDOS }, #endif { ppp_if_print, DLT_PPP }, +#ifdef DLT_PPP_WITHDIRECTION + { ppp_if_print, DLT_PPP_WITHDIRECTION }, +#endif #ifdef DLT_PPP_BSDOS { ppp_bsdos_if_print, DLT_PPP_BSDOS }, #endif @@ -214,6 +215,51 @@ static struct printer printers[] = { #endif #ifdef DLT_APPLE_IP_OVER_IEEE1394 { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, +#endif +#ifdef DLT_JUNIPER_ATM1 + { juniper_atm1_print, DLT_JUNIPER_ATM1 }, +#endif +#ifdef DLT_JUNIPER_ATM2 + { juniper_atm2_print, DLT_JUNIPER_ATM2 }, +#endif +#ifdef DLT_JUNIPER_MFR + { juniper_mfr_print, DLT_JUNIPER_MFR }, +#endif +#ifdef DLT_JUNIPER_MLFR + { juniper_mlfr_print, DLT_JUNIPER_MLFR }, +#endif +#ifdef DLT_JUNIPER_MLPPP + { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, +#endif +#ifdef DLT_JUNIPER_PPPOE + { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, +#endif +#ifdef DLT_JUNIPER_PPPOE_ATM + { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, +#endif +#ifdef DLT_JUNIPER_GGSN + { juniper_ggsn_print, DLT_JUNIPER_GGSN }, +#endif +#ifdef DLT_JUNIPER_ES + { juniper_es_print, DLT_JUNIPER_ES }, +#endif +#ifdef DLT_JUNIPER_MONITOR + { juniper_monitor_print, DLT_JUNIPER_MONITOR }, +#endif +#ifdef DLT_JUNIPER_SERVICES + { juniper_services_print, DLT_JUNIPER_SERVICES }, +#endif +#ifdef DLT_JUNIPER_ETHER + { juniper_ether_print, DLT_JUNIPER_ETHER }, +#endif +#ifdef DLT_JUNIPER_PPP + { juniper_ppp_print, DLT_JUNIPER_PPP }, +#endif +#ifdef DLT_JUNIPER_FRELAY + { juniper_frelay_print, DLT_JUNIPER_FRELAY }, +#endif +#ifdef DLT_JUNIPER_CHDLC + { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, #endif { NULL, 0 }, }; @@ -370,10 +416,32 @@ getWflagChars(int x) static void MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) { + char *filename = malloc(NAME_MAX + 1); + + /* Process with strftime if Gflag is set. */ + if (Gflag != 0) { + struct tm *local_tm; + + /* Convert Gflag_time to a usable format */ + if ((local_tm = localtime(&Gflag_time)) == NULL) { + error("MakeTimedFilename: localtime"); + } + + /* 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); + } else { + strncpy(filename, orig_name, NAME_MAX); + } + if (cnt == 0 && max_chars == 0) - strcpy(buffer, orig_name); + strncpy(buffer, filename, NAME_MAX + 1); else - sprintf(buffer, "%s%0*d", orig_name, max_chars, cnt); + if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX) + /* Report an error if the filename is too large */ + error("too many output files or filename is too long (> %d)", NAME_MAX); + free(filename); } static int tcpdump_printf(netdissect_options *ndo _U_, @@ -388,7 +456,7 @@ static int tcpdump_printf(netdissect_options *ndo _U_, va_end(args); return ret; -}; +} int main(int argc, char **argv) @@ -420,8 +488,8 @@ main(int argc, char **argv) gndo->ndo_Oflag=1; gndo->ndo_Rflag=1; - gndo->ndo_tflag=1; gndo->ndo_dlt=-1; + gndo->ndo_default_print=ndo_default_print; gndo->ndo_printf=tcpdump_printf; gndo->ndo_error=ndo_error; gndo->ndo_warning=ndo_warning; @@ -446,7 +514,7 @@ main(int argc, char **argv) opterr = 0; while ( - (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1) + (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1) switch (op) { case 'a': @@ -454,8 +522,6 @@ main(int argc, char **argv) break; case 'A': - ++xflag; - ++Xflag; ++Aflag; break; @@ -522,6 +588,21 @@ main(int argc, char **argv) infile = optarg; break; + case 'G': + Gflag = atoi(optarg); + if (Gflag < 0) + error("invalid number of seconds %s", optarg); + + /* We will create one file initially. */ + Gflag_count = 0; + + /* Grab the current time for rotation use. */ + if ((Gflag_time = time(NULL)) == (time_t)-1) { + error("main: can't get current time: %s", + pcap_strerror(errno)); + } + break; + case 'i': if (optarg[0] == '0' && optarg[1] == 0) error("Invalid adapter index"); @@ -588,9 +669,9 @@ main(int argc, char **argv) case 'm': #ifdef LIBSMI - if (smiLoadModule(optarg) == 0) { + if (smiLoadModule(optarg) == 0) { error("could not load MIB module %s", optarg); - } + } sflag = 1; #else (void)fprintf(stderr, "%s: ignoring option `-m %s' ", @@ -617,6 +698,7 @@ main(int argc, char **argv) case 'q': ++qflag; + ++suppress_default_print; break; case 'r': @@ -644,7 +726,7 @@ main(int argc, char **argv) break; case 't': - --tflag; + ++tflag; break; case 'T': @@ -697,11 +779,12 @@ main(int argc, char **argv) case 'x': ++xflag; + ++suppress_default_print; break; case 'X': - ++xflag; ++Xflag; + ++suppress_default_print; break; case 'y': @@ -741,8 +824,23 @@ main(int argc, char **argv) /* NOTREACHED */ } - if (tflag > 0) + switch (tflag) { + + case 0: /* Default */ + case 4: /* Default + Date*/ thiszone = 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 */ + break; + + default: /* Not supported */ + error("only -t, -tt, -ttt, -tttt and -ttttt are supported"); + break; + } #ifdef WITH_CHROOT /* if run as root, prepare for chrooting */ @@ -852,7 +950,7 @@ main(int argc, char **argv) } #endif (void)fprintf(stderr, "%s: data link type %s\n", - program_name, gndo->ndo_dltname); + program_name, gndo->ndo_dltname); (void)fflush(stderr); } i = pcap_snapshot(pd); @@ -895,15 +993,23 @@ 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. */ + WFileNameAlt = (char *)malloc(NAME_MAX + 1); - WFileNameAlt = (char *)malloc(strlen(WFileName) + MAX_CFLAG_CHARS + 1); if (WFileNameAlt == NULL) error("malloc of WFileNameAlt"); - MakeFilename(WFileNameAlt, WFileName, 0, WflagChars); + + /* We do not need numbering for dumpfiles if Cflag isn't set. */ + if (Cflag != 0) + MakeFilename(WFileNameAlt, WFileName, 0, WflagChars); + else + MakeFilename(WFileNameAlt, WFileName, 0, 0); + p = pcap_dump_open(pd, WFileNameAlt); + free(WFileNameAlt); if (p == NULL) error("%s", pcap_geterr(pd)); - if (Cflag != 0) { + if (Cflag != 0 || Gflag != 0) { callback = dump_packet_and_trunc; dumpinfo.WFileName = WFileName; dumpinfo.pd = pd; @@ -1095,12 +1201,74 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s dump_info = (struct dump_info *)user; + /* + * XXX - this won't force the file to rotate on the specified time + * boundary, but it will rotate on the first packet received after the + * specified Gflag number of seconds. Note: if a Gflag time boundary + * and a Cflag size boundary coincide, the time rotation will occur + * first thereby cancelling the Cflag boundary (since the file should + * be 0). + */ + if (Gflag != 0) { + /* Check if it is time to rotate */ + time_t t; + + /* Get the current time */ + if ((t = time(NULL)) == (time_t)-1) { + error("dump_and_trunc_packet: can't get current_time: %s", + pcap_strerror(errno)); + } + + + /* If the time is greater than the specified window, rotate */ + if (t - Gflag_time >= Gflag) { + /* Update the Gflag_time */ + Gflag_time = t; + /* Update Gflag_count */ + Gflag_count++; + /* + * Close the current file and open a new one. + */ + pcap_dump_close(dump_info->p); + + /* + * Check to see if we've exceeded the Wflag (when + * not using Cflag). + */ + if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) { + (void)fprintf(stderr, "Maximum file limit reached: %d\n", + Wflag); + exit(0); + /* NOTREACHED */ + } + /* Allocate space for max filename + \0. */ + name = (char *)malloc(NAME_MAX + 1); + if (name == NULL) + error("dump_packet_and_trunc: malloc"); + /* + * This is always the first file in the Cflag + * rotation: e.g. 0 + * We also don't need numbering if Cflag is not set. + */ + if (Cflag != 0) + MakeFilename(name, dump_info->WFileName, 0, + WflagChars); + else + MakeFilename(name, dump_info->WFileName, 0, 0); + + dump_info->p = pcap_dump_open(dump_info->pd, name); + free(name); + if (dump_info->p == NULL) + error("%s", pcap_geterr(pd)); + } + } + /* * XXX - this won't prevent capture files from getting * larger than Cflag - the last packet written to the * file could put it over Cflag. */ - if (ftell((FILE *)dump_info->p) > Cflag) { + if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { /* * Close the current file and open a new one. */ @@ -1109,11 +1277,8 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s if (Wflag > 0) { if (Cflag_count >= Wflag) Cflag_count = 0; - } else { - if (Cflag_count >= MAX_CFLAG) - error("too many output files"); } - name = (char *)malloc(strlen(dump_info->WFileName) + MAX_CFLAG_CHARS + 1); + name = (char *)malloc(NAME_MAX + 1); if (name == NULL) error("dump_packet_and_trunc: malloc"); MakeFilename(name, dump_info->WFileName, Cflag_count, WflagChars); @@ -1173,15 +1338,34 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) snapend = sp + h->caplen; hdrlen = (*print_info->printer)(h, sp); - if (xflag) { + if (Xflag) { + /* + * Print the raw packet data in hex and ASCII. + */ + if (Xflag > 1) { + /* + * Include the link-layer header. + */ + hex_and_ascii_print("\n\t", sp, h->caplen); + } else { + /* + * Don't include the link-layer header - and if + * we have nothing past the link-layer header, + * print nothing. + */ + if (h->caplen > hdrlen) + hex_and_ascii_print("\n\t", sp + hdrlen, + h->caplen - hdrlen); + } + } else if (xflag) { /* - * Print the raw packet data. + * Print the raw packet data in hex. */ if (xflag > 1) { /* * Include the link-layer header. */ - default_print(sp, h->caplen); + hex_print("\n\t", sp, h->caplen); } else { /* * Don't include the link-layer header - and if @@ -1189,9 +1373,27 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) * print nothing. */ if (h->caplen > hdrlen) - default_print(sp + hdrlen, + hex_print("\n\t", sp + hdrlen, h->caplen - hdrlen); } + } else if (Aflag) { + /* + * Print the raw packet data in ASCII. + */ + if (Aflag > 1) { + /* + * Include the link-layer header. + */ + ascii_print(sp, h->caplen); + } else { + /* + * Don't include the link-layer header - and if + * we have nothing past the link-layer header, + * print nothing. + */ + if (h->caplen > hdrlen) + ascii_print(sp + hdrlen, h->caplen - hdrlen); + } } putchar('\n'); @@ -1229,12 +1431,18 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) #endif /* - * By default, print the specified data out in hex. + * 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) +{ + hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */ +} + void -default_print(register const u_char *bp, register u_int length) +default_print(const u_char *bp, u_int length) { - ascii_print("\n\t", bp, length); /* pass on lf and identation string */ + ndo_default_print(gndo, bp, length); } #ifdef SIGINFO @@ -1252,7 +1460,7 @@ RETSIGTYPE requestinfo(int signo _U_) */ #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_) + DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) { struct pcap_stat stat; @@ -1301,11 +1509,11 @@ usage(void) (void)fprintf(stderr, "Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name); (void)fprintf(stderr, -"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]\n"); +"\t\t[ -E algo:secret ] [ -F file ] [ -G seconds ] [ -i interface ]\n"); (void)fprintf(stderr, -"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ] [ -W filecount ]\n"); +"\t\t[ -M secret ] [ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n"); (void)fprintf(stderr, -"\t\t[ -y datalinktype ] [ -Z user ]\n"); +"\t\t[ -W filecount ] [ -y datalinktype ] [ -Z user ]\n"); (void)fprintf(stderr, "\t\t[ expression ]\n"); exit(1); @@ -1314,7 +1522,7 @@ usage(void) /* VARARGS */ -void +static void ndo_error(netdissect_options *ndo _U_, const char *fmt, ...) { va_list ap; @@ -1333,7 +1541,7 @@ ndo_error(netdissect_options *ndo _U_, const char *fmt, ...) } /* VARARGS */ -void +static void ndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) { va_list ap;