From 06ed001f62397030b40d1662ab68a6dff8432179 Mon Sep 17 00:00:00 2001 From: Apple OSS Distributions <91980991+AppleOSSDistributions@users.noreply.github.com> Date: Thu, 21 Sep 2023 16:13:48 +0000 Subject: [PATCH] tcpdump-133 Imported from tcpdump-133.tar.gz --- tcpdump/netdissect.h | 4 ++ tcpdump/ntp.c | 23 +++------ tcpdump/pktaputil.c | 93 ++++++++++++++++++++----------------- tcpdump/pktmetadatafilter.c | 85 ++++++++++++++++++++++++++------- tcpdump/pktmetadatafilter.h | 1 + tcpdump/print-ahcp.c | 12 ++--- tcpdump/print-arista.c | 17 +++---- tcpdump/print-ntp.c | 2 - tcpdump/print-rx.c | 8 ++-- tcpdump/print-zep.c | 9 ++-- tcpdump/print_pktap.c | 6 +++ tcpdump/smbutil.c | 13 ++---- tcpdump/tcpdump.1 | 23 +++++++++ tcpdump/tcpdump.c | 93 ++++++++++++++++++++++++++----------- tcpdump/tests/TESTonce.sh | 2 +- tcpdump/util-print.c | 36 ++++++++++---- 16 files changed, 277 insertions(+), 150 deletions(-) diff --git a/tcpdump/netdissect.h b/tcpdump/netdissect.h index 72b05f3..1bad51c 100644 --- a/tcpdump/netdissect.h +++ b/tcpdump/netdissect.h @@ -335,6 +335,7 @@ extern void nd_pop_all_packet_info(netdissect_options *); #define PRMD_FLAGS 0x1000 #define PRMD_FLOWID 0x2000 #define PRMD_TRACETAG 0x4000 +#define PRMD_DLT 0x8000 #define PRMD_DEFAULT (PRMD_IF|PRMD_PNAME|PRMD_PID|PRMD_SVC|PRMD_DIR|PRMD_COMMENT|PRMD_FLAGS) #define PRMD_ALL 0xffff #endif /* __APPLE__ */ @@ -431,6 +432,9 @@ extern void ts_print(netdissect_options *, const struct timeval *); extern void signed_relts_print(netdissect_options *, int32_t); extern void unsigned_relts_print(netdissect_options *, uint32_t); +extern const char *nd_format_time(char *buf, size_t bufsize, + const char *format, const struct tm *timeptr); + extern void fn_print_char(netdissect_options *, u_char); extern void fn_print_str(netdissect_options *, const u_char *); extern u_int nd_printztn(netdissect_options *, const u_char *, u_int, const u_char *); diff --git a/tcpdump/ntp.c b/tcpdump/ntp.c index 4d17932..ec8f659 100644 --- a/tcpdump/ntp.c +++ b/tcpdump/ntp.c @@ -48,15 +48,14 @@ p_ntp_time(netdissect_options *ndo, f = (uint32_t)(ff * 1000000000.0); /* treat fraction as parts per billion */ ND_PRINT("%u.%09u", i, f); -#ifdef HAVE_STRFTIME /* * print the UTC time in human-readable format. */ if (i) { int64_t seconds_64bit = (int64_t)i - JAN_1970; time_t seconds; - struct tm *tm; char time_buf[128]; + const char *time_string; seconds = (time_t)seconds_64bit; if (seconds != seconds_64bit) { @@ -64,22 +63,12 @@ p_ntp_time(netdissect_options *ndo, * It doesn't fit into a time_t, so we can't hand it * to gmtime. */ - ND_PRINT(" (unrepresentable)"); + time_string = "[Time is too large to fit into a time_t]"; } else { - tm = gmtime(&seconds); - if (tm == NULL) { - /* - * gmtime() can't handle it. - * (Yes, that might happen with some version of - * Microsoft's C library.) - */ - ND_PRINT(" (unrepresentable)"); - } else { - /* use ISO 8601 (RFC3339) format */ - strftime(time_buf, sizeof (time_buf), "%Y-%m-%dT%H:%M:%SZ", tm); - ND_PRINT(" (%s)", time_buf); - } + /* use ISO 8601 (RFC3339) format */ + time_string = nd_format_time(time_buf, sizeof (time_buf), + "%Y-%m-%dT%H:%M:%SZ", gmtime(&seconds)); } + ND_PRINT(" (%s)", time_string); } -#endif } diff --git a/tcpdump/pktaputil.c b/tcpdump/pktaputil.c index fb7e7b5..47dd9d3 100644 --- a/tcpdump/pktaputil.c +++ b/tcpdump/pktaputil.c @@ -83,7 +83,31 @@ pktap_filter_packet(netdissect_options *ndo, struct pcap_if_info *if_info, pktp_hdr->pth_length > h->caplen) { return (-1); } - + /* + * Filter on packet metadata + */ + if (pkt_meta_data_expression != NULL) { + struct pkt_meta_data pmd = {}; + + pmd.itf = &pktp_hdr->pth_ifname[0]; + pmd.dlt = pktp_hdr->pth_dlt; + pmd.proc = &pktp_hdr->pth_comm[0]; + pmd.eproc = &pktp_hdr->pth_ecomm[0]; + pmd.pid = pktp_hdr->pth_pid; + pmd.epid = pktp_hdr->pth_epid; + pmd.svc = svc2str(pktp_hdr->pth_svc); + pmd.dir = (pktp_hdr->pth_flags & PTH_FLAG_DIR_IN) ? "in" : + (pktp_hdr->pth_flags & PTH_FLAG_DIR_OUT) ? "out" : ""; + pmd.flowid = pktp_hdr->pth_flowid; + + match = evaluate_expression(pkt_meta_data_expression, &pmd); + if (match == 0) { + packets_mtdt_fltr_drop++; + + return 0; + } + } + if (if_info == NULL) { if_info = pcap_find_if_info_by_name(pcap, pktp_hdr->pth_ifname); /* @@ -118,27 +142,6 @@ pktap_filter_packet(netdissect_options *ndo, struct pcap_if_info *if_info, match = pcap_offline_filter(&if_info->if_filter_program, &tmp_hdr, pkt_data); } - /* - * Filter on packet metadata - */ - if (match && pkt_meta_data_expression != NULL) { - struct pkt_meta_data pmd = {}; - - pmd.itf = &pktp_hdr->pth_ifname[0]; - pmd.proc = &pktp_hdr->pth_comm[0]; - pmd.eproc = &pktp_hdr->pth_ecomm[0]; - pmd.pid = pktp_hdr->pth_pid; - pmd.epid = pktp_hdr->pth_epid; - pmd.svc = svc2str(pktp_hdr->pth_svc); - pmd.dir = (pktp_hdr->pth_flags & PTH_FLAG_DIR_IN) ? "in" : - (pktp_hdr->pth_flags & PTH_FLAG_DIR_OUT) ? "out" : ""; - pmd.flowid = pktp_hdr->pth_flowid; - - match = evaluate_expression(pkt_meta_data_expression, &pmd); - if (match == 0) { - packets_mtdt_fltr_drop++; - } - } return (match); } @@ -180,6 +183,31 @@ pktapv2_filter_packet(netdissect_options *ndo, struct pcap_if_info *if_info, if (pktap_v2_hdr->pth_e_comm_offset != 0) e_comm = ((char *) pktap_v2_hdr) + pktap_v2_hdr->pth_e_comm_offset; + /* + * Filter on packet metadata + */ + if (match && pkt_meta_data_expression != NULL) { + struct pkt_meta_data pmd = {}; + + pmd.itf = ifname; + pmd.dlt = pktap_v2_hdr->pth_dlt; + pmd.proc = comm; + pmd.eproc = e_comm; + pmd.pid = pktap_v2_hdr->pth_pid; + pmd.epid = pktap_v2_hdr->pth_e_pid; + pmd.svc = svc2str(pktap_v2_hdr->pth_svc); + pmd.dir = (pktap_v2_hdr->pth_flags & PTH_FLAG_DIR_IN) ? "in" : + (pktap_v2_hdr->pth_flags & PTH_FLAG_DIR_OUT) ? "out" : ""; + pmd.flowid = pktap_v2_hdr->pth_flowid; + + match = evaluate_expression(pkt_meta_data_expression, &pmd); + if (match == 0) { + packets_mtdt_fltr_drop++; + + return 0; + } + } + if (if_info == NULL) { if_info = pcap_find_if_info_by_name(pcap, ifname); /* @@ -214,27 +242,6 @@ pktapv2_filter_packet(netdissect_options *ndo, struct pcap_if_info *if_info, match = pcap_offline_filter(&if_info->if_filter_program, &tmp_hdr, pkt_data); } - /* - * Filter on packet metadata - */ - if (match && pkt_meta_data_expression != NULL) { - struct pkt_meta_data pmd = {}; - - pmd.itf = ifname; - pmd.proc = comm; - pmd.eproc = e_comm; - pmd.pid = pktap_v2_hdr->pth_pid; - pmd.epid = pktap_v2_hdr->pth_e_pid; - pmd.svc = svc2str(pktap_v2_hdr->pth_svc); - pmd.dir = (pktap_v2_hdr->pth_flags & PTH_FLAG_DIR_IN) ? "in" : - (pktap_v2_hdr->pth_flags & PTH_FLAG_DIR_OUT) ? "out" : ""; - pmd.flowid = pktap_v2_hdr->pth_flowid; - - match = evaluate_expression(pkt_meta_data_expression, &pmd); - if (match == 0) { - packets_mtdt_fltr_drop++; - } - } return (match); } diff --git a/tcpdump/pktmetadatafilter.c b/tcpdump/pktmetadatafilter.c index bfdf226..fb270bc 100644 --- a/tcpdump/pktmetadatafilter.c +++ b/tcpdump/pktmetadatafilter.c @@ -59,8 +59,11 @@ #include #include +#include + #include "pktmetadatafilter.h" + #define TOKEN_ID_LIST \ X(TOK_NONE) \ X(TOK_OR) \ @@ -69,6 +72,7 @@ X(TOK_LP) \ X(TOK_RP) \ X(TOK_IF) \ + X(TOK_DLT) \ X(TOK_PROC) \ X(TOK_EPROC) \ X(TOK_PID) \ @@ -100,7 +104,9 @@ struct token tokens[] = { { TOK_NOT, "not", 0 } , { TOK_LP, "(", 0 }, { TOK_RP, ")", 0 }, + { TOK_IF, "if", 0 }, + { TOK_DLT, "dlt", 0 }, { TOK_PROC, "proc", 0 }, { TOK_EPROC, "eproc", 0 }, { TOK_PID, "pid", 0 }, @@ -108,6 +114,7 @@ struct token tokens[] = { { TOK_SVC, "svc", 0 }, { TOK_DIR, "dir", 0 }, { TOK_FLOWID, "flowid", 0 }, + { TOK_EQ, "=", 0 }, { TOK_NEQ, "!=", 0 }, @@ -119,9 +126,29 @@ struct token tokens[] = { { TOK_NONE, NULL, 0 } }; +#define DLT_LIST \ + X(NULL) \ + X(EN10MB) \ + X(PPP) \ + X(RAW) \ + +struct dlt_type_str { + int num; + const char *str; +}; + +struct dlt_type_str dlt_type_strs[] = { +#define X(name, ...) { .num = DLT_##name, .str = #name }, + DLT_LIST +#undef X + { .num = DLT_EN10MB, .str = "ether" }, + { .num = 0, .str = NULL } +}; + struct node { int id; char *str; + size_t prfx_len; // used match begining of label uint32_t num; int op; struct node *left_node; @@ -228,7 +255,7 @@ get_token(const char **ptr) #ifdef DEBUG if (parse_verbose) - printf("%s\n", __func__); + printf("%s %s\n", __func__, *ptr); #endif /* DEBUG */ /* Skip white spaces */ @@ -249,9 +276,9 @@ get_token(const char **ptr) if (strncmp(*ptr, tok->tok_label, tok->tok_len) == 0) { #ifdef DEBUG if (parse_verbose) - printf("tok id: %s label: %s\n", get_token_id_str(tok->tok_id), tok->tok_label); + printf("tok id: %d label: %s len: %lu\n", tok->tok_id, tok->tok_label, tok->tok_len); #endif /* DEBUG */ - + lex_token.tok_id = tok->tok_id; lex_token.tok_label = strdup(tok->tok_label); lex_token.tok_len = tok->tok_len; @@ -260,7 +287,7 @@ get_token(const char **ptr) return; } } - + lex_token.tok_id = TOK_STR; if (strncmp(*ptr, "''", 2) == 0 || strncmp(*ptr, "\"\"", 2) == 0) { @@ -302,14 +329,10 @@ get_token(const char **ptr) } } } - #ifdef DEBUG if (parse_verbose) { - char fmt[50]; - - bzero(fmt, sizeof(fmt)); - snprintf(fmt, sizeof(fmt), "tok id: %%s len: %%lu str: %%.%lus *ptr: %%s\n", len); - printf(fmt, get_token_id_str(lex_token.tok_id) , lex_token.tok_len, lex_token.tok_label, *ptr); + printf("tok id: %d len: %lu label: %s *ptr: %s\n", + lex_token.tok_id , lex_token.tok_len, lex_token.tok_label, *ptr); } #endif /* DEBUG */ return; @@ -322,11 +345,12 @@ parse_term_expression(const char **ptr) #ifdef DEBUG if (parse_verbose) - printf("%s\n", __func__); + printf("%s lex_token.tok_id %d *ptr %s\n", __func__, lex_token.tok_id, *ptr); #endif /* DEBUG */ switch (lex_token.tok_id) { case TOK_IF: + case TOK_DLT: case TOK_PROC: case TOK_EPROC: case TOK_PID: @@ -336,7 +360,7 @@ parse_term_expression(const char **ptr) case TOK_FLOWID: term_node = alloc_node(lex_token.tok_id); get_token(ptr); - + if (lex_token.tok_id == TOK_EQ || lex_token.tok_id == TOK_NEQ) term_node->op = lex_token.tok_id; else { @@ -352,14 +376,30 @@ parse_term_expression(const char **ptr) * TBD * For TOK_SVC and TOK_DIR restrict to meaningful values */ - term_node->str = strdup(lex_token.tok_label); - + if (term_node->id == TOK_IF) { + size_t len = strlen(term_node->str); + + if (len > 0 && (term_node->str[len - 1] < '0' || term_node->str[len - 1] > '9')) { + term_node->prfx_len = len; + } + } + if (term_node->id == TOK_DLT) { + struct dlt_type_str *dts; + + term_node->num = (uint32_t)strtoul(term_node->str, NULL, 0); + + for (dts = dlt_type_strs; dts->str != NULL; dts++) { + if (strcasecmp(term_node->str, dts->str) == 0) { + term_node->num = dts->num; + } + } + fprintf(stderr, "num %d str %s\n", term_node->num, term_node->str); + } if (term_node->id == TOK_PID || term_node->id == TOK_EPID || term_node->id == TOK_FLOWID) { term_node->num = (uint32_t)strtoul(term_node->str, NULL, 0); } break; - default: warnx("cannot parse term at: %s", *ptr); break; @@ -551,7 +591,16 @@ evaluate_expression(node_t *expression, struct pkt_meta_data *p) break; case TOK_IF: - match = !strcmp(p->itf, expression->str); + if (expression->prfx_len == 0) { + match = !strcmp(p->itf, expression->str); + } else { + match = !strncmp(p->itf, expression->str, expression->prfx_len); + } + if (expression->op == TOK_NEQ) + match = !match; + break; + case TOK_DLT: + match = (p->dlt == expression->num); if (expression->op == TOK_NEQ) match = !match; break; @@ -625,6 +674,7 @@ print_expression(node_t *expression) break; case TOK_IF: + case TOK_DLT: case TOK_PROC: case TOK_EPROC: case TOK_PID: @@ -636,6 +686,9 @@ print_expression(node_t *expression) case TOK_IF: printf("if"); break; + case TOK_DLT: + printf("dlt"); + break; case TOK_PID: printf("pid"); break; diff --git a/tcpdump/pktmetadatafilter.h b/tcpdump/pktmetadatafilter.h index 45f8af3..877444a 100644 --- a/tcpdump/pktmetadatafilter.h +++ b/tcpdump/pktmetadatafilter.h @@ -34,6 +34,7 @@ typedef struct node node_t; struct pkt_meta_data { const char *itf; + uint32_t dlt; const char *proc; const char *eproc; pid_t pid; diff --git a/tcpdump/print-ahcp.c b/tcpdump/print-ahcp.c index 9859f76..d57edda 100644 --- a/tcpdump/print-ahcp.c +++ b/tcpdump/print-ahcp.c @@ -102,18 +102,14 @@ ahcp_time_print(netdissect_options *ndo, const u_char *cp, uint8_t len) { time_t t; - struct tm *tm; - char buf[BUFSIZE]; + char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss UTC")]; if (len != 4) goto invalid; t = GET_BE_U_4(cp); - if (NULL == (tm = gmtime(&t))) - ND_PRINT(": gmtime() error"); - else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm)) - ND_PRINT(": strftime() error"); - else - ND_PRINT(": %s UTC", buf); + ND_PRINT(": %s", + nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC", + gmtime(&t))); return; invalid: diff --git a/tcpdump/print-arista.c b/tcpdump/print-arista.c index 0d1d5d9..9efabb7 100644 --- a/tcpdump/print-arista.c +++ b/tcpdump/print-arista.c @@ -32,16 +32,13 @@ arista_print_date_hms_time(netdissect_options *ndo, uint32_t seconds, uint32_t nanoseconds) { time_t ts; - struct tm *tm; - char buf[BUFSIZE]; + char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss")]; ts = seconds + (nanoseconds / 1000000000); - if (NULL == (tm = gmtime(&ts))) - ND_PRINT(": gmtime() error"); - else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm)) - ND_PRINT(": strftime() error"); - else - ND_PRINT(": %s, %09u ns, ", buf, nanoseconds); + nanoseconds %= 1000000000; + ND_PRINT("%s, %09u ns, ", + nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", + gmtime(&ts)), nanoseconds); } int @@ -66,7 +63,7 @@ arista_ethertype_print(netdissect_options *ndo, const u_char *bp, u_int len _U_) // TapAgg Header Timestamping if (subTypeId == ARISTA_SUBTYPE_TIMESTAMP) { // Timestamp has 32-bit lsb in nanosec and remaining msb in sec - ND_PRINT("Timestamp %s", tok2str(ts_version_name, + ND_PRINT("Timestamp %s: ", tok2str(ts_version_name, "Unknown timestamp Version 0x%04x ", version)); switch (version) { case ARISTA_TIMESTAMP_64_TAI: @@ -78,7 +75,7 @@ arista_ethertype_print(netdissect_options *ndo, const u_char *bp, u_int len _U_) break; case ARISTA_TIMESTAMP_48_TAI: case ARISTA_TIMESTAMP_48_UTC: - ND_PRINT(": Seconds %u,", GET_BE_U_2(bp)); + ND_PRINT("Seconds %u,", GET_BE_U_2(bp)); ND_PRINT(" Nanoseconds %u, ", GET_BE_U_4(bp + 2)); bytesConsumed += size + 6; break; diff --git a/tcpdump/print-ntp.c b/tcpdump/print-ntp.c index 99c0896..4b02917 100644 --- a/tcpdump/print-ntp.c +++ b/tcpdump/print-ntp.c @@ -38,9 +38,7 @@ #include "netdissect-stdinc.h" -#ifdef HAVE_STRFTIME #include -#endif #include "netdissect.h" #include "addrtoname.h" diff --git a/tcpdump/print-rx.c b/tcpdump/print-rx.c index b8ee5a8..469cf8f 100644 --- a/tcpdump/print-rx.c +++ b/tcpdump/print-rx.c @@ -794,12 +794,12 @@ rx_cache_find(netdissect_options *ndo, const struct rx_header *rxh, ND_PRINT(" %" PRIu64, _i); \ } -#define DATEOUT() { time_t _t; struct tm *tm; char str[256]; \ +#define DATEOUT() { time_t _t; char str[256]; \ _t = (time_t) GET_BE_S_4(bp); \ bp += sizeof(int32_t); \ - tm = localtime(&_t); \ - strftime(str, 256, "%Y/%m/%d %H:%M:%S", tm); \ - ND_PRINT(" %s", str); \ + ND_PRINT(" %s", \ + nd_format_time(str, sizeof(str), \ + "%Y/%m/%d %H:%M:%S", localtime(&_t))); \ } #define STOREATTROUT() { uint32_t mask, _i; \ diff --git a/tcpdump/print-zep.c b/tcpdump/print-zep.c index e10ecb3..0af18cd 100644 --- a/tcpdump/print-zep.c +++ b/tcpdump/print-zep.c @@ -77,20 +77,17 @@ static void zep_print_ts(netdissect_options *ndo, const u_char *p) billion */ ND_PRINT("%u.%09d", i, f); -#ifdef HAVE_STRFTIME /* * print the time in human-readable format. */ if (i) { time_t seconds = i - JAN_1970; - struct tm *tm; char time_buf[128]; - tm = localtime(&seconds); - strftime(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", tm); - ND_PRINT(" (%s)", time_buf); + ND_PRINT(" (%s)", + nd_format_time(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S", + localtime(&seconds))); } -#endif } /* diff --git a/tcpdump/print_pktap.c b/tcpdump/print_pktap.c index 13dca4a..8865705 100644 --- a/tcpdump/print_pktap.c +++ b/tcpdump/print_pktap.c @@ -261,6 +261,12 @@ print_pktap_header(struct netdissect_options *ndo, struct pktap_header *pktp_hdr prsep = ", "; } #endif /* PKTAP_HAS_TRACE_TAG */ + if (ndo->ndo_kflag & PRMD_DLT) { + ND_PRINT("%s" "dlt 0x%x", + prsep, + pktp_hdr->pth_dlt); + prsep = ", "; + } ND_PRINT(") "); } } diff --git a/tcpdump/smbutil.c b/tcpdump/smbutil.c index ff32ecc..f33a323 100644 --- a/tcpdump/smbutil.c +++ b/tcpdump/smbutil.c @@ -768,8 +768,8 @@ smb_fdata1(netdissect_options *ndo, case 'T': { time_t t; - struct tm *lt; const char *tstring; + char buffer[sizeof("Www Mmm dd hh:mm:ss yyyyy")]; uint32_t x; switch (atoi(fmt + 1)) { @@ -799,14 +799,11 @@ smb_fdata1(netdissect_options *ndo, break; } if (t != 0) { - lt = localtime(&t); - if (lt != NULL) - tstring = asctime(lt); - else - tstring = "(Can't convert time)\n"; + tstring = nd_format_time(buffer, sizeof(buffer), "%a %b %e %T %Y", + localtime(&t)); } else - tstring = "NULL\n"; - ND_PRINT("%s", tstring); + tstring = "NULL"; + ND_PRINT("%s\n", tstring); fmt++; while (ND_ASCII_ISDIGIT(*fmt)) fmt++; diff --git a/tcpdump/tcpdump.1 b/tcpdump/tcpdump.1 index 27ef570..0e4a24c 100644 --- a/tcpdump/tcpdump.1 +++ b/tcpdump/tcpdump.1 @@ -641,6 +641,7 @@ where each character corresponds to a type of packet metadata as follows: \fBF\fP flags \fBU\fP process UUID (not shown by default) \fBV\fP verbose printf of pcap-ng blocks (not shown by default) +\fBd\fP data link type \fBf\fP flow identifier \fBt\fP trace tag \fBA\fP display all types of metadata @@ -2182,6 +2183,7 @@ is to be compared: \fBdir\fP direction \fBeproc\fP effective process name \fBepid\fP effective process ID +\fBdlt\fP data link type .fi .RE .LP @@ -2205,6 +2207,27 @@ Likewise, strings that contain spaces have to be surrounded by quotes. For examp \fB-Q "proc = 'Some App'"\fP .fi .RE +.LP +Interface names can be filtered by partial string if the unit number is ommitted. +For example use the following to include interfaces whose name begins with "en": +.LP +.RS +.nf +\fB-Q "if = en"\fP +.fi +.RE +.LP +The data link type can be specified by number or by one of the following symbolic names: +.LP +.RS +.nf +NULL +EN10MB +PPP +RAW +ether (same as EN10MB) +.fi +.RE .SH "SEE ALSO" .BR stty (1), .BR pcap (3PCAP), diff --git a/tcpdump/tcpdump.c b/tcpdump/tcpdump.c index 88d2c26..0e922ed 100644 --- a/tcpdump/tcpdump.c +++ b/tcpdump/tcpdump.c @@ -726,7 +726,11 @@ show_remote_devices_and_exit(void) #ifdef HAVE_PCAP_SETDIRECTION #define Q_FLAG "Q:" +#ifdef __APPLE__ +#define Q_FLAG_USAGE " [ -Q in|out|inout|out|packet-metadata-filter ]" +#else /* __APPLE__ */ #define Q_FLAG_USAGE " [ -Q in|out|inout ]" +#endif /* __APPLE__ */ #else #define Q_FLAG #define Q_FLAG_USAGE @@ -933,6 +937,8 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) char *filename = malloc(PATH_MAX + 1); if (filename == NULL) error("%s: malloc", __func__); + if (strlen(orig_name) == 0) + error("an empty string is not a valid file name"); /* Process with strftime if Gflag is set. */ if (Gflag != 0) { @@ -944,9 +950,25 @@ 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. + * value of 0 isn't necessarily failure; if orig_name is an empty + * string, the formatted string will be empty. + * + * However, the C90 standard says that, if there *is* a + * buffer overflow, the content of the buffer is undefined, + * so we must check for a buffer overflow. + * + * So we check above for an empty orig_name, and only call + * strftime() if it's non-empty, in which case the return + * value will only be 0 if the formatted date doesn't fit + * in the buffer. + * + * (We check above because, even if we don't use -G, we + * want a better error message than "tcpdump: : No such + * file or directory" for this case.) */ - strftime(filename, PATH_MAX, orig_name, local_tm); + if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) { + error("%s: strftime", __func__); + } } else { strncpy(filename, orig_name, PATH_MAX); } @@ -1899,6 +1921,9 @@ main(int argc, char **argv) case 't': val |= PRMD_TRACETAG; break; + case 'd': + val |= PRMD_DLT; + break; default: /* * This is most likely parsing a filter expression @@ -1972,26 +1997,30 @@ main(int argc, char **argv) ++ndo->ndo_suppress_default_print; break; -#ifdef __APPLE__ - case 'Q': - pkt_meta_data_expression = parse_expression(optarg); - if (pkt_meta_data_expression == NULL) - error("invalid expression \"%s\"", optarg); - break; -#else /* __APPLE__ */ #ifdef HAVE_PCAP_SETDIRECTION case 'Q': if (ascii_strcasecmp(optarg, "in") == 0) Qflag = PCAP_D_IN; else if (ascii_strcasecmp(optarg, "out") == 0) Qflag = PCAP_D_OUT; - else if (ascii_strcasecmp(optarg, "inout") == 0) - Qflag = PCAP_D_INOUT; - else + else if (ascii_strcasecmp(optarg, "inout") == 0) + Qflag = PCAP_D_INOUT; +#ifdef __APPLE__ +#ifdef PCAP_D_NONE + else if (ascii_strcasecmp(optarg, "none") == 0) + Qflag = PCAP_D_NONE; +#endif /* PCAP_D_NONE */ + else { + pkt_meta_data_expression = parse_expression(optarg); + if (pkt_meta_data_expression == NULL) + error("invalid expression \"%s\"", optarg); + } +#else /* __APPLE__ */ + else error("unknown capture direction `%s'", optarg); +#endif /* __APPLE__ */ break; #endif /* HAVE_PCAP_SETDIRECTION */ -#endif /* __APPLE__ */ case 'r': RFileName = optarg; break; @@ -4182,13 +4211,6 @@ handle_pcap_ng_dump(struct dump_info *dump_info, const struct pcap_pkthdr *h, goto done; } - /* - * Evaluate the per-interface BPF filter expression - */ - if (if_info->if_filter_program.bf_insns != NULL && - pcap_offline_filter(&if_info->if_filter_program, h, pkt_data) == 0) - goto done; - if (pcap_ng_block_get_option(block, pack_flags_code, &option_info) == 1) { if (option_info.length != 4) { warning("%s: pack_flags option length %u != 4", __func__, option_info.length); @@ -4207,6 +4229,7 @@ handle_pcap_ng_dump(struct dump_info *dump_info, const struct pcap_pkthdr *h, struct pkt_meta_data pmd; pmd.itf = &if_info->if_name[0]; + pmd.dlt = if_info->if_linktype; pmd.proc = (proc_info != NULL) ? proc_info->proc_name : ""; pmd.eproc = (e_proc_info != NULL) ? e_proc_info->proc_name : ""; pmd.pid = (proc_info != NULL) ? proc_info->proc_pid : -1; @@ -4221,6 +4244,14 @@ handle_pcap_ng_dump(struct dump_info *dump_info, const struct pcap_pkthdr *h, } } + /* + * Evaluate the per-interface BPF filter expression + */ + if (if_info->if_filter_program.bf_insns != NULL && + pcap_offline_filter(&if_info->if_filter_program, h, pkt_data) == 0) { + goto done; + } + /* * Skip until minimum packet count */ @@ -4688,13 +4719,6 @@ print_pcap_ng_block(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) goto done; } - /* - * Evaluate the per-interface BPF filter expression - */ - if (if_info->if_filter_program.bf_insns != NULL && - pcap_offline_filter(&if_info->if_filter_program, h, pkt_data) == 0) - goto done; - if (pcap_ng_block_get_option(block, pack_flags_code, &option_info) == 1) { if (option_info.length != 4) { warning("%s: pack_flags option length %u != 4", __func__, option_info.length); @@ -4713,6 +4737,7 @@ print_pcap_ng_block(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) struct pkt_meta_data pmd; pmd.itf = &if_info->if_name[0]; + pmd.dlt = if_info->if_linktype; pmd.proc = (proc_info != NULL) ? proc_info->proc_name : ""; pmd.eproc = (e_proc_info != NULL) ? e_proc_info->proc_name : ""; pmd.pid = (proc_info != NULL) ? proc_info->proc_pid : -1; @@ -4728,6 +4753,14 @@ print_pcap_ng_block(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) } } + /* + * Evaluate the per-interface BPF filter expression + */ + if (if_info->if_filter_program.bf_insns != NULL && + pcap_offline_filter(&if_info->if_filter_program, h, pkt_data) == 0) { + goto done; + } + ++packets_captured; if (packets_captured <= skip_packet_cnt) @@ -4845,6 +4878,12 @@ print_pcap_ng_block(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) prsep = ", "; } #endif /* PCAPNG_EPB_TRACE_TAG */ + if (ndo->ndo_kflag & PRMD_DLT) { + ND_PRINT("%s" "dlt 0x%x", + prsep, + if_info->if_linktype); + prsep = ", "; + } /* * Comment diff --git a/tcpdump/tests/TESTonce.sh b/tcpdump/tests/TESTonce.sh index 40edd6d..04f2227 100755 --- a/tcpdump/tests/TESTonce.sh +++ b/tcpdump/tests/TESTonce.sh @@ -17,7 +17,7 @@ input="$2" output="$3" options="$4" -echo "$" "${TCPDUMP_BIN}" "--apple-arp-plain -# -n -r $input $options" >>verbose-outputs.txt +echo "$" "${TCPDUMP_BIN}" "--apple-ext-fmt 0 -# -n -r $input $options" >>verbose-outputs.txt #use eval otherwise $option may contain double quotes '"' eval ${TCPDUMP_BIN} 2>>verbose-outputs.txt --apple-ext-fmt 0 -\# -n -r $input $options >NEW/$output diff --git a/tcpdump/util-print.c b/tcpdump/util-print.c index c32161c..ef4e21e 100644 --- a/tcpdump/util-print.c +++ b/tcpdump/util-print.c @@ -230,7 +230,8 @@ ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec, { time_t Time = sec; struct tm *tm; - char timestr[32]; + char timebuf[32]; + const char *timestr; if ((unsigned)sec & 0x80000000) { ND_PRINT("[Error converting time]"); @@ -242,14 +243,13 @@ ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec, else tm = gmtime(&Time); - if (!tm) { - ND_PRINT("[Error converting time]"); - return; + if (date_flag == WITH_DATE) { + timestr = nd_format_time(timebuf, sizeof(timebuf), + "%Y-%m-%d %H:%M:%S", tm); + } else { + timestr = nd_format_time(timebuf, sizeof(timebuf), + "%H:%M:%S", tm); } - if (date_flag == WITH_DATE) - strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm); - else - strftime(timestr, sizeof(timestr), "%H:%M:%S", tm); ND_PRINT("%s", timestr); ts_frac_print(ndo, usec); @@ -500,6 +500,26 @@ signed_relts_print(netdissect_options *ndo, unsigned_relts_print(ndo, secs); } +/* + * Format a struct tm with strftime(). + * If the pointer to the struct tm is null, that means that the + * routine to convert a time_t to a struct tm failed; the localtime() + * and gmtime() in the Microsoft Visual Studio C library will fail, + * returning null, if the value is before the UNIX Epoch. + */ +const char * +nd_format_time(char *buf, size_t bufsize, const char *format, + const struct tm *timeptr) +{ + if (timeptr != NULL) { + if (strftime(buf, bufsize, format, timeptr) != 0) + return (buf); + else + return ("[nd_format_time() buffer is too small]"); + } else + return ("[localtime() or gmtime() couldn't convert the date and time]"); +} + /* Print the truncated string */ void nd_print_trunc(netdissect_options *ndo) {