/* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ u_int ap1394_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int length = h->len; u_int caplen = h->caplen; struct firewire_header *fp; u_short ether_type; if (caplen < FIREWIRE_HDRLEN) { ND_PRINT((ndo, "[|ap1394]")); return FIREWIRE_HDRLEN; } if (ndo->ndo_eflag) ap1394_hdr_print(ndo, p, length); length -= FIREWIRE_HDRLEN; caplen -= FIREWIRE_HDRLEN; fp = (struct firewire_header *)p; p += FIREWIRE_HDRLEN; ether_type = EXTRACT_16BITS(&fp->firewire_type); if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) ap1394_hdr_print(ndo, (u_char *)fp, length + FIREWIRE_HDRLEN); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } return FIREWIRE_HDRLEN; }
u_int juniper_pppoe_atm_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; uint16_t extracted_ethertype; l2info.pictype = DLT_JUNIPER_PPPOE_ATM; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; extracted_ethertype = EXTRACT_16BITS(p); /* this DLT contains nothing but raw PPPoE frames, * prepended with a type field*/ if (ethertype_print(ndo, extracted_ethertype, p+ETHERTYPE_LEN, l2info.length-ETHERTYPE_LEN, l2info.caplen-ETHERTYPE_LEN) == 0) /* ether_type not known, probably it wasn't one */ ND_PRINT((ndo, "unknown ethertype 0x%04x", extracted_ethertype)); return l2info.header_len; }
/* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ u_int ap1394_if_print(const struct pcap_pkthdr *h, const u_char *p) { u_int length = h->len; u_int caplen = h->caplen; struct firewire_header *fp; u_short ether_type; if (caplen < FIREWIRE_HDRLEN) { printf("[|ap1394]"); return FIREWIRE_HDRLEN; } if (eflag) ap1394_hdr_print(p, length); length -= FIREWIRE_HDRLEN; caplen -= FIREWIRE_HDRLEN; fp = (struct firewire_header *)p; p += FIREWIRE_HDRLEN; ether_type = EXTRACT_16BITS(&fp->firewire_type); if (ethertype_print(ether_type, p, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!eflag) ap1394_hdr_print((u_char *)fp, length + FIREWIRE_HDRLEN); if (!suppress_default_print) default_print(p, caplen); } return FIREWIRE_HDRLEN; }
void medsa_print(netdissect_options *ndo, const u_char *bp, u_int length, u_int caplen) { register const struct ether_header *ep; const struct medsa_pkthdr *medsa; u_short ether_type; medsa = (const struct medsa_pkthdr *)bp; ep = (const struct ether_header *)(bp - sizeof(*ep)); ND_TCHECK(*medsa); if (!ndo->ndo_eflag) ND_PRINT((ndo, "MEDSA %d.%d:%d: ", SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa))); else medsa_print_full(ndo, medsa, caplen); bp += 8; length -= 8; caplen -= 8; 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) { /* packet type not known, print raw packet */ if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(bp, caplen); } } else { if (ndo->ndo_eflag) ND_PRINT((ndo, "ethertype %s (0x%04x) ", tok2str(ethertype_values, "Unknown", ether_type), ether_type)); if (ethertype_print(ndo, ether_type, bp, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) ND_PRINT((ndo, "ethertype %s (0x%04x) ", tok2str(ethertype_values, "Unknown", ether_type), ether_type)); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(bp, caplen); } } return; trunc: ND_PRINT((ndo, "%s", tstr)); }
/* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ u_int symantec_if_print(const struct pcap_pkthdr *h, const u_char *p) { u_int length = h->len; u_int caplen = h->caplen; struct symantec_header *sp; u_short ether_type; if (caplen < sizeof (struct symantec_header)) { printf("[|symantec]"); return caplen; } if (eflag) symantec_hdr_print(p, length); length -= sizeof (struct symantec_header); caplen -= sizeof (struct symantec_header); sp = (struct symantec_header *)p; p += sizeof (struct symantec_header); ether_type = EXTRACT_16BITS(&sp->ether_type); if (ether_type <= ETHERMTU) { /* ether_type not known, print raw packet */ if (!eflag) symantec_hdr_print((u_char *)sp, length + sizeof (struct symantec_header)); if (!suppress_default_print) default_print(p, caplen); } else if (ethertype_print(gndo, ether_type, p, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!eflag) symantec_hdr_print((u_char *)sp, length + sizeof (struct symantec_header)); if (!suppress_default_print) default_print(p, caplen); } return (sizeof (struct symantec_header)); }
/* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ u_int symantec_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int length = h->len; u_int caplen = h->caplen; struct symantec_header *sp; u_short ether_type; if (caplen < sizeof (struct symantec_header)) { ND_PRINT((ndo, "[|symantec]")); return caplen; } if (ndo->ndo_eflag) symantec_hdr_print(ndo, p, length); length -= sizeof (struct symantec_header); caplen -= sizeof (struct symantec_header); sp = (struct symantec_header *)p; p += sizeof (struct symantec_header); ether_type = EXTRACT_16BITS(&sp->ether_type); if (ether_type <= ETHERMTU) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) symantec_hdr_print(ndo, (u_char *)sp, length + sizeof (struct symantec_header)); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } else if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) symantec_hdr_print(ndo, (u_char *)sp, length + sizeof (struct symantec_header)); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } return (sizeof (struct symantec_header)); }
/* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ u_int ap1394_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int length = h->len; u_int caplen = h->caplen; const struct firewire_header *fp; u_short ether_type; struct lladdr_info src, dst; ndo->ndo_protocol = "ap1394_if"; if (caplen < FIREWIRE_HDRLEN) { nd_print_trunc(ndo); return FIREWIRE_HDRLEN; } if (ndo->ndo_eflag) ap1394_hdr_print(ndo, p, length); length -= FIREWIRE_HDRLEN; caplen -= FIREWIRE_HDRLEN; fp = (const struct firewire_header *)p; p += FIREWIRE_HDRLEN; ether_type = GET_BE_U_2(fp->firewire_type); 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); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } return FIREWIRE_HDRLEN; }
u_int juniper_pppoe_atm_print(const struct pcap_pkthdr *h, packetbody_t p) { struct juniper_l2info_t l2info; u_int16_t extracted_ethertype; l2info.pictype = DLT_JUNIPER_PPPOE_ATM; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; extracted_ethertype = EXTRACT_16BITS(p); /* this DLT contains nothing but raw PPPoE frames, * prepended with a type field*/ if (ethertype_print(gndo, extracted_ethertype, p+ETHERTYPE_LEN, l2info.length-ETHERTYPE_LEN, l2info.caplen-ETHERTYPE_LEN) == 0) /* ether_type not known, probably it wasn't one */ printf("unknown ethertype 0x%04x", extracted_ethertype); return l2info.header_len; }
void geneve_print(netdissect_options *ndo, const u_char *bp, u_int len) { uint8_t ver_opt; u_int version; uint8_t flags; uint16_t prot; uint32_t vni; uint8_t reserved; u_int opts_len; ndo->ndo_protocol = "geneve"; ND_PRINT("Geneve"); ND_TCHECK_8(bp); ver_opt = GET_U_1(bp); bp += 1; len -= 1; version = ver_opt >> VER_SHIFT; if (version != 0) { ND_PRINT(" ERROR: unknown-version %u", version); return; } flags = GET_U_1(bp); bp += 1; len -= 1; prot = GET_BE_U_2(bp); bp += 2; len -= 2; vni = GET_BE_U_3(bp); bp += 3; len -= 3; reserved = GET_U_1(bp); bp += 1; len -= 1; ND_PRINT(", Flags [%s]", bittok2str_nosep(geneve_flag_values, "none", flags)); ND_PRINT(", vni 0x%x", vni); if (reserved) ND_PRINT(", rsvd 0x%x", reserved); if (ndo->ndo_eflag) ND_PRINT(", proto %s (0x%04x)", tok2str(ethertype_values, "unknown", prot), prot); opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4; if (len < opts_len) { ND_PRINT(" truncated-geneve - %u bytes missing", opts_len - len); return; } ND_TCHECK_LEN(bp, opts_len); if (opts_len > 0) { ND_PRINT(", options ["); if (ndo->ndo_vflag) geneve_opts_print(ndo, bp, opts_len); else ND_PRINT("%u bytes", opts_len); ND_PRINT("]"); } bp += opts_len; len -= opts_len; if (ndo->ndo_vflag < 1) ND_PRINT(": "); else ND_PRINT("\n\t"); if (ethertype_print(ndo, prot, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL) == 0) { if (prot == ETHERTYPE_TEB) ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); else ND_PRINT("geneve-proto-0x%x", prot); } return; trunc: nd_print_trunc(ndo); }
void geneve_print(netdissect_options *ndo, const u_char *bp, u_int len) { uint8_t ver_opt; u_int version; uint8_t flags; uint16_t prot; uint32_t vni; uint8_t reserved; u_int opts_len; ND_PRINT((ndo, "Geneve")); ND_TCHECK2(*bp, 8); ver_opt = *bp; bp += 1; len -= 1; version = ver_opt >> VER_SHIFT; if (version != 0) { ND_PRINT((ndo, " ERROR: unknown-version %u", version)); return; } flags = *bp; bp += 1; len -= 1; prot = EXTRACT_16BITS(bp); bp += 2; len -= 2; vni = EXTRACT_24BITS(bp); bp += 3; len -= 3; reserved = *bp; bp += 1; len -= 1; ND_PRINT((ndo, ", Flags [%s]", bittok2str_nosep(geneve_flag_values, "none", flags))); ND_PRINT((ndo, ", vni 0x%x", vni)); if (reserved) ND_PRINT((ndo, ", rsvd 0x%x", reserved)); if (ndo->ndo_eflag) ND_PRINT((ndo, ", proto %s (0x%04x)", tok2str(ethertype_values, "unknown", prot), prot)); opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4; if (len < opts_len) { ND_PRINT((ndo, " truncated-geneve - %u bytes missing", opts_len - len)); return; } ND_TCHECK2(*bp, opts_len); if (opts_len > 0) { ND_PRINT((ndo, ", options [")); if (ndo->ndo_vflag) geneve_opts_print(ndo, bp, opts_len); else ND_PRINT((ndo, "%u bytes", opts_len)); ND_PRINT((ndo, "]")); } bp += opts_len; len -= opts_len; if (ndo->ndo_vflag < 1) ND_PRINT((ndo, ": ")); else ND_PRINT((ndo, "\n\t")); if (ethertype_print(ndo, prot, bp, len, len) == 0) { if (prot == ETHERTYPE_TEB) ether_print(ndo, bp, len, len, NULL, NULL); else ND_PRINT((ndo, "geneve-proto-0x%x", prot)); } return; trunc: ND_PRINT((ndo, " [|geneve]")); }
/* * Print an Ethernet frame. * This might be encapsulated within another frame; we might be passed * a pointer to a function that can print header information for that * frame's protocol, and an argument to pass to that function. */ void ether_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, void (*print_encap_header)(netdissect_options *ndo, const u_char *), const u_char *encap_header_arg) { struct ether_header *ep; u_int orig_length; u_short ether_type; u_short extracted_ether_type; if (caplen < ETHER_HDRLEN || length < ETHER_HDRLEN) { ND_PRINT((ndo, "[|ether]")); return; } if (ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, p, length); } orig_length = length; length -= ETHER_HDRLEN; caplen -= ETHER_HDRLEN; ep = (struct ether_header *)p; p += ETHER_HDRLEN; ether_type = EXTRACT_16BITS(&ep->ether_type); recurse: /* * Is it (gag) an 802.3 encapsulation? */ if (ether_type <= ETHERMTU) { /* Try to print the LLC-layer header & higher layers */ if (llc_print(ndo, p, length, caplen, ESRC(ep), EDST(ep), &extracted_ether_type) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, (u_char *)ep, orig_length); } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } } else if (ether_type == ETHERTYPE_8021Q || ether_type == ETHERTYPE_8021Q9100 || ether_type == ETHERTYPE_8021Q9200 || ether_type == ETHERTYPE_8021QinQ) { /* * Print VLAN information, and then go back and process * the enclosed type field. */ if (caplen < 4 || length < 4) { ND_PRINT((ndo, "[|vlan]")); return; } if (ndo->ndo_eflag) { uint16_t tag = EXTRACT_16BITS(p); ND_PRINT((ndo, "%s, ", ieee8021q_tci_string(tag))); } ether_type = EXTRACT_16BITS(p + 2); if (ndo->ndo_eflag && ether_type > ETHERMTU) ND_PRINT((ndo, "ethertype %s, ", tok2str(ethertype_values,"0x%04x", ether_type))); p += 4; length -= 4; caplen -= 4; goto recurse; } else if (ether_type == ETHERTYPE_JUMBO) { /* * Alteon jumbo frames. * See * * http://tools.ietf.org/html/draft-ietf-isis-ext-eth-01 * * which indicates that, following the type field, * there's an LLC header and payload. */ /* Try to print the LLC-layer header & higher layers */ if (llc_print(ndo, p, length, caplen, ESRC(ep), EDST(ep), &extracted_ether_type) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, (u_char *)ep, orig_length); } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } } else { if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, (u_char *)ep, orig_length); } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } } }
int snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, const struct lladdr_info *src, const struct lladdr_info *dst, u_int bridge_pad) { uint32_t orgcode; u_short et; int ret; ND_TCHECK_5(p); if (caplen < 5 || length < 5) goto trunc; orgcode = EXTRACT_BE_U_3(p); et = EXTRACT_BE_U_2(p + 3); if (ndo->ndo_eflag) { /* * Somebody's already printed the MAC addresses, if there * are any, so just print the SNAP header, not the MAC * addresses. */ ND_PRINT("oui %s (0x%06x), %s %s (0x%04x), length %u: ", tok2str(oui_values, "Unknown", orgcode), orgcode, (orgcode == 0x000000 ? "ethertype" : "pid"), tok2str(oui_to_struct_tok(orgcode), "Unknown", et), et, length - 5); } p += 5; length -= 5; caplen -= 5; switch (orgcode) { case OUI_ENCAP_ETHER: case OUI_CISCO_90: /* * This is an encapsulated Ethernet packet, * or a packet bridged by some piece of * Cisco hardware; the protocol ID is * an Ethernet protocol type. */ ret = ethertype_print(ndo, et, p, length, caplen, src, dst); if (ret) return (ret); break; case OUI_APPLETALK: if (et == ETHERTYPE_ATALK) { /* * No, I have no idea why Apple used one * of their own OUIs, rather than * 0x000000, and an Ethernet packet * type, for Appletalk data packets, * but used 0x000000 and an Ethernet * packet type for AARP packets. */ ret = ethertype_print(ndo, et, p, length, caplen, src, dst); if (ret) return (ret); } break; case OUI_CISCO: switch (et) { case PID_CISCO_CDP: cdp_print(ndo, p, length, caplen); return (1); case PID_CISCO_DTP: dtp_print(ndo, p, length); return (1); case PID_CISCO_UDLD: udld_print(ndo, p, length); return (1); case PID_CISCO_VTP: vtp_print(ndo, p, length); return (1); case PID_CISCO_PVST: case PID_CISCO_VLANBRIDGE: stp_print(ndo, p, length); return (1); default: break; } break; case OUI_RFC2684: switch (et) { case PID_RFC2684_ETH_FCS: case PID_RFC2684_ETH_NOFCS: /* * XXX - remove the last two bytes for * PID_RFC2684_ETH_FCS? */ /* * Skip the padding. */ ND_TCHECK_LEN(p, bridge_pad); caplen -= bridge_pad; length -= bridge_pad; p += bridge_pad; /* * What remains is an Ethernet packet. */ ether_print(ndo, p, length, caplen, NULL, NULL); return (1); case PID_RFC2684_802_5_FCS: case PID_RFC2684_802_5_NOFCS: /* * XXX - remove the last two bytes for * PID_RFC2684_ETH_FCS? */ /* * Skip the padding, but not the Access * Control field. */ ND_TCHECK_LEN(p, bridge_pad); caplen -= bridge_pad; length -= bridge_pad; p += bridge_pad; /* * What remains is an 802.5 Token Ring * packet. */ token_print(ndo, p, length, caplen); return (1); case PID_RFC2684_FDDI_FCS: case PID_RFC2684_FDDI_NOFCS: /* * XXX - remove the last two bytes for * PID_RFC2684_ETH_FCS? */ /* * Skip the padding. */ ND_TCHECK_LEN(p, bridge_pad + 1); caplen -= bridge_pad + 1; length -= bridge_pad + 1; p += bridge_pad + 1; /* * What remains is an FDDI packet. */ fddi_print(ndo, p, length, caplen); return (1); case PID_RFC2684_BPDU: stp_print(ndo, p, length); return (1); } } if (!ndo->ndo_eflag) { /* * Nobody printed the link-layer addresses, so print them, if * we have any. */ if (src != NULL && dst != NULL) { ND_PRINT("%s > %s ", (src->addr_string)(ndo, src->addr), (dst->addr_string)(ndo, dst->addr)); } /* * Print the SNAP header, but if the OUI is 000000, don't * bother printing it, and report the PID as being an * ethertype. */ if (orgcode == 0x000000) { ND_PRINT("SNAP, ethertype %s (0x%04x), length %u: ", tok2str(ethertype_values, "Unknown", et), et, length); } else { ND_PRINT("SNAP, oui %s (0x%06x), pid %s (0x%04x), length %u: ", tok2str(oui_values, "Unknown", orgcode), orgcode, tok2str(oui_to_struct_tok(orgcode), "Unknown", et), et, length); } } return (0); trunc: ND_PRINT("[|snap]"); return (1); }
int snap_print(packetbody_t p, u_int length, u_int caplen, u_int bridge_pad) { u_int32_t orgcode; register u_short et; register int ret; PACKET_HAS_SPACE_OR_TRUNC(p, 5); orgcode = EXTRACT_24BITS(p); et = EXTRACT_16BITS(p + 3); if (eflag) { const struct tok *tok = null_values; const struct oui_tok *otp; for (otp = &oui_to_tok[0]; otp->tok != NULL; otp++) { if (otp->oui == orgcode) { tok = otp->tok; break; } } (void)printf("oui %s (0x%06x), %s %s (0x%04x): ", tok2str(oui_values, "Unknown", orgcode), orgcode, (orgcode == 0x000000 ? "ethertype" : "pid"), tok2str(tok, "Unknown", et), et); } p += 5; length -= 5; caplen -= 5; switch (orgcode) { case OUI_ENCAP_ETHER: case OUI_CISCO_90: /* * This is an encapsulated Ethernet packet, * or a packet bridged by some piece of * Cisco hardware; the protocol ID is * an Ethernet protocol type. */ ret = ethertype_print(gndo, et, p, length, caplen); if (ret) return (ret); break; case OUI_APPLETALK: if (et == ETHERTYPE_ATALK) { /* * No, I have no idea why Apple used one * of their own OUIs, rather than * 0x000000, and an Ethernet packet * type, for Appletalk data packets, * but used 0x000000 and an Ethernet * packet type for AARP packets. */ ret = ethertype_print(gndo, et, p, length, caplen); if (ret) return (ret); } break; case OUI_CISCO: switch (et) { case PID_CISCO_CDP: cdp_print(p, length, caplen); return (1); case PID_CISCO_DTP: dtp_print(p, length); return (1); case PID_CISCO_UDLD: udld_print(p, length); return (1); case PID_CISCO_VTP: vtp_print(p, length); return (1); case PID_CISCO_PVST: stp_print(p, length); return (1); default: break; } case OUI_RFC2684: switch (et) { case PID_RFC2684_ETH_FCS: case PID_RFC2684_ETH_NOFCS: /* * XXX - remove the last two bytes for * PID_RFC2684_ETH_FCS? */ /* * Skip the padding. */ PACKET_HAS_SPACE_OR_TRUNC(p, bridge_pad); caplen -= bridge_pad; length -= bridge_pad; p += bridge_pad; /* * What remains is an Ethernet packet. */ ether_print(gndo, p, length, caplen, NULL, NULL); return (1); case PID_RFC2684_802_5_FCS: case PID_RFC2684_802_5_NOFCS: /* * XXX - remove the last two bytes for * PID_RFC2684_ETH_FCS? */ /* * Skip the padding, but not the Access * Control field. */ PACKET_HAS_SPACE_OR_TRUNC(p, bridge_pad); caplen -= bridge_pad; length -= bridge_pad; p += bridge_pad; /* * What remains is an 802.5 Token Ring * packet. */ token_print(p, length, caplen); return (1); case PID_RFC2684_FDDI_FCS: case PID_RFC2684_FDDI_NOFCS: /* * XXX - remove the last two bytes for * PID_RFC2684_ETH_FCS? */ /* * Skip the padding. */ PACKET_HAS_SPACE_OR_TRUNC(p, bridge_pad + 1); caplen -= bridge_pad + 1; length -= bridge_pad + 1; p += bridge_pad + 1; /* * What remains is an FDDI packet. */ fddi_print(p, length, caplen); return (1); case PID_RFC2684_BPDU: stp_print(p, length); return (1); } } return (0); trunc: (void)printf("[|snap]"); return (1); }
/* * This is the top level routine of the printer. 'p' points to the * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ u_int sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; u_int length = h->len; register const struct sll_header *sllp; u_short ether_type; int llc_hdrlen; u_int hdrlen; if (caplen < SLL_HDR_LEN) { /* * XXX - this "can't happen" because "pcap-linux.c" always * adds this many bytes of header to every packet in a * cooked socket capture. */ ND_PRINT((ndo, "[|sll]")); return (caplen); } sllp = (const struct sll_header *)p; if (ndo->ndo_eflag) sll_print(ndo, sllp, length); /* * Go past the cooked-mode header. */ length -= SLL_HDR_LEN; caplen -= SLL_HDR_LEN; p += SLL_HDR_LEN; hdrlen = SLL_HDR_LEN; ether_type = EXTRACT_16BITS(&sllp->sll_protocol); recurse: /* * Is it (gag) an 802.3 encapsulation, or some non-Ethernet * packet type? */ if (ether_type <= ETHERMTU) { /* * Yes - what type is it? */ switch (ether_type) { case LINUX_SLL_P_802_3: /* * Ethernet_802.3 IPX frame. */ ipx_print(ndo, p, length); break; case LINUX_SLL_P_802_2: /* * 802.2. * Try to print the LLC-layer header & higher layers. */ llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL); if (llc_hdrlen < 0) goto unknown; /* unknown LLC type */ hdrlen += llc_hdrlen; break; default: /*FALLTHROUGH*/ unknown: /* packet type not known, print raw packet */ if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); break; } } else if (ether_type == ETHERTYPE_8021Q) { /* * Print VLAN information, and then go back and process * the enclosed type field. */ if (caplen < 4) { ND_PRINT((ndo, "[|vlan]")); return (hdrlen + caplen); } if (length < 4) { ND_PRINT((ndo, "[|vlan]")); return (hdrlen + length); } if (ndo->ndo_eflag) { uint16_t tag = EXTRACT_16BITS(p); ND_PRINT((ndo, "%s, ", ieee8021q_tci_string(tag))); } ether_type = EXTRACT_16BITS(p + 2); if (ether_type <= ETHERMTU) ether_type = LINUX_SLL_P_802_2; if (!ndo->ndo_qflag) { ND_PRINT((ndo, "ethertype %s, ", tok2str(ethertype_values, "Unknown", ether_type))); } p += 4; length -= 4; caplen -= 4; hdrlen += 4; goto recurse; } else { if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) sll_print(ndo, sllp, length + SLL_HDR_LEN); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } } return (hdrlen); }