From: Guy Harris Date: Fri, 3 Jul 2015 22:54:14 +0000 (-0700) Subject: CVE-2016-7985,7986/Change the way protocols print link-layer addresses. X-Git-Tag: tcpdump-4.9.0-bp~96 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/6bc44295cfbe1f7b6633c755841518f4b159aa8a CVE-2016-7985,7986/Change the way protocols print link-layer addresses. If a protocol that runs under a link-layer protocol would print the link-layer addresses for the packet as source and destination addresses for the packet, don't have it blithely assume those link-layer addresses are present or are at a particular offset from the beginning of that protocol's data; Ethertypes, for example, are used by a number of protocols, not all of which have Ethernet headers and not all of which have any MAC headers. Instead, pass the printers for those protocols structures with a pointer to the address data and a pointer to a routine that prints the address. Fixes some heap overflows found with American Fuzzy Lop by Hanno Böck. --- diff --git a/netdissect.h b/netdissect.h index 902bf1b2..a855e87a 100644 --- a/netdissect.h +++ b/netdissect.h @@ -449,6 +449,21 @@ extern u_int token_if_print IF_PRINTER_ARGS; extern u_int usb_linux_48_byte_print IF_PRINTER_ARGS; extern u_int usb_linux_64_byte_print IF_PRINTER_ARGS; +/* + * Structure passed to some printers to allow them to print + * link-layer address information if ndo_eflag isn't set + * (because they are for protocols that don't have their + * own addresses, so that we'd want to report link-layer + * address information). + * + * This contains a pointer to an address and a pointer to a routine + * to which we pass that pointer in order to get a string. + */ +struct lladdr_info { + const char *(*addr_string)(netdissect_options *, const u_char *); + const u_char *addr; +}; + /* The printer routines. */ extern void aarp_print(netdissect_options *, const u_char *, u_int); @@ -466,7 +481,7 @@ extern void bfd_print(netdissect_options *, const u_char *, u_int, u_int); extern void bgp_print(netdissect_options *, const u_char *, int); extern char *bgp_vpn_rd_print (netdissect_options *, const u_char *); extern void bootp_print(netdissect_options *, const u_char *, u_int); -extern void calm_fast_print(netdissect_options *, const u_char *, const u_char *, u_int); +extern void calm_fast_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *); extern void carp_print(netdissect_options *, const u_char *, u_int, int); extern void cdp_print(netdissect_options *, const u_char *, u_int, u_int); extern void cfm_print(netdissect_options *, const u_char *, u_int); @@ -484,14 +499,14 @@ extern void egp_print(netdissect_options *, const u_char *, u_int); extern void eigrp_print(netdissect_options *, const u_char *, u_int); extern int esp_print(netdissect_options *, const u_char *, const int, const u_char *, int *, int *); extern u_int ether_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), const u_char *); -extern int ethertype_print(netdissect_options *, u_short, const u_char *, u_int, u_int); +extern int ethertype_print(netdissect_options *, u_short, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *); extern u_int fddi_print(netdissect_options *, const u_char *, u_int, u_int); extern void forces_print(netdissect_options *, const u_char *, u_int); extern u_int fr_print(netdissect_options *, register const u_char *, u_int); extern int frag6_print(netdissect_options *, const u_char *, const u_char *); extern void ftp_print(netdissect_options *, const u_char *, u_int); extern void geneve_print(netdissect_options *, const u_char *, u_int); -extern void geonet_print(netdissect_options *, const u_char *, const u_char *, u_int); +extern void geonet_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *); extern void gre_print(netdissect_options *, const u_char *, u_int); extern int hbhopt_print(netdissect_options *, const u_char *); extern void hex_and_ascii_print(netdissect_options *, const char *, const u_char *, u_int); @@ -521,7 +536,7 @@ extern void lane_print(netdissect_options *, const u_char *, u_int, u_int); extern void ldp_print(netdissect_options *, const u_char *, u_int); extern void lisp_print(netdissect_options *, const u_char *, u_int); extern u_int llap_print(netdissect_options *, const u_char *, u_int); -extern int llc_print(netdissect_options *, const u_char *, u_int, u_int, const u_char *, const u_char *); +extern int llc_print(netdissect_options *, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *); extern void lldp_print(netdissect_options *, const u_char *, u_int); extern void lmp_print(netdissect_options *, const u_char *, u_int); extern void loopback_print(netdissect_options *, const u_char *, const u_int); @@ -572,7 +587,7 @@ extern void resp_print(netdissect_options *, const u_char *, u_int); extern void rip_print(netdissect_options *, const u_char *, u_int); extern void ripng_print(netdissect_options *, const u_char *, unsigned int); extern void rpki_rtr_print(netdissect_options *, const u_char *, u_int); -extern void rrcp_print(netdissect_options *, const u_char *, u_int); +extern void rrcp_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *, const struct lladdr_info *); extern void rsvp_print(netdissect_options *, const u_char *, u_int); extern int rt6_print(netdissect_options *, const u_char *, const u_char *); extern void rtsp_print(netdissect_options *, const u_char *, u_int); @@ -584,7 +599,7 @@ extern void slow_print(netdissect_options *, const u_char *, u_int); extern void smb_print_data(netdissect_options *, const unsigned char *, int); extern void smb_tcp_print(netdissect_options *, const u_char *, int); extern void smtp_print(netdissect_options *, const u_char *, u_int); -extern int snap_print(netdissect_options *, const u_char *, u_int, u_int, const u_char *, const u_char *, u_int); +extern int snap_print(netdissect_options *, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *, u_int); extern void snmp_print(netdissect_options *, const u_char *, u_int); extern void stp_print(netdissect_options *, const u_char *, u_int); extern void sunrpcrequest_print(netdissect_options *, const u_char *, u_int, const u_char *); diff --git a/print-802_11.c b/print-802_11.c index 7721524b..78a57b18 100644 --- a/print-802_11.c +++ b/print-802_11.c @@ -2039,7 +2039,7 @@ ieee802_11_print(netdissect_options *ndo, { uint16_t fc; u_int caplen, hdrlen, meshdrlen; - const uint8_t *src, *dst; + struct lladdr_info src, dst; int llc_hdrlen; caplen = orig_caplen; @@ -2091,10 +2091,12 @@ ieee802_11_print(netdissect_options *ndo, caplen -= hdrlen; p += hdrlen; + src.addr_string = etheraddr_string; + dst.addr_string = etheraddr_string; switch (FC_TYPE(fc)) { case T_MGMT: - get_mgmt_src_dst_mac(p - hdrlen, &src, &dst); - if (!mgmt_body_print(ndo, fc, src, p, length)) { + get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr); + if (!mgmt_body_print(ndo, fc, src.addr, p, length)) { ND_PRINT((ndo, "%s", tstr)); return hdrlen; } @@ -2116,8 +2118,8 @@ ieee802_11_print(netdissect_options *ndo, return hdrlen; } } else { - get_data_src_dst_mac(fc, p - hdrlen, &src, &dst); - llc_hdrlen = llc_print(ndo, p, length, caplen, src, dst); + get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr); + llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); if (llc_hdrlen < 0) { /* * Some kinds of LLC packet we cannot diff --git a/print-ap1394.c b/print-ap1394.c index 1e6bbd98..79401cba 100644 --- a/print-ap1394.c +++ b/print-ap1394.c @@ -49,6 +49,12 @@ struct firewire_header { */ #define FIREWIRE_HDRLEN 18 +static const char * +fwaddr_string(netdissect_options *ndo, const u_char *addr) +{ + return (linkaddr_string(ndo, addr, LINKADDR_IEEE1394, FIREWIRE_EUI64_LEN)); +} + static inline void ap1394_hdr_print(netdissect_options *ndo, register const u_char *bp, u_int length) { @@ -58,8 +64,8 @@ ap1394_hdr_print(netdissect_options *ndo, register const u_char *bp, u_int lengt fp = (const struct firewire_header *)bp; ND_PRINT((ndo, "%s > %s", - linkaddr_string(ndo, fp->firewire_shost, LINKADDR_IEEE1394, FIREWIRE_EUI64_LEN), - linkaddr_string(ndo, fp->firewire_dhost, LINKADDR_IEEE1394, FIREWIRE_EUI64_LEN))); + fwaddr_string(ndo, fp->firewire_shost), + fwaddr_string(ndo, fp->firewire_dhost))); firewire_type = EXTRACT_16BITS(&fp->firewire_type); if (!ndo->ndo_qflag) { @@ -86,6 +92,7 @@ ap1394_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_ch u_int caplen = h->caplen; const struct firewire_header *fp; u_short ether_type; + struct lladdr_info src, dst; if (caplen < FIREWIRE_HDRLEN) { ND_PRINT((ndo, "[|ap1394]")); @@ -101,7 +108,11 @@ ap1394_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_ch p += FIREWIRE_HDRLEN; ether_type = EXTRACT_16BITS(&fp->firewire_type); - if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { + src.addr = fp->firewire_shost; + src.addr_string = fwaddr_string; + dst.addr = fp->firewire_dhost; + dst.addr_string = fwaddr_string; + if (ethertype_print(ndo, ether_type, p, length, caplen, &src, &dst) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) ap1394_hdr_print(ndo, (const u_char *)fp, length + FIREWIRE_HDRLEN); diff --git a/print-calm-fast.c b/print-calm-fast.c index 4e4e51af..c9be008c 100644 --- a/print-calm-fast.c +++ b/print-calm-fast.c @@ -37,19 +37,33 @@ * to the calm header of the packet. */ void -calm_fast_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int length) +calm_fast_print(netdissect_options *ndo, const u_char *bp, u_int length, const struct lladdr_info *src) { - int srcNwref = bp[0]; - int dstNwref = bp[1]; + int srcNwref; + int dstNwref; + + ND_TCHECK2(*bp, 2); + if (length < 2) + goto trunc; + srcNwref = bp[0]; + dstNwref = bp[1]; length -= 2; bp += 2; - ND_PRINT((ndo, "CALM FAST src:%s; ", etheraddr_string(ndo, eth+6))); + ND_PRINT((ndo, "CALM FAST")); + if (src != NULL) + ND_PRINT((ndo, " src:%s", (src->addr_string)(ndo, src->addr))); + ND_PRINT((ndo, "; ")); ND_PRINT((ndo, "SrcNwref:%d; ", srcNwref)); ND_PRINT((ndo, "DstNwref:%d; ", dstNwref)); if (ndo->ndo_vflag) ND_DEFAULTPRINT(bp, length); + return; + +trunc: + ND_PRINT((ndo, "[|calm fast]")); + return; } diff --git a/print-ether.c b/print-ether.c index 0f8c7dc5..59d15c24 100644 --- a/print-ether.c +++ b/print-ether.c @@ -137,6 +137,7 @@ ether_print(netdissect_options *ndo, u_short length_type; u_int hdrlen; int llc_hdrlen; + struct lladdr_info src, dst; if (caplen < ETHER_HDRLEN) { ND_PRINT((ndo, "[|ether]")); @@ -160,6 +161,10 @@ ether_print(netdissect_options *ndo, p += ETHER_HDRLEN; hdrlen = ETHER_HDRLEN; + src.addr = ESRC(ep); + src.addr_string = etheraddr_string; + dst.addr = EDST(ep); + dst.addr_string = etheraddr_string; length_type = EXTRACT_16BITS(&ep->ether_length_type); recurse: @@ -168,7 +173,7 @@ recurse: */ if (length_type <= ETHERMTU) { /* Try to print the LLC-layer header & higher layers */ - llc_hdrlen = llc_print(ndo, p, length, caplen, ESRC(ep), EDST(ep)); + llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); if (llc_hdrlen < 0) { /* packet type not known, print raw packet */ if (!ndo->ndo_suppress_default_print) @@ -217,7 +222,7 @@ recurse: * there's an LLC header and payload. */ /* Try to print the LLC-layer header & higher layers */ - llc_hdrlen = llc_print(ndo, p, length, caplen, ESRC(ep), EDST(ep)); + llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); if (llc_hdrlen < 0) { /* packet type not known, print raw packet */ if (!ndo->ndo_suppress_default_print) @@ -226,7 +231,7 @@ recurse: } hdrlen += llc_hdrlen; } else { - if (ethertype_print(ndo, length_type, p, length, caplen) == 0) { + if (ethertype_print(ndo, length_type, p, length, caplen, &src, &dst) == 0) { /* type not known, print raw packet */ if (!ndo->ndo_eflag) { if (print_encap_header != NULL) @@ -317,7 +322,8 @@ netanalyzer_transparent_if_print(netdissect_options *ndo, int ethertype_print(netdissect_options *ndo, u_short ether_type, const u_char *p, - u_int length, u_int caplen) + u_int length, u_int caplen, + const struct lladdr_info *src, const struct lladdr_info *dst) { switch (ether_type) { @@ -369,7 +375,7 @@ ethertype_print(netdissect_options *ndo, return (1); case ETHERTYPE_RRCP: - rrcp_print(ndo, p - 14 , length + 14); + rrcp_print(ndo, p, length, src, dst); return (1); case ETHERTYPE_PPP: @@ -415,11 +421,11 @@ ethertype_print(netdissect_options *ndo, case ETHERTYPE_GEONET_OLD: case ETHERTYPE_GEONET: - geonet_print(ndo, p-14, p, length); + geonet_print(ndo, p, length, src); return (1); case ETHERTYPE_CALM_FAST: - calm_fast_print(ndo, p-14, p, length); + calm_fast_print(ndo, p, length, src); return (1); case ETHERTYPE_AOE: diff --git a/print-fddi.c b/print-fddi.c index 93f6ccd8..27803783 100644 --- a/print-fddi.c +++ b/print-fddi.c @@ -278,6 +278,7 @@ fddi_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) { const struct fddi_header *fddip = (const struct fddi_header *)p; struct ether_header ehdr; + struct lladdr_info src, dst; int llc_hdrlen; if (caplen < FDDI_HDRLEN) { @@ -293,6 +294,11 @@ fddi_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) if (ndo->ndo_eflag) fddi_hdr_print(ndo, fddip, length, ESRC(&ehdr), EDST(&ehdr)); + src.addr = ESRC(&ehdr); + src.addr_string = etheraddr_string; + dst.addr = EDST(&ehdr); + dst.addr_string = etheraddr_string; + /* Skip over FDDI MAC header */ length -= FDDI_HDRLEN; p += FDDI_HDRLEN; @@ -301,7 +307,7 @@ fddi_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) /* Frame Control field determines interpretation of packet */ if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) { /* Try to print the LLC-layer header & higher layers */ - llc_hdrlen = llc_print(ndo, p, length, caplen, ESRC(&ehdr), EDST(&ehdr)); + llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); if (llc_hdrlen < 0) { /* * Some kinds of LLC packet we cannot diff --git a/print-fr.c b/print-fr.c index 3ee46551..9c97bcb4 100644 --- a/print-fr.c +++ b/print-fr.c @@ -276,7 +276,8 @@ fr_print(netdissect_options *ndo, if (ethertype_print(ndo, extracted_ethertype, p+addr_len+ETHERTYPE_LEN, length-addr_len-ETHERTYPE_LEN, - length-addr_len-ETHERTYPE_LEN) == 0) + length-addr_len-ETHERTYPE_LEN, + NULL, NULL) == 0) /* ether_type not known, probably it wasn't one */ ND_PRINT((ndo, "UI %02x! ", p[addr_len])); else diff --git a/print-geneve.c b/print-geneve.c index d565103d..f0319636 100644 --- a/print-geneve.c +++ b/print-geneve.c @@ -223,7 +223,7 @@ geneve_print(netdissect_options *ndo, const u_char *bp, u_int len) else ND_PRINT((ndo, "\n\t")); - if (ethertype_print(ndo, prot, bp, len, len) == 0) { + if (ethertype_print(ndo, prot, bp, len, len, NULL, NULL) == 0) { if (prot == ETHERTYPE_TEB) ether_print(ndo, bp, len, len, NULL, NULL); else diff --git a/print-geonet.c b/print-geonet.c index 61441a0b..9da89bfe 100644 --- a/print-geonet.c +++ b/print-geonet.c @@ -86,6 +86,8 @@ print_long_pos_vector(netdissect_options *ndo, { uint32_t lat, lon; + if (!ND_TTEST2(*bp, GEONET_ADDR_LEN)) + return (-1); ND_PRINT((ndo, "GN_ADDR:%s ", linkaddr_string (ndo, bp, 0, GEONET_ADDR_LEN))); if (!ND_TTEST2(*(bp+12), 8)) @@ -103,7 +105,8 @@ print_long_pos_vector(netdissect_options *ndo, * to the geonet header of the packet. */ void -geonet_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int length) +geonet_print(netdissect_options *ndo, const u_char *bp, u_int length, + const struct lladdr_info *src) { int version; int next_hdr; @@ -115,13 +118,16 @@ geonet_print(netdissect_options *ndo, const u_char *eth, const u_char *bp, u_int const char *hdr_type_txt = "Unknown"; int hdr_size = -1; - ND_PRINT((ndo, "GeoNet src:%s; ", etheraddr_string(ndo, eth+6))); + ND_PRINT((ndo, "GeoNet ")); + if (src != NULL) + ND_PRINT((ndo, "src:%s", (src->addr_string)(ndo, src->addr))); + ND_PRINT((ndo, "; ")); /* Process Common Header */ if (length < 36) goto invalid; - ND_TCHECK2(*bp, 7); + ND_TCHECK2(*bp, 8); version = bp[0] >> 4; next_hdr = bp[0] & 0x0f; hdr_type = bp[1] >> 4; diff --git a/print-ipfc.c b/print-ipfc.c index fc204652..b8a08e96 100644 --- a/print-ipfc.c +++ b/print-ipfc.c @@ -93,6 +93,7 @@ ipfc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) { const struct ipfc_header *ipfcp = (const struct ipfc_header *)p; struct ether_header ehdr; + struct lladdr_info src, dst; int llc_hdrlen; if (caplen < IPFC_HDRLEN) { @@ -107,13 +108,18 @@ ipfc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) if (ndo->ndo_eflag) ipfc_hdr_print(ndo, ipfcp, length, ESRC(&ehdr), EDST(&ehdr)); + src.addr = ESRC(&ehdr); + src.addr_string = etheraddr_string; + dst.addr = EDST(&ehdr); + dst.addr_string = etheraddr_string; + /* Skip over Network_Header */ length -= IPFC_HDRLEN; p += IPFC_HDRLEN; caplen -= IPFC_HDRLEN; /* Try to print the LLC-layer header & higher layers */ - llc_hdrlen = llc_print(ndo, p, length, caplen, ESRC(&ehdr), EDST(&ehdr)); + llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); if (llc_hdrlen < 0) { /* * Some kinds of LLC packet we cannot diff --git a/print-juniper.c b/print-juniper.c index 2fc5bea6..4fb5453c 100644 --- a/print-juniper.c +++ b/print-juniper.c @@ -746,7 +746,8 @@ juniper_pppoe_atm_print(netdissect_options *ndo, if (ethertype_print(ndo, extracted_ethertype, p+ETHERTYPE_LEN, l2info.length-ETHERTYPE_LEN, - l2info.caplen-ETHERTYPE_LEN) == 0) + l2info.caplen-ETHERTYPE_LEN, + NULL, NULL) == 0) /* ether_type not known, probably it wasn't one */ ND_PRINT((ndo, "unknown ethertype 0x%04x", extracted_ethertype)); diff --git a/print-llc.c b/print-llc.c index 99d74c11..bca9b502 100644 --- a/print-llc.c +++ b/print-llc.c @@ -148,7 +148,7 @@ static const struct oui_tok oui_to_tok[] = { */ int llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, - const u_char *esrc, const u_char *edst) + const struct lladdr_info *src, const struct lladdr_info *dst) { uint8_t dsap_field, dsap, ssap_field, ssap; uint16_t control; @@ -262,7 +262,7 @@ llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, * Does anybody ever bridge one form of LAN traffic * over a networking type that uses 802.2 LLC? */ - if (!snap_print(ndo, p, length, caplen, esrc, edst, 2)) { + if (!snap_print(ndo, p, length, caplen, src, dst, 2)) { /* * Unknown packet type; tell our caller, by * returning a negative value, so they @@ -330,23 +330,23 @@ llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, if (!ndo->ndo_eflag) { if (ssap == dsap) { - if (esrc == NULL || edst == NULL) + if (src == NULL || dst == NULL) ND_PRINT((ndo, "%s ", tok2str(llc_values, "Unknown DSAP 0x%02x", dsap))); else ND_PRINT((ndo, "%s > %s %s ", - etheraddr_string(ndo, esrc), - etheraddr_string(ndo, edst), + (src->addr_string)(ndo, src->addr), + (dst->addr_string)(ndo, dst->addr), tok2str(llc_values, "Unknown DSAP 0x%02x", dsap))); } else { - if (esrc == NULL || edst == NULL) + if (src == NULL || dst == NULL) ND_PRINT((ndo, "%s > %s ", tok2str(llc_values, "Unknown SSAP 0x%02x", ssap), tok2str(llc_values, "Unknown DSAP 0x%02x", dsap))); else ND_PRINT((ndo, "%s %s > %s %s ", - etheraddr_string(ndo, esrc), + (src->addr_string)(ndo, src->addr), tok2str(llc_values, "Unknown SSAP 0x%02x", ssap), - etheraddr_string(ndo, edst), + (dst->addr_string)(ndo, dst->addr), tok2str(llc_values, "Unknown DSAP 0x%02x", dsap))); } } @@ -399,7 +399,8 @@ oui_to_struct_tok(uint32_t orgcode) int snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, - const u_char *esrc, const u_char *edst, u_int bridge_pad) + const struct lladdr_info *src, const struct lladdr_info *dst, + u_int bridge_pad) { uint32_t orgcode; register u_short et; @@ -437,7 +438,7 @@ snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, * Cisco hardware; the protocol ID is * an Ethernet protocol type. */ - ret = ethertype_print(ndo, et, p, length, caplen); + ret = ethertype_print(ndo, et, p, length, caplen, src, dst); if (ret) return (ret); break; @@ -452,7 +453,7 @@ snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, * but used 0x000000 and an Ethernet * packet type for AARP packets. */ - ret = ethertype_print(ndo, et, p, length, caplen); + ret = ethertype_print(ndo, et, p, length, caplen, src, dst); if (ret) return (ret); } @@ -553,13 +554,13 @@ snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, } if (!ndo->ndo_eflag) { /* - * Nobody printed the MAC addresses, so print them, if + * Nobody printed the link-layer addresses, so print them, if * we have any. */ - if (esrc != NULL && edst != NULL) { + if (src != NULL && dst != NULL) { ND_PRINT((ndo, "%s > %s ", - etheraddr_string(ndo, esrc), - etheraddr_string(ndo, edst))); + (src->addr_string)(ndo, src->addr), + (dst->addr_string)(ndo, dst->addr))); } /* * Print the SNAP header, but if the OUI is 000000, don't diff --git a/print-medsa.c b/print-medsa.c index 1266c9c8..005416f0 100644 --- a/print-medsa.c +++ b/print-medsa.c @@ -30,6 +30,7 @@ #include "netdissect.h" #include "ether.h" #include "ethertype.h" +#include "addrtoname.h" #include "extract.h" static const char tstr[] = "[|MEDSA]"; @@ -141,6 +142,7 @@ medsa_print(netdissect_options *ndo, { register const struct ether_header *ep; const struct medsa_pkthdr *medsa; + struct lladdr_info src, dst; u_short ether_type; medsa = (const struct medsa_pkthdr *)bp; @@ -157,10 +159,14 @@ medsa_print(netdissect_options *ndo, length -= 8; caplen -= 8; + src.addr = ESRC(ep); + src.addr_string = etheraddr_string; + dst.addr = EDST(ep); + dst.addr_string = etheraddr_string; ether_type = EXTRACT_16BITS(&medsa->ether_type); if (ether_type <= ETHERMTU) { /* Try to print the LLC-layer header & higher layers */ - if (llc_print(ndo, bp, length, caplen, ESRC(ep), EDST(ep)) < 0) { + if (llc_print(ndo, bp, length, caplen, &src, &dst) < 0) { /* packet type not known, print raw packet */ if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(bp, caplen); @@ -172,7 +178,7 @@ medsa_print(netdissect_options *ndo, ether_type), ether_type)); - if (ethertype_print(ndo, ether_type, bp, length, caplen) == 0) { + if (ethertype_print(ndo, ether_type, bp, length, caplen, &src, &dst) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) ND_PRINT((ndo, "ethertype %s (0x%04x) ", diff --git a/print-rrcp.c b/print-rrcp.c index ee3a858d..936b3ea7 100644 --- a/print-rrcp.c +++ b/print-rrcp.c @@ -73,54 +73,54 @@ static const struct tok opcode_values[] = { void rrcp_print(netdissect_options *ndo, register const u_char *cp, - u_int length _U_) + u_int length _U_, + const struct lladdr_info *src, + const struct lladdr_info *dst) { - const u_char *rrcp; uint8_t rrcp_proto; uint8_t rrcp_opcode; - register const struct ether_header *ep; - ep = (const struct ether_header *)cp; - rrcp = cp + ETHER_HDRLEN; - - ND_TCHECK(*(rrcp + RRCP_PROTO_OFFSET)); - rrcp_proto = *(rrcp + RRCP_PROTO_OFFSET); - ND_TCHECK(*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)); - rrcp_opcode = (*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK; - ND_PRINT((ndo, "%s > %s, %s %s", - etheraddr_string(ndo, ESRC(ep)), - etheraddr_string(ndo, EDST(ep)), + ND_TCHECK(*(cp + RRCP_PROTO_OFFSET)); + rrcp_proto = *(cp + RRCP_PROTO_OFFSET); + ND_TCHECK(*(cp + RRCP_OPCODE_ISREPLY_OFFSET)); + rrcp_opcode = (*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK; + if (src != NULL && dst != NULL) { + ND_PRINT((ndo, "%s > %s, ", + (src->addr_string)(ndo, src->addr), + (dst->addr_string)(ndo, dst->addr))); + } + ND_PRINT((ndo, "%s %s", tok2str(proto_values,"RRCP-0x%02x",rrcp_proto), - ((*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query")); + ((*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query")); if (rrcp_proto==1){ ND_PRINT((ndo, ": %s", tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode))); } if (rrcp_opcode==1 || rrcp_opcode==2){ - ND_TCHECK2(*(rrcp + RRCP_REG_ADDR_OFFSET), 6); + ND_TCHECK2(*(cp + RRCP_REG_ADDR_OFFSET), 6); ND_PRINT((ndo, " addr=0x%04x, data=0x%08x", - EXTRACT_LE_16BITS(rrcp + RRCP_REG_ADDR_OFFSET), - EXTRACT_LE_32BITS(rrcp + RRCP_REG_DATA_OFFSET))); + EXTRACT_LE_16BITS(cp + RRCP_REG_ADDR_OFFSET), + EXTRACT_LE_32BITS(cp + RRCP_REG_DATA_OFFSET))); } if (rrcp_proto==1){ - ND_TCHECK2(*(rrcp + RRCP_AUTHKEY_OFFSET), 2); + ND_TCHECK2(*(cp + RRCP_AUTHKEY_OFFSET), 2); ND_PRINT((ndo, ", auth=0x%04x", - EXTRACT_16BITS(rrcp + RRCP_AUTHKEY_OFFSET))); + EXTRACT_16BITS(cp + RRCP_AUTHKEY_OFFSET))); } if (rrcp_proto==1 && rrcp_opcode==0 && - ((*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){ - ND_TCHECK2(*(rrcp + RRCP_VENDOR_ID_OFFSET), 4); + ((*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){ + ND_TCHECK2(*(cp + RRCP_VENDOR_ID_OFFSET), 4); ND_PRINT((ndo, " downlink_port=%d, uplink_port=%d, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ", - *(rrcp + RRCP_DOWNLINK_PORT_OFFSET), - *(rrcp + RRCP_UPLINK_PORT_OFFSET), - etheraddr_string(ndo, rrcp + RRCP_UPLINK_MAC_OFFSET), - EXTRACT_32BITS(rrcp + RRCP_VENDOR_ID_OFFSET), - EXTRACT_16BITS(rrcp + RRCP_CHIP_ID_OFFSET))); + *(cp + RRCP_DOWNLINK_PORT_OFFSET), + *(cp + RRCP_UPLINK_PORT_OFFSET), + etheraddr_string(ndo, cp + RRCP_UPLINK_MAC_OFFSET), + EXTRACT_32BITS(cp + RRCP_VENDOR_ID_OFFSET), + EXTRACT_16BITS(cp + RRCP_CHIP_ID_OFFSET))); }else if (rrcp_opcode==1 || rrcp_opcode==2 || rrcp_proto==2){ - ND_TCHECK2(*(rrcp + RRCP_COOKIE2_OFFSET), 4); + ND_TCHECK2(*(cp + RRCP_COOKIE2_OFFSET), 4); ND_PRINT((ndo, ", cookie=0x%08x%08x ", - EXTRACT_32BITS(rrcp + RRCP_COOKIE2_OFFSET), - EXTRACT_32BITS(rrcp + RRCP_COOKIE1_OFFSET))); + EXTRACT_32BITS(cp + RRCP_COOKIE2_OFFSET), + EXTRACT_32BITS(cp + RRCP_COOKIE1_OFFSET))); } return; diff --git a/print-sll.c b/print-sll.c index 0cbc3c93..6148569e 100644 --- a/print-sll.c +++ b/print-sll.c @@ -297,7 +297,7 @@ recurse: hdrlen += 4; goto recurse; } else { - if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { + if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) sll_print(ndo, sllp, length + SLL_HDR_LEN); diff --git a/print-symantec.c b/print-symantec.c index 13ac4e15..9e9f8f33 100644 --- a/print-symantec.c +++ b/print-symantec.c @@ -101,7 +101,7 @@ symantec_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_ if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); - } else if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { + } else if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) symantec_hdr_print(ndo, (const u_char *)sp, length + sizeof (struct symantec_header)); diff --git a/print-token.c b/print-token.c index 370c44c9..faffd4b1 100644 --- a/print-token.c +++ b/print-token.c @@ -151,6 +151,7 @@ token_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen const struct token_header *trp; int llc_hdrlen; struct ether_header ehdr; + struct lladdr_info src, dst; u_int route_len = 0, hdr_len = TOKEN_HDRLEN; int seg; @@ -203,6 +204,11 @@ token_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen token_hdr_print(ndo, trp, length, ESRC(&ehdr), EDST(&ehdr)); } + src.addr = ESRC(&ehdr); + src.addr_string = etheraddr_string; + dst.addr = EDST(&ehdr); + dst.addr_string = etheraddr_string; + /* Skip over token ring MAC header and routing information */ length -= hdr_len; p += hdr_len; @@ -211,8 +217,7 @@ token_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen /* Frame Control field determines interpretation of packet */ if (FRAME_TYPE(trp) == TOKEN_FC_LLC) { /* Try to print the LLC-layer header & higher layers */ - llc_hdrlen = llc_print(ndo, p, length, caplen, ESRC(&ehdr), - EDST(&ehdr)); + llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); if (llc_hdrlen < 0) { /* packet type not known, print raw packet */ if (!ndo->ndo_suppress_default_print) diff --git a/tests/TESTLIST b/tests/TESTLIST index a406c884..96d0312d 100644 --- a/tests/TESTLIST +++ b/tests/TESTLIST @@ -379,3 +379,5 @@ heapoverflow-in_checksum heapoverflow-in_checksum.pcap heapoverflow-in_checksum. heapoverflow-tcp_print heapoverflow-tcp_print.pcap heapoverflow-tcp_print.out -t -v -n gre-heapoverflow-1 gre-heapoverflow-1.pcap gre-heapoverflow-1.out -t -v -n gre-heapoverflow-2 gre-heapoverflow-2.pcap gre-heapoverflow-2.out -t -v -n +calm-fast-mac-lookup-heapoverflow calm-fast-mac-lookup-heapoverflow.pcap calm-fast-mac-lookup-heapoverflow.out -t -v -n +geonet-mac-lookup-heapoverflow geonet-mac-lookup-heapoverflow.pcap geonet-mac-lookup-heapoverflow.out -t -v -n diff --git a/tests/calm-fast-mac-lookup-heapoverflow.out b/tests/calm-fast-mac-lookup-heapoverflow.out new file mode 100644 index 00000000..a6e6f418 --- /dev/null +++ b/tests/calm-fast-mac-lookup-heapoverflow.out @@ -0,0 +1,5 @@ +Q.922, invalid address +CALM FAST; SrcNwref:48; DstNwref:48; + 0x0000: 3030 3030 3030 3030 3030 3030 3030 3030 0000000000000000 + 0x0010: 3030 3030 3030 3030 3030 3030 3030 3030 0000000000000000 + 0x0020: 3030 3030 3030 3030 3030 0000000000 diff --git a/tests/calm-fast-mac-lookup-heapoverflow.pcap b/tests/calm-fast-mac-lookup-heapoverflow.pcap new file mode 100644 index 00000000..a8409557 Binary files /dev/null and b/tests/calm-fast-mac-lookup-heapoverflow.pcap differ diff --git a/tests/geonet-mac-lookup-heapoverflow.out b/tests/geonet-mac-lookup-heapoverflow.out new file mode 100644 index 00000000..7d49dd0e --- /dev/null +++ b/tests/geonet-mac-lookup-heapoverflow.out @@ -0,0 +1 @@ +GeoNet src:30:30:30:30:30:30; v:3 NH:0-Any HT:3-0-GeoAnycastCircle HopLim:48 Payload:12336 [|geonet] diff --git a/tests/geonet-mac-lookup-heapoverflow.pcap b/tests/geonet-mac-lookup-heapoverflow.pcap new file mode 100644 index 00000000..e3041fb3 Binary files /dev/null and b/tests/geonet-mac-lookup-heapoverflow.pcap differ