/* * Print EtherTalk/TokenTalk packets (or FDDITalk, or whatever it's called * when it runs over FDDI; yes, I've seen FDDI captures with AppleTalk * packets in them). */ void atalk_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct atDDP *dp; u_short snet; ndo->ndo_protocol = "atalk"; if(!ndo->ndo_eflag) ND_PRINT("AT "); if (length < ddpSize) { ND_PRINT(" [|ddp %u]", length); return; } if (!ND_TTEST_LEN(bp, ddpSize)) { ND_PRINT(" [|ddp]"); return; } dp = (const struct atDDP *)bp; snet = EXTRACT_BE_U_2(dp->srcNet); ND_PRINT("%s.%s", ataddr_string(ndo, snet, EXTRACT_U_1(dp->srcNode)), ddpskt_string(ndo, EXTRACT_U_1(dp->srcSkt))); ND_PRINT(" > %s.%s: ", ataddr_string(ndo, EXTRACT_BE_U_2(dp->dstNet), EXTRACT_U_1(dp->dstNode)), ddpskt_string(ndo, EXTRACT_U_1(dp->dstSkt))); bp += ddpSize; length -= ddpSize; ddp_print(ndo, bp, length, EXTRACT_U_1(dp->type), snet, EXTRACT_U_1(dp->srcNode), EXTRACT_U_1(dp->srcSkt)); }
/* * Print RRCP requests */ void rrcp_print(netdissect_options *ndo, const u_char *cp, u_int length _U_, const struct lladdr_info *src, const struct lladdr_info *dst) { uint8_t rrcp_proto; uint8_t rrcp_opcode; ndo->ndo_protocol = "rrcp"; ND_TCHECK_1(cp + RRCP_PROTO_OFFSET); rrcp_proto = EXTRACT_U_1(cp + RRCP_PROTO_OFFSET); ND_TCHECK_1(cp + RRCP_OPCODE_ISREPLY_OFFSET); rrcp_opcode = EXTRACT_U_1((cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK; if (src != NULL && dst != NULL) { ND_PRINT("%s > %s, ", (src->addr_string)(ndo, src->addr), (dst->addr_string)(ndo, dst->addr)); } ND_PRINT("%s %s", tok2str(proto_values,"RRCP-0x%02x",rrcp_proto), ((EXTRACT_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query"); if (rrcp_proto==1){ ND_PRINT(": %s", tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode)); } if (rrcp_opcode==1 || rrcp_opcode==2){ ND_TCHECK_6(cp + RRCP_REG_ADDR_OFFSET); ND_PRINT(" addr=0x%04x, data=0x%08x", EXTRACT_LE_U_2(cp + RRCP_REG_ADDR_OFFSET), EXTRACT_LE_U_4(cp + RRCP_REG_DATA_OFFSET)); } if (rrcp_proto==1){ ND_TCHECK_2(cp + RRCP_AUTHKEY_OFFSET); ND_PRINT(", auth=0x%04x", EXTRACT_BE_U_2(cp + RRCP_AUTHKEY_OFFSET)); } if (rrcp_proto==1 && rrcp_opcode==0 && ((EXTRACT_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){ ND_TCHECK_4(cp + RRCP_VENDOR_ID_OFFSET); ND_PRINT(" downlink_port=%u, uplink_port=%u, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ", EXTRACT_U_1(cp + RRCP_DOWNLINK_PORT_OFFSET), EXTRACT_U_1(cp + RRCP_UPLINK_PORT_OFFSET), etheraddr_string(ndo, cp + RRCP_UPLINK_MAC_OFFSET), EXTRACT_BE_U_4(cp + RRCP_VENDOR_ID_OFFSET), EXTRACT_BE_U_2(cp + RRCP_CHIP_ID_OFFSET)); }else if (rrcp_opcode==1 || rrcp_opcode==2 || rrcp_proto==2){ ND_TCHECK_4(cp + RRCP_COOKIE2_OFFSET); ND_PRINT(", cookie=0x%08x%08x ", EXTRACT_BE_U_4(cp + RRCP_COOKIE2_OFFSET), EXTRACT_BE_U_4(cp + RRCP_COOKIE1_OFFSET)); } return; trunc: nd_print_trunc(ndo); }
/* IP6CP config options */ static u_int print_ip6cp_config_options(netdissect_options *ndo, const u_char *p, u_int length) { u_int opt, len; if (length < 2) return 0; ND_TCHECK_2(p); opt = EXTRACT_U_1(p); len = EXTRACT_U_1(p + 1); if (length < len) return 0; if (len < 2) { ND_PRINT("\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", tok2str(ip6cpopt_values,"unknown",opt), opt, len); return 0; } ND_PRINT("\n\t %s Option (0x%02x), length %u", tok2str(ip6cpopt_values,"unknown",opt), opt, len); switch (opt) { case IP6CP_IFID: if (len != 10) { ND_PRINT(" (length bogus, should be = 10)"); return len; } ND_TCHECK_8(p + 2); ND_PRINT(": %04x:%04x:%04x:%04x", EXTRACT_BE_U_2(p + 2), EXTRACT_BE_U_2(p + 4), EXTRACT_BE_U_2(p + 6), EXTRACT_BE_U_2(p + 8)); break; default: /* * Unknown option; dump it as raw bytes now if we're * not going to do so below. */ if (ndo->ndo_vflag < 2) print_unknown_data(ndo, p + 2, "\n\t ", len - 2); break; } if (ndo->ndo_vflag > 1) print_unknown_data(ndo, p + 2, "\n\t ", len - 2); /* exclude TLV header */ return len; trunc: ND_PRINT("[|ip6cp]"); return 0; }
/* * Print NTP control message requests and responses */ static void ntp_control_print(netdissect_options *ndo, const struct ntp_control_data *cd, u_int length) { uint8_t control, R, E, M, opcode; uint16_t sequence, status, assoc, offset, count; if (length < NTP_CTRLMSG_MINLEN) goto invalid; ND_TCHECK_1(cd->control); control = EXTRACT_U_1(cd->control); R = (control & 0x80) != 0; E = (control & 0x40) != 0; M = (control & 0x20) != 0; opcode = control & 0x1f; ND_PRINT(", %s, %s, %s, OpCode=%u\n", R ? "Response" : "Request", E ? "Error" : "OK", M ? "More" : "Last", opcode); ND_TCHECK_2(cd->sequence); sequence = EXTRACT_BE_U_2(cd->sequence); ND_PRINT("\tSequence=%hu", sequence); ND_TCHECK_2(cd->status); status = EXTRACT_BE_U_2(cd->status); ND_PRINT(", Status=%#hx", status); ND_TCHECK_2(cd->assoc); assoc = EXTRACT_BE_U_2(cd->assoc); ND_PRINT(", Assoc.=%hu", assoc); ND_TCHECK_2(cd->offset); offset = EXTRACT_BE_U_2(cd->offset); ND_PRINT(", Offset=%hu", offset); ND_TCHECK_2(cd->count); count = EXTRACT_BE_U_2(cd->count); ND_PRINT(", Count=%hu", count); if (NTP_CTRLMSG_MINLEN + count > length) goto invalid; if (count != 0) { ND_TCHECK_LEN(cd->data, count); ND_PRINT("\n\tTO-BE-DONE: data not interpreted"); } return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(cd, length); return; trunc: nd_print_trunc(ndo); }
void igrp_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct igrphdr *hdr; const u_char *cp; u_int nint, nsys, next; hdr = (const struct igrphdr *)bp; cp = (const u_char *)(hdr + 1); ND_PRINT("igrp:"); /* Header */ ND_TCHECK_SIZE(hdr); nint = EXTRACT_BE_U_2(hdr->ig_ni); nsys = EXTRACT_BE_U_2(hdr->ig_ns); next = EXTRACT_BE_U_2(hdr->ig_nx); ND_PRINT(" %s V%u edit=%u AS=%u (%u/%u/%u)", tok2str(op2str, "op-#%u", IGRP_OP(EXTRACT_U_1(hdr->ig_vop))), IGRP_V(EXTRACT_U_1(hdr->ig_vop)), EXTRACT_U_1(hdr->ig_ed), EXTRACT_BE_U_2(hdr->ig_as), nint, nsys, next); length -= sizeof(*hdr); while (length >= IGRP_RTE_SIZE) { if (nint > 0) { ND_TCHECK_LEN(cp, IGRP_RTE_SIZE); igrp_entry_print(ndo, (const struct igrprte *)cp, 1, 0); --nint; } else if (nsys > 0) { ND_TCHECK_LEN(cp, IGRP_RTE_SIZE); igrp_entry_print(ndo, (const struct igrprte *)cp, 0, 0); --nsys; } else if (next > 0) { ND_TCHECK_LEN(cp, IGRP_RTE_SIZE); igrp_entry_print(ndo, (const struct igrprte *)cp, 0, 1); --next; } else { ND_PRINT(" [extra bytes %u]", length); break; } cp += IGRP_RTE_SIZE; length -= IGRP_RTE_SIZE; } if (nint == 0 && nsys == 0 && next == 0) return; trunc: ND_PRINT(" [|igrp]"); }
void gre_print(netdissect_options *ndo, const u_char *bp, u_int length) { u_int len = length, vers; ND_TCHECK_2(bp); if (len < 2) goto trunc; vers = EXTRACT_BE_U_2(bp) & GRE_VERS_MASK; ND_PRINT("GREv%u",vers); switch(vers) { case 0: gre_print_0(ndo, bp, len); break; case 1: gre_print_1(ndo, bp, len); break; default: ND_PRINT(" ERROR: unknown-version"); break; } return; trunc: ND_PRINT("%s", tstr); return; }
static int gre_sre_asn_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen, const u_char *bp, u_int len) { const u_char *up = bp; if (sreoff & 1) { ND_PRINT(", badoffset=%u", sreoff); return (1); } if (srelen & 1) { ND_PRINT(", badlength=%u", srelen); return (1); } if (sreoff >= srelen) { ND_PRINT(", badoff/len=%u/%u", sreoff, srelen); return (1); } while (srelen != 0) { if (!ND_TTEST_2(bp)) return (0); if (len < 2) return (0); ND_PRINT(" %s%x", ((bp - up) == sreoff) ? "*" : "", EXTRACT_BE_U_2(bp)); bp += 2; len -= 2; srelen -= 2; } return (1); }
/* * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload, * with the CAN ID being in host byte order. * * When reading a DLT_LINUX_SLL capture file, we need to check for those * packets and convert the CAN ID from the byte order of the host that * wrote the file to this host's byte order. */ static void swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf) { u_int caplen = hdr->caplen; u_int length = hdr->len; struct sll_header *shdr = (struct sll_header *)buf; uint16_t protocol; pcap_can_socketcan_hdr *chdr; if (caplen < (u_int) sizeof(struct sll_header) || length < (u_int) sizeof(struct sll_header)) { /* Not enough data to have the protocol field */ return; } protocol = EXTRACT_BE_U_2(&shdr->sll_protocol); if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD) return; /* * SocketCAN packet; fix up the packet's header. */ chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header)); if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) || length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) { /* Not enough data to have the CAN ID */ return; } chdr->can_id = SWAPLONG(chdr->can_id); }
static void igrp_entry_print(netdissect_options *ndo, const struct igrprte *igr, int is_interior, int is_exterior) { u_int delay, bandwidth; u_int metric, mtu; if (is_interior) ND_PRINT(" *.%u.%u.%u", igr->igr_net[0], igr->igr_net[1], igr->igr_net[2]); else if (is_exterior) ND_PRINT(" X%u.%u.%u.0", igr->igr_net[0], igr->igr_net[1], igr->igr_net[2]); else ND_PRINT(" %u.%u.%u.0", igr->igr_net[0], igr->igr_net[1], igr->igr_net[2]); delay = EXTRACT_BE_U_3(igr->igr_dly); bandwidth = EXTRACT_BE_U_3(igr->igr_bw); metric = bandwidth + delay; if (metric > 0xffffff) metric = 0xffffff; mtu = EXTRACT_BE_U_2(igr->igr_mtu); ND_PRINT(" d=%u b=%u r=%u l=%u M=%u mtu=%u in %u hops", 10 * delay, bandwidth == 0 ? 0 : 10000000 / bandwidth, EXTRACT_U_1(igr->igr_rel), EXTRACT_U_1(igr->igr_ld), metric, mtu, EXTRACT_U_1(igr->igr_hct)); }
static void print_attr_string(netdissect_options *ndo, const u_char *data, u_int length, u_short attr_code) { u_int i; ND_TCHECK_LEN(data, length); switch(attr_code) { case TUNNEL_PASS: if (length < 3) goto trunc; if (EXTRACT_U_1(data) && (EXTRACT_U_1(data) <= 0x1F)) ND_PRINT("Tag[%u] ", EXTRACT_U_1(data)); else ND_PRINT("Tag[Unused] "); data++; length--; ND_PRINT("Salt %u ", EXTRACT_BE_U_2(data)); data+=2; length-=2; break; case TUNNEL_CLIENT_END: case TUNNEL_SERVER_END: case TUNNEL_PRIV_GROUP: case TUNNEL_ASSIGN_ID: case TUNNEL_CLIENT_AUTH: case TUNNEL_SERVER_AUTH: if (EXTRACT_U_1(data) <= 0x1F) { if (length < 1) goto trunc; if (EXTRACT_U_1(data)) ND_PRINT("Tag[%u] ", EXTRACT_U_1(data)); else ND_PRINT("Tag[Unused] "); data++; length--; } break; case EGRESS_VLAN_NAME: if (length < 1) goto trunc; ND_PRINT("%s (0x%02x) ", tok2str(rfc4675_tagged,"Unknown tag",EXTRACT_U_1(data)), EXTRACT_U_1(data)); data++; length--; break; } for (i=0; i < length && EXTRACT_U_1(data); i++, data++) ND_PRINT("%c", ND_ISPRINT(EXTRACT_U_1(data)) ? EXTRACT_U_1(data) : '.'); return; trunc: nd_print_trunc(ndo); }
void timed_print(netdissect_options *ndo, const u_char *bp) { const struct tsp *tsp = (const struct tsp *)bp; uint8_t tsp_type; int sec, usec; ndo->ndo_protocol = "timed"; ND_TCHECK_1(tsp->tsp_type); tsp_type = EXTRACT_U_1(tsp->tsp_type); if (tsp_type < TSPTYPENUMBER) ND_PRINT("TSP_%s", tsptype[tsp_type]); else ND_PRINT("(tsp_type %#x)", tsp_type); ND_TCHECK_1(tsp->tsp_vers); ND_PRINT(" vers %u", EXTRACT_U_1(tsp->tsp_vers)); ND_TCHECK_2(tsp->tsp_seq); ND_PRINT(" seq %u", EXTRACT_BE_U_2(tsp->tsp_seq)); switch (tsp_type) { case TSP_LOOP: ND_TCHECK_1(tsp->tsp_hopcnt); ND_PRINT(" hopcnt %u", EXTRACT_U_1(tsp->tsp_hopcnt)); break; case TSP_SETTIME: case TSP_ADJTIME: case TSP_SETDATE: case TSP_SETDATEREQ: ND_TCHECK_8(&tsp->tsp_time); sec = EXTRACT_BE_S_4(tsp->tsp_time.tv_sec); usec = EXTRACT_BE_S_4(tsp->tsp_time.tv_usec); /* XXX The comparison below is always false? */ if (usec < 0) /* invalid, skip the rest of the packet */ return; ND_PRINT(" time "); if (sec < 0 && usec != 0) { sec++; if (sec == 0) ND_PRINT("-"); usec = 1000000 - usec; } ND_PRINT("%d.%06d", sec, usec); break; } ND_PRINT(" name "); if (nd_printzp(ndo, tsp->tsp_name, sizeof(tsp->tsp_name), ndo->ndo_snapend)) goto trunc; return; trunc: nd_print_trunc(ndo); }
static int stp_print_config_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu, u_int length) { uint8_t bpdu_flags; ND_TCHECK_1(stp_bpdu->flags); bpdu_flags = EXTRACT_U_1(stp_bpdu->flags); ND_PRINT(", Flags [%s]", bittok2str(stp_bpdu_flag_values, "none", bpdu_flags)); ND_TCHECK_2(stp_bpdu->port_id); ND_PRINT(", bridge-id %s.%04x, length %u", stp_print_bridge_id((const u_char *)&stp_bpdu->bridge_id), EXTRACT_BE_U_2(stp_bpdu->port_id), length); /* in non-verbose mode just print the bridge-id */ if (!ndo->ndo_vflag) { return 1; } ND_TCHECK_2(stp_bpdu->forward_delay); ND_PRINT("\n\tmessage-age %.2fs, max-age %.2fs" ", hello-time %.2fs, forwarding-delay %.2fs", (float) EXTRACT_BE_U_2(stp_bpdu->message_age) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->max_age) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->hello_time) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->forward_delay) / STP_TIME_BASE); ND_PRINT("\n\troot-id %s, root-pathcost %u", stp_print_bridge_id((const u_char *)&stp_bpdu->root_id), EXTRACT_BE_U_4(stp_bpdu->root_path_cost)); /* Port role is only valid for 802.1w */ if (EXTRACT_U_1(stp_bpdu->protocol_version) == STP_PROTO_RAPID) { ND_PRINT(", port-role %s", tok2str(rstp_obj_port_role_values, "Unknown", RSTP_EXTRACT_PORT_ROLE(bpdu_flags))); } return 1; trunc: return 0; }
/* Print a single OpenFlow message. */ static const u_char * of_header_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { uint8_t version, type; uint16_t length; uint32_t xid; if (ep < cp + OF_HEADER_LEN) goto invalid; /* version */ ND_TCHECK_1(cp); version = EXTRACT_U_1(cp); cp += 1; /* type */ ND_TCHECK_1(cp); type = EXTRACT_U_1(cp); cp += 1; /* length */ ND_TCHECK_2(cp); length = EXTRACT_BE_U_2(cp); cp += 2; /* xid */ ND_TCHECK_4(cp); xid = EXTRACT_BE_U_4(cp); cp += 4; /* Message length includes the header length and a message always includes * the basic header. A message length underrun fails decoding of the rest of * the current packet. At the same time, try decoding as much of the current * message as possible even when it does not end within the current TCP * segment. */ if (length < OF_HEADER_LEN) { of_header_print(ndo, version, type, length, xid); goto invalid; } /* Decode known protocol versions further without printing the header (the * type decoding is version-specific. */ switch (version) { case OF_VER_1_0: return of10_header_body_print(ndo, cp, ep, type, length, xid); default: of_header_print(ndo, version, type, length, xid); ND_TCHECK_LEN(cp, length - OF_HEADER_LEN); return cp + length - OF_HEADER_LEN; /* done with current message */ } invalid: /* fail current packet */ ND_PRINT("%s", istr); ND_TCHECK_LEN(cp, ep - cp); return ep; trunc: ND_PRINT("%s", tstr); return ep; }
void radius_print(netdissect_options *ndo, const u_char *dat, u_int length) { const struct radius_hdr *rad; u_int len, auth_idx; ndo->ndo_protocol = "radius"; ND_TCHECK_LEN(dat, MIN_RADIUS_LEN); rad = (const struct radius_hdr *)dat; len = EXTRACT_BE_U_2(rad->len); if (len < MIN_RADIUS_LEN) { nd_print_trunc(ndo); return; } if (len > length) len = length; if (ndo->ndo_vflag < 1) { ND_PRINT("RADIUS, %s (%u), id: 0x%02x length: %u", tok2str(radius_command_values,"Unknown Command",EXTRACT_U_1(rad->code)), EXTRACT_U_1(rad->code), EXTRACT_U_1(rad->id), len); return; } else { ND_PRINT("RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ", len, tok2str(radius_command_values,"Unknown Command",EXTRACT_U_1(rad->code)), EXTRACT_U_1(rad->code), EXTRACT_U_1(rad->id)); for(auth_idx=0; auth_idx < 16; auth_idx++) ND_PRINT("%02x", rad->auth[auth_idx]); } if (len > MIN_RADIUS_LEN) radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN); return; trunc: nd_print_trunc(ndo); }
static int lwres_printnamelen(netdissect_options *ndo, const u_char *p) { uint16_t l; int advance; if (p + 2 > ndo->ndo_snapend) goto trunc; l = EXTRACT_BE_U_2(p); advance = lwres_printname(ndo, l, p + 2); if (advance < 0) goto trunc; return 2 + advance; trunc: return -1; }
static void ahcp1_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { uint8_t type, mbz; uint16_t body_len; if (cp + AHCP1_BODY_MIN_LEN > ep) goto invalid; /* Type */ ND_TCHECK_1(cp); type = EXTRACT_U_1(cp); cp += 1; /* MBZ */ ND_TCHECK_1(cp); mbz = EXTRACT_U_1(cp); cp += 1; /* Length */ ND_TCHECK_2(cp); body_len = EXTRACT_BE_U_2(cp); cp += 2; if (ndo->ndo_vflag) { ND_PRINT("\n\t%s", tok2str(ahcp1_msg_str, "Unknown-%u", type)); if (mbz != 0) ND_PRINT(", MBZ %u", mbz); ND_PRINT(", Length %u", body_len); } if (cp + body_len > ep) goto invalid; /* Options */ if (ndo->ndo_vflag >= 2) ahcp1_options_print(ndo, cp, cp + body_len); /* not ep (ignore extra data) */ else ND_TCHECK_LEN(cp, body_len); return; invalid: ND_PRINT("%s", istr); ND_TCHECK_LEN(cp, ep - cp); return; trunc: nd_print_trunc(ndo); }
static int lwres_printaddr(netdissect_options *ndo, const u_char *p0) { const u_char *p; const lwres_addr_t *ap; uint16_t l; int i; p = p0; ap = (const lwres_addr_t *)p; ND_TCHECK_2(ap->length); l = EXTRACT_BE_U_2(ap->length); p += LWRES_ADDR_LEN; ND_TCHECK_LEN(p, l); switch (EXTRACT_BE_U_4(ap->family)) { case 1: /* IPv4 */ if (l < 4) return -1; ND_PRINT(" %s", ipaddr_string(ndo, p)); p += sizeof(nd_ipv4); break; case 2: /* IPv6 */ if (l < 16) return -1; ND_PRINT(" %s", ip6addr_string(ndo, p)); p += sizeof(nd_ipv6); break; default: ND_PRINT(" %u/", EXTRACT_BE_U_4(ap->family)); for (i = 0; i < l; i++) { ND_PRINT("%02x", EXTRACT_U_1(p)); p++; } } return p - p0; trunc: return -1; }
static void geneve_opts_print(netdissect_options *ndo, const u_char *bp, u_int len) { const char *sep = ""; while (len > 0) { uint16_t opt_class; uint8_t opt_type; uint8_t opt_len; ND_PRINT("%s", sep); sep = ", "; opt_class = EXTRACT_BE_U_2(bp); opt_type = EXTRACT_U_1(bp + 2); opt_len = 4 + ((EXTRACT_U_1(bp + 3) & OPT_LEN_MASK) * 4); ND_PRINT("class %s (0x%x) type 0x%x%s len %u", format_opt_class(opt_class), opt_class, opt_type, opt_type & OPT_TYPE_CRITICAL ? "(C)" : "", opt_len); if (opt_len > len) { ND_PRINT(" [bad length]"); return; } if (ndo->ndo_vflag > 1 && opt_len > 4) { const uint32_t *data = (const uint32_t *)(bp + 4); int i; ND_PRINT(" data"); for (i = 4; i < opt_len; i += 4) { ND_PRINT(" %08x", EXTRACT_BE_U_4(data)); data++; } } bp += opt_len; len -= opt_len; } }
static void handle_mlppp(netdissect_options *ndo, const u_char *p, u_int length) { if (!ndo->ndo_eflag) ND_PRINT("MLPPP, "); if (length < 2) { ND_PRINT("[|mlppp]"); return; } if (!ND_TTEST_2(p)) { ND_PRINT("[|mlppp]"); return; } ND_PRINT("seq 0x%03x, Flags [%s], length %u", (EXTRACT_BE_U_2(p))&0x0fff, /* only support 12-Bit sequence space for now */ bittok2str(ppp_ml_flag_values, "none", EXTRACT_U_1(p) & 0xc0), length); }
static int lwres_printbinlen(netdissect_options *ndo, const u_char *p0) { const u_char *p; uint16_t l; int i; p = p0; if (p + 2 > ndo->ndo_snapend) goto trunc; l = EXTRACT_BE_U_2(p); if (p + 2 + l > ndo->ndo_snapend) goto trunc; p += 2; for (i = 0; i < l; i++) { ND_PRINT("%02x", EXTRACT_U_1(p)); p++; } return p - p0; trunc: return -1; }
/* XXX should probably pass in the snap header and do checks like arp_print() */ void aarp_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct aarp *ap; #define AT(member) ataddr_string(ndo, (ap->member[1]<<8)|ap->member[2],ap->member[3]) ndo->ndo_protocol = "aarp"; ND_PRINT("aarp "); ap = (const struct aarp *)bp; if (!ND_TTEST_SIZE(ap)) { /* Just bail if we don't have the whole chunk. */ nd_print_trunc(ndo); return; } if (length < sizeof(*ap)) { ND_PRINT(" [|aarp %u]", length); return; } if (EXTRACT_BE_U_2(ap->htype) == 1 && EXTRACT_BE_U_2(ap->ptype) == ETHERTYPE_ATALK && EXTRACT_U_1(ap->halen) == 6 && EXTRACT_U_1(ap->palen) == 4 ) switch (EXTRACT_BE_U_2(ap->op)) { case 1: /* request */ ND_PRINT("who-has %s tell %s", AT(pdaddr), AT(psaddr)); return; case 2: /* response */ ND_PRINT("reply %s is-at %s", AT(psaddr), etheraddr_string(ndo, ap->hsaddr)); return; case 3: /* probe (oy!) */ ND_PRINT("probe %s tell %s", AT(pdaddr), AT(psaddr)); return; } ND_PRINT("len %u op %u htype %u ptype %#x halen %u palen %u", length, EXTRACT_BE_U_2(ap->op), EXTRACT_BE_U_2(ap->htype), EXTRACT_BE_U_2(ap->ptype), EXTRACT_U_1(ap->halen), EXTRACT_U_1(ap->palen)); }
void msdp_print(netdissect_options *ndo, const u_char *sp, u_int length) { unsigned int type, len; ndo->ndo_protocol = "msdp"; ND_TCHECK_3(sp); /* See if we think we're at the beginning of a compound packet */ type = EXTRACT_U_1(sp); len = EXTRACT_BE_U_2(sp + 1); if (len > 1500 || len < 3 || type == 0 || type > MSDP_TYPE_MAX) goto trunc; /* not really truncated, but still not decodable */ ND_PRINT(" msdp:"); while (length != 0) { ND_TCHECK_3(sp); type = EXTRACT_U_1(sp); len = EXTRACT_BE_U_2(sp + 1); if (len > 1400 || ndo->ndo_vflag) ND_PRINT(" [len %u]", len); if (len < 3) goto trunc; if (length < len) goto trunc; sp += 3; length -= 3; switch (type) { case 1: /* IPv4 Source-Active */ case 3: /* IPv4 Source-Active Response */ if (type == 1) ND_PRINT(" SA"); else ND_PRINT(" SA-Response"); ND_TCHECK_1(sp); ND_PRINT(" %u entries", EXTRACT_U_1(sp)); if ((u_int)((EXTRACT_U_1(sp) * 12) + 8) < len) { ND_PRINT(" [w/data]"); if (ndo->ndo_vflag > 1) { ND_PRINT(" "); ip_print(ndo, sp + EXTRACT_U_1(sp) * 12 + 8 - 3, len - (EXTRACT_U_1(sp) * 12 + 8)); } } break; case 2: ND_PRINT(" SA-Request"); ND_TCHECK_5(sp); ND_PRINT(" for %s", ipaddr_string(ndo, sp + 1)); break; case 4: ND_PRINT(" Keepalive"); if (len != 3) ND_PRINT("[len=%u] ", len); break; case 5: ND_PRINT(" Notification"); break; default: ND_PRINT(" [type=%u len=%u]", type, len); break; } sp += (len - 3); length -= (len - 3); } return; trunc: nd_print_trunc(ndo); }
void egp_print(netdissect_options *ndo, const uint8_t *bp, u_int length) { const struct egp_packet *egp; u_int version; u_int type; u_int code; u_int status; ndo->ndo_protocol = "egp"; egp = (const struct egp_packet *)bp; if (length < sizeof(*egp) || !ND_TTEST_SIZE(egp)) { ND_PRINT("[|egp]"); return; } version = EXTRACT_U_1(egp->egp_version); if (!ndo->ndo_vflag) { ND_PRINT("EGPv%u, AS %u, seq %u, length %u", version, EXTRACT_BE_U_2(egp->egp_as), EXTRACT_BE_U_2(egp->egp_sequence), length); return; } else ND_PRINT("EGPv%u, length %u", version, length); if (version != EGP_VERSION) { ND_PRINT("[version %u]", version); return; } type = EXTRACT_U_1(egp->egp_type); code = EXTRACT_U_1(egp->egp_code); status = EXTRACT_U_1(egp->egp_status); switch (type) { case EGPT_ACQUIRE: ND_PRINT(" acquire"); switch (code) { case EGPC_REQUEST: case EGPC_CONFIRM: ND_PRINT(" %s", egp_acquire_codes[code]); switch (status) { case EGPS_UNSPEC: case EGPS_ACTIVE: case EGPS_PASSIVE: ND_PRINT(" %s", egp_acquire_status[status]); break; default: ND_PRINT(" [status %u]", status); break; } ND_PRINT(" hello:%u poll:%u", EXTRACT_BE_U_2(egp->egp_hello), EXTRACT_BE_U_2(egp->egp_poll)); break; case EGPC_REFUSE: case EGPC_CEASE: case EGPC_CEASEACK: ND_PRINT(" %s", egp_acquire_codes[code]); switch (status ) { case EGPS_UNSPEC: case EGPS_NORES: case EGPS_ADMIN: case EGPS_GODOWN: case EGPS_PARAM: case EGPS_PROTO: ND_PRINT(" %s", egp_acquire_status[status]); break; default: ND_PRINT("[status %u]", status); break; } break; default: ND_PRINT("[code %u]", code); break; } break; case EGPT_REACH: switch (code) { case EGPC_HELLO: case EGPC_HEARDU: ND_PRINT(" %s", egp_reach_codes[code]); if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); break; default: ND_PRINT("[reach code %u]", code); break; } break; case EGPT_POLL: ND_PRINT(" poll"); if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); ND_PRINT(" net:%s", ipaddr_string(ndo, egp->egp_sourcenet)); break; case EGPT_UPDATE: ND_PRINT(" update"); if (status & EGPS_UNSOL) { status &= ~EGPS_UNSOL; ND_PRINT(" unsolicited"); } if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); ND_PRINT(" %s int %u ext %u", ipaddr_string(ndo, egp->egp_sourcenet), EXTRACT_U_1(egp->egp_intgw), EXTRACT_U_1(egp->egp_extgw)); if (ndo->ndo_vflag) egpnrprint(ndo, egp, length); break; case EGPT_ERROR: ND_PRINT(" error"); if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); if (EXTRACT_BE_U_2(egp->egp_reason) <= EGPR_UVERSION) ND_PRINT(" %s", egp_reasons[EXTRACT_BE_U_2(egp->egp_reason)]); else ND_PRINT(" [reason %u]", EXTRACT_BE_U_2(egp->egp_reason)); break; default: ND_PRINT("[type %u]", type); break; } }
static void dhcp6opt_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { const struct dhcp6opt *dh6o; const u_char *tp; u_int i; uint16_t opttype; uint16_t optlen; uint8_t auth_proto; uint8_t auth_alg; uint8_t auth_rdm; u_int authinfolen, authrealmlen; u_int remain_len; /* Length of remaining options */ u_int label_len; /* Label length */ uint16_t subopt_code; uint16_t subopt_len; uint8_t dh6_reconf_type; uint8_t dh6_lq_query_type; if (cp == ep) return; while (cp < ep) { if (ep < cp + sizeof(*dh6o)) goto trunc; dh6o = (const struct dhcp6opt *)cp; ND_TCHECK_SIZE(dh6o); optlen = EXTRACT_BE_U_2(dh6o->dh6opt_len); if (ep < cp + sizeof(*dh6o) + optlen) goto trunc; opttype = EXTRACT_BE_U_2(dh6o->dh6opt_type); ND_PRINT(" (%s", tok2str(dh6opt_str, "opt_%u", opttype)); ND_TCHECK_LEN(cp + sizeof(*dh6o), optlen); switch (opttype) { case DH6OPT_CLIENTID: case DH6OPT_SERVERID: if (optlen < 2) { /*(*/ ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); switch (EXTRACT_BE_U_2(tp)) { case 1: if (optlen >= 2 + 6) { ND_PRINT(" hwaddr/time type %u time %u ", EXTRACT_BE_U_2(tp + 2), EXTRACT_BE_U_4(tp + 4)); for (i = 8; i < optlen; i++) ND_PRINT("%02x", EXTRACT_U_1(tp + i)); /*(*/ ND_PRINT(")"); } else { /*(*/ ND_PRINT(" ?)"); } break; case 2: if (optlen >= 2 + 8) { ND_PRINT(" vid "); for (i = 2; i < 2 + 8; i++) ND_PRINT("%02x", EXTRACT_U_1(tp + i)); /*(*/ ND_PRINT(")"); } else { /*(*/ ND_PRINT(" ?)"); } break; case 3: if (optlen >= 2 + 2) { ND_PRINT(" hwaddr type %u ", EXTRACT_BE_U_2(tp + 2)); for (i = 4; i < optlen; i++) ND_PRINT("%02x", EXTRACT_U_1(tp + i)); /*(*/ ND_PRINT(")"); } else { /*(*/ ND_PRINT(" ?)"); } break; default: ND_PRINT(" type %u)", EXTRACT_BE_U_2(tp)); break; } break; case DH6OPT_IA_ADDR: if (optlen < 24) { /*(*/ ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %s", ip6addr_string(ndo, tp)); ND_PRINT(" pltime:%u vltime:%u", EXTRACT_BE_U_4(tp + 16), EXTRACT_BE_U_4(tp + 20)); if (optlen > 24) { /* there are sub-options */ dhcp6opt_print(ndo, tp + 24, tp + optlen); } ND_PRINT(")"); break; case DH6OPT_ORO: case DH6OPT_ERO: if (optlen % 2) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); for (i = 0; i < optlen; i += 2) { ND_PRINT(" %s", tok2str(dh6opt_str, "opt_%u", EXTRACT_BE_U_2(tp + i))); } ND_PRINT(")"); break; case DH6OPT_PREFERENCE: if (optlen != 1) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %u)", EXTRACT_U_1(tp)); break; case DH6OPT_ELAPSED_TIME: if (optlen != 2) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %u)", EXTRACT_BE_U_2(tp)); break; case DH6OPT_RELAY_MSG: ND_PRINT(" ("); tp = (const u_char *)(dh6o + 1); dhcp6_print(ndo, tp, optlen); ND_PRINT(")"); break; case DH6OPT_AUTH: if (optlen < 11) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); auth_proto = EXTRACT_U_1(tp); switch (auth_proto) { case DH6OPT_AUTHPROTO_DELAYED: ND_PRINT(" proto: delayed"); break; case DH6OPT_AUTHPROTO_RECONFIG: ND_PRINT(" proto: reconfigure"); break; default: ND_PRINT(" proto: %u", auth_proto); break; } tp++; auth_alg = EXTRACT_U_1(tp); switch (auth_alg) { case DH6OPT_AUTHALG_HMACMD5: /* XXX: may depend on the protocol */ ND_PRINT(", alg: HMAC-MD5"); break; default: ND_PRINT(", alg: %u", auth_alg); break; } tp++; auth_rdm = EXTRACT_U_1(tp); switch (auth_rdm) { case DH6OPT_AUTHRDM_MONOCOUNTER: ND_PRINT(", RDM: mono"); break; default: ND_PRINT(", RDM: %u", auth_rdm); break; } tp++; ND_PRINT(", RD:"); for (i = 0; i < 4; i++, tp += 2) ND_PRINT(" %04x", EXTRACT_BE_U_2(tp)); /* protocol dependent part */ authinfolen = optlen - 11; switch (auth_proto) { case DH6OPT_AUTHPROTO_DELAYED: if (authinfolen == 0) break; if (authinfolen < 20) { ND_PRINT(" ??"); break; } authrealmlen = authinfolen - 20; if (authrealmlen > 0) { ND_PRINT(", realm: "); } for (i = 0; i < authrealmlen; i++, tp++) ND_PRINT("%02x", EXTRACT_U_1(tp)); ND_PRINT(", key ID: %08x", EXTRACT_BE_U_4(tp)); tp += 4; ND_PRINT(", HMAC-MD5:"); for (i = 0; i < 4; i++, tp+= 4) ND_PRINT(" %08x", EXTRACT_BE_U_4(tp)); break; case DH6OPT_AUTHPROTO_RECONFIG: if (authinfolen != 17) { ND_PRINT(" ??"); break; } switch (EXTRACT_U_1(tp)) { case DH6OPT_AUTHRECONFIG_KEY: ND_PRINT(" reconfig-key"); break; case DH6OPT_AUTHRECONFIG_HMACMD5: ND_PRINT(" type: HMAC-MD5"); break; default: ND_PRINT(" type: ??"); break; } tp++; ND_PRINT(" value:"); for (i = 0; i < 4; i++, tp+= 4) ND_PRINT(" %08x", EXTRACT_BE_U_4(tp)); break; default: ND_PRINT(" ??"); break; } ND_PRINT(")"); break; case DH6OPT_RAPID_COMMIT: /* nothing todo */ ND_PRINT(")"); break; case DH6OPT_INTERFACE_ID: case DH6OPT_SUBSCRIBER_ID: /* * Since we cannot predict the encoding, print hex dump * at most 10 characters. */ tp = (const u_char *)(dh6o + 1); ND_PRINT(" "); for (i = 0; i < optlen && i < 10; i++) ND_PRINT("%02x", EXTRACT_U_1(tp + i)); ND_PRINT("...)"); break; case DH6OPT_RECONF_MSG: if (optlen != 1) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); dh6_reconf_type = EXTRACT_U_1(tp); switch (dh6_reconf_type) { case DH6_RENEW: ND_PRINT(" for renew)"); break; case DH6_INFORM_REQ: ND_PRINT(" for inf-req)"); break; default: ND_PRINT(" for ?\?\?(%02x))", dh6_reconf_type); break; } break; case DH6OPT_RECONF_ACCEPT: /* nothing todo */ ND_PRINT(")"); break; case DH6OPT_SIP_SERVER_A: case DH6OPT_DNS_SERVERS: case DH6OPT_SNTP_SERVERS: case DH6OPT_NIS_SERVERS: case DH6OPT_NISP_SERVERS: case DH6OPT_BCMCS_SERVER_A: case DH6OPT_PANA_AGENT: case DH6OPT_LQ_CLIENT_LINK: if (optlen % 16) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); for (i = 0; i < optlen; i += 16) ND_PRINT(" %s", ip6addr_string(ndo, tp + i)); ND_PRINT(")"); break; case DH6OPT_SIP_SERVER_D: case DH6OPT_DOMAIN_LIST: tp = (const u_char *)(dh6o + 1); while (tp < cp + sizeof(*dh6o) + optlen) { ND_PRINT(" "); if ((tp = ns_nprint(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL) goto trunc; } ND_PRINT(")"); break; case DH6OPT_STATUS_CODE: if (optlen < 2) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %s)", dhcp6stcode(EXTRACT_BE_U_2(tp))); break; case DH6OPT_IA_NA: case DH6OPT_IA_PD: if (optlen < 12) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" IAID:%u T1:%u T2:%u", EXTRACT_BE_U_4(tp), EXTRACT_BE_U_4(tp + 4), EXTRACT_BE_U_4(tp + 8)); if (optlen > 12) { /* there are sub-options */ dhcp6opt_print(ndo, tp + 12, tp + optlen); } ND_PRINT(")"); break; case DH6OPT_IA_TA: if (optlen < 4) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" IAID:%u", EXTRACT_BE_U_4(tp)); if (optlen > 4) { /* there are sub-options */ dhcp6opt_print(ndo, tp + 4, tp + optlen); } ND_PRINT(")"); break; case DH6OPT_IA_PD_PREFIX: if (optlen < 25) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %s/%u", ip6addr_string(ndo, tp + 9), EXTRACT_U_1(tp + 8)); ND_PRINT(" pltime:%u vltime:%u", EXTRACT_BE_U_4(tp), EXTRACT_BE_U_4(tp + 4)); if (optlen > 25) { /* there are sub-options */ dhcp6opt_print(ndo, tp + 25, tp + optlen); } ND_PRINT(")"); break; case DH6OPT_LIFETIME: case DH6OPT_CLT_TIME: if (optlen != 4) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %u)", EXTRACT_BE_U_4(tp)); break; case DH6OPT_REMOTE_ID: if (optlen < 4) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %u ", EXTRACT_BE_U_4(tp)); /* * Print hex dump first 10 characters. */ for (i = 4; i < optlen && i < 14; i++) ND_PRINT("%02x", EXTRACT_U_1(tp + i)); ND_PRINT("...)"); break; case DH6OPT_LQ_QUERY: if (optlen < 17) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); dh6_lq_query_type = EXTRACT_U_1(tp); switch (dh6_lq_query_type) { case 1: ND_PRINT(" by-address"); break; case 2: ND_PRINT(" by-clientID"); break; default: ND_PRINT(" type_%u", dh6_lq_query_type); break; } ND_PRINT(" %s", ip6addr_string(ndo, tp + 1)); if (optlen > 17) { /* there are query-options */ dhcp6opt_print(ndo, tp + 17, tp + optlen); } ND_PRINT(")"); break; case DH6OPT_CLIENT_DATA: tp = (const u_char *)(dh6o + 1); if (optlen > 0) { /* there are encapsulated options */ dhcp6opt_print(ndo, tp, tp + optlen); } ND_PRINT(")"); break; case DH6OPT_LQ_RELAY_DATA: if (optlen < 16) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT(" %s ", ip6addr_string(ndo, tp)); /* * Print hex dump first 10 characters. */ for (i = 16; i < optlen && i < 26; i++) ND_PRINT("%02x", EXTRACT_U_1(tp + i)); ND_PRINT("...)"); break; case DH6OPT_NTP_SERVER: if (optlen < 4) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); while (tp < cp + sizeof(*dh6o) + optlen - 4) { subopt_code = EXTRACT_BE_U_2(tp); tp += 2; subopt_len = EXTRACT_BE_U_2(tp); tp += 2; if (tp + subopt_len > cp + sizeof(*dh6o) + optlen) goto trunc; ND_PRINT(" subopt:%u", subopt_code); switch (subopt_code) { case DH6OPT_NTP_SUBOPTION_SRV_ADDR: case DH6OPT_NTP_SUBOPTION_MC_ADDR: if (subopt_len != 16) { ND_PRINT(" ?"); break; } ND_PRINT(" %s", ip6addr_string(ndo, tp)); break; case DH6OPT_NTP_SUBOPTION_SRV_FQDN: ND_PRINT(" "); if (ns_nprint(ndo, tp, tp + subopt_len) == NULL) goto trunc; break; default: ND_PRINT(" ?"); break; } tp += subopt_len; } ND_PRINT(")"); break; case DH6OPT_AFTR_NAME: if (optlen < 3) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); remain_len = optlen; ND_PRINT(" "); /* Encoding is described in section 3.1 of RFC 1035 */ while (remain_len && EXTRACT_U_1(tp)) { label_len = EXTRACT_U_1(tp); tp++; if (label_len < remain_len - 1) { (void)fn_printn(ndo, tp, label_len, NULL); tp += label_len; remain_len -= (label_len + 1); if(EXTRACT_U_1(tp)) ND_PRINT("."); } else { ND_PRINT(" ?"); break; } } ND_PRINT(")"); break; case DH6OPT_NEW_POSIX_TIMEZONE: /* all three of these options */ case DH6OPT_NEW_TZDB_TIMEZONE: /* are encoded similarly */ case DH6OPT_MUDURL: /* although GMT might not work */ if (optlen < 5) { ND_PRINT(" ?)"); break; } tp = (const u_char *)(dh6o + 1); ND_PRINT("="); (void)fn_printn(ndo, tp, (u_int)optlen, NULL); ND_PRINT(")"); break; default: ND_PRINT(")"); break; } cp += sizeof(*dh6o) + optlen; } return; trunc: ND_PRINT("[|dhcp6ext]"); }
static int stp_print_mstp_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu, u_int length) { const u_char *ptr; uint8_t bpdu_flags; uint16_t v3len; uint16_t len; uint16_t msti; u_int offset; ptr = (const u_char *)stp_bpdu; ND_TCHECK_1(stp_bpdu->flags); bpdu_flags = EXTRACT_U_1(stp_bpdu->flags); ND_PRINT(", CIST Flags [%s], length %u", bittok2str(stp_bpdu_flag_values, "none", bpdu_flags), length); /* * in non-verbose mode just print the flags. */ if (!ndo->ndo_vflag) { return 1; } ND_PRINT("\n\tport-role %s, ", tok2str(rstp_obj_port_role_values, "Unknown", RSTP_EXTRACT_PORT_ROLE(bpdu_flags))); ND_TCHECK_4(stp_bpdu->root_path_cost); ND_PRINT("CIST root-id %s, CIST ext-pathcost %u", stp_print_bridge_id((const u_char *)&stp_bpdu->root_id), EXTRACT_BE_U_4(stp_bpdu->root_path_cost)); ND_TCHECK_SIZE(&stp_bpdu->bridge_id); ND_PRINT("\n\tCIST regional-root-id %s, ", stp_print_bridge_id((const u_char *)&stp_bpdu->bridge_id)); ND_TCHECK_2(stp_bpdu->port_id); ND_PRINT("CIST port-id %04x,", EXTRACT_BE_U_2(stp_bpdu->port_id)); ND_TCHECK_2(stp_bpdu->forward_delay); ND_PRINT("\n\tmessage-age %.2fs, max-age %.2fs" ", hello-time %.2fs, forwarding-delay %.2fs", (float) EXTRACT_BE_U_2(stp_bpdu->message_age) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->max_age) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->hello_time) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->forward_delay) / STP_TIME_BASE); ND_TCHECK_2(ptr + MST_BPDU_VER3_LEN_OFFSET); ND_PRINT("\n\tv3len %u, ", EXTRACT_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET)); ND_TCHECK_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 12); ND_PRINT("MCID Name "); if (fn_printzp(ndo, ptr + MST_BPDU_CONFIG_NAME_OFFSET, 32, ndo->ndo_snapend)) goto trunc; ND_PRINT(", rev %u," "\n\t\tdigest %08x%08x%08x%08x, ", EXTRACT_BE_U_2(ptr + MST_BPDU_CONFIG_NAME_OFFSET + 32), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 4), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 8), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 12)); ND_TCHECK_4(ptr + MST_BPDU_CIST_INT_PATH_COST_OFFSET); ND_PRINT("CIST int-root-pathcost %u,", EXTRACT_BE_U_4(ptr + MST_BPDU_CIST_INT_PATH_COST_OFFSET)); ND_TCHECK_BRIDGE_ID(ptr + MST_BPDU_CIST_BRIDGE_ID_OFFSET); ND_PRINT("\n\tCIST bridge-id %s, ", stp_print_bridge_id(ptr + MST_BPDU_CIST_BRIDGE_ID_OFFSET)); ND_TCHECK_1(ptr + MST_BPDU_CIST_REMAIN_HOPS_OFFSET); ND_PRINT("CIST remaining-hops %u", EXTRACT_U_1(ptr + MST_BPDU_CIST_REMAIN_HOPS_OFFSET)); /* Dump all MSTI's */ ND_TCHECK_2(ptr + MST_BPDU_VER3_LEN_OFFSET); v3len = EXTRACT_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET); if (v3len > MST_BPDU_CONFIG_INFO_LENGTH) { len = v3len - MST_BPDU_CONFIG_INFO_LENGTH; offset = MST_BPDU_MSTI_OFFSET; while (len >= MST_BPDU_MSTI_LENGTH) { ND_TCHECK_LEN(ptr + offset, MST_BPDU_MSTI_LENGTH); msti = EXTRACT_BE_U_2(ptr + offset + MST_BPDU_MSTI_ROOT_PRIO_OFFSET); msti = msti & 0x0FFF; ND_PRINT("\n\tMSTI %u, Flags [%s], port-role %s", msti, bittok2str(stp_bpdu_flag_values, "none", EXTRACT_U_1(ptr + offset)), tok2str(rstp_obj_port_role_values, "Unknown", RSTP_EXTRACT_PORT_ROLE(EXTRACT_U_1(ptr + offset)))); ND_PRINT("\n\t\tMSTI regional-root-id %s, pathcost %u", stp_print_bridge_id(ptr + offset + MST_BPDU_MSTI_ROOT_PRIO_OFFSET), EXTRACT_BE_U_4(ptr + offset + MST_BPDU_MSTI_ROOT_PATH_COST_OFFSET)); ND_PRINT("\n\t\tMSTI bridge-prio %u, port-prio %u, hops %u", EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_BRIDGE_PRIO_OFFSET) >> 4, EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_PORT_PRIO_OFFSET) >> 4, EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_REMAIN_HOPS_OFFSET)); len -= MST_BPDU_MSTI_LENGTH; offset += MST_BPDU_MSTI_LENGTH; } }
static int ldp_pdu_print(netdissect_options *ndo, const u_char *pptr) { const struct ldp_common_header *ldp_com_header; const struct ldp_msg_header *ldp_msg_header; const u_char *tptr,*msg_tptr; u_short tlen; u_short pdu_len,msg_len,msg_type,msg_tlen; int hexdump,processed; ldp_com_header = (const struct ldp_common_header *)pptr; ND_TCHECK_SIZE(ldp_com_header); /* * Sanity checking of the header. */ if (EXTRACT_BE_U_2(ldp_com_header->version) != LDP_VERSION) { ND_PRINT("%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", EXTRACT_BE_U_2(ldp_com_header->version)); return 0; } pdu_len = EXTRACT_BE_U_2(ldp_com_header->pdu_length); if (pdu_len < sizeof(struct ldp_common_header)-4) { /* length too short */ ND_PRINT("%sLDP, pdu-length: %u (too short, < %u)", (ndo->ndo_vflag < 1) ? "" : "\n\t", pdu_len, (u_int)(sizeof(struct ldp_common_header)-4)); return 0; } /* print the LSR-ID, label-space & length */ ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", (ndo->ndo_vflag < 1) ? "" : "\n\t", ipaddr_string(ndo, &ldp_com_header->lsr_id), EXTRACT_BE_U_2(ldp_com_header->label_space), pdu_len); /* bail out if non-verbose */ if (ndo->ndo_vflag < 1) return 0; /* ok they seem to want to know everything - lets fully decode it */ tptr = pptr + sizeof(struct ldp_common_header); tlen = pdu_len - (sizeof(struct ldp_common_header)-4); /* Type & Length fields not included */ while(tlen>0) { /* did we capture enough for fully decoding the msg header ? */ ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; msg_len=EXTRACT_BE_U_2(ldp_msg_header->length); msg_type=LDP_MASK_MSG_TYPE(EXTRACT_BE_U_2(ldp_msg_header->type)); if (msg_len < sizeof(struct ldp_msg_header)-4) { /* length too short */ /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u (too short, < %u)", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, (u_int)(sizeof(struct ldp_msg_header)-4)); return 0; } /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, EXTRACT_BE_U_4(ldp_msg_header->id), LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore"); msg_tptr=tptr+sizeof(struct ldp_msg_header); msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */ /* did we capture enough for fully decoding the message ? */ ND_TCHECK_LEN(tptr, msg_len); hexdump=FALSE; switch(msg_type) { case LDP_MSG_NOTIF: case LDP_MSG_HELLO: case LDP_MSG_INIT: case LDP_MSG_KEEPALIVE: case LDP_MSG_ADDRESS: case LDP_MSG_LABEL_MAPPING: case LDP_MSG_ADDRESS_WITHDRAW: case LDP_MSG_LABEL_WITHDRAW: while(msg_tlen >= 4) { processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen); if (processed == 0) break; msg_tlen-=processed; msg_tptr+=processed; } break; /* * FIXME those are the defined messages that lack a decoder * you are welcome to contribute code ;-) */ case LDP_MSG_LABEL_REQUEST: case LDP_MSG_LABEL_RELEASE: case LDP_MSG_LABEL_ABORT_REQUEST: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen); break; } /* do we want to see an additionally hexdump ? */ if (ndo->ndo_vflag > 1 || hexdump==TRUE) print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t ", msg_len); tptr += msg_len+4; tlen -= msg_len+4; } return pdu_len+4; trunc: ND_PRINT("\n\t\t packet exceeded snapshot"); return 0; }
static int ldp_tlv_print(netdissect_options *ndo, const u_char *tptr, u_short msg_tlen) { struct ldp_tlv_header { nd_uint16_t type; nd_uint16_t length; }; const struct ldp_tlv_header *ldp_tlv_header; u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; u_char fec_type; u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; char buf[100]; int i; ldp_tlv_header = (const struct ldp_tlv_header *)tptr; ND_TCHECK_SIZE(ldp_tlv_header); tlv_len=EXTRACT_BE_U_2(ldp_tlv_header->length); if (tlv_len + 4 > msg_tlen) { ND_PRINT("\n\t\t TLV contents go past end of message"); return 0; } tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_BE_U_2(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", tok2str(ldp_tlv_values, "Unknown", tlv_type), tlv_type, tlv_len, LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore", LDP_MASK_F_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't"); tptr+=sizeof(struct ldp_tlv_header); switch(tlv_type) { case LDP_TLV_COMMON_HELLO: TLV_TCHECK(4); ND_PRINT("\n\t Hold Time: %us, Flags: [%s Hello%s]", EXTRACT_BE_U_2(tptr), (EXTRACT_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link", (EXTRACT_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : ""); break; case LDP_TLV_IPV4_TRANSPORT_ADDR: TLV_TCHECK(4); ND_PRINT("\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr)); break; case LDP_TLV_IPV6_TRANSPORT_ADDR: TLV_TCHECK(16); ND_PRINT("\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr)); break; case LDP_TLV_CONFIG_SEQ_NUMBER: TLV_TCHECK(4); ND_PRINT("\n\t Sequence Number: %u", EXTRACT_BE_U_4(tptr)); break; case LDP_TLV_ADDRESS_LIST: TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = EXTRACT_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; ND_PRINT("\n\t Address Family: %s, addresses", tok2str(af_values, "Unknown (%u)", af)); switch (af) { case AFNUM_INET: while(tlv_tlen >= sizeof(struct in_addr)) { ND_TCHECK_LEN(tptr, sizeof(struct in_addr)); ND_PRINT(" %s", ipaddr_string(ndo, tptr)); tlv_tlen-=sizeof(struct in_addr); tptr+=sizeof(struct in_addr); } break; case AFNUM_INET6: while(tlv_tlen >= sizeof(struct in6_addr)) { ND_TCHECK_LEN(tptr, sizeof(struct in6_addr)); ND_PRINT(" %s", ip6addr_string(ndo, tptr)); tlv_tlen-=sizeof(struct in6_addr); tptr+=sizeof(struct in6_addr); } break; default: /* unknown AF */ break; } break; case LDP_TLV_COMMON_SESSION: TLV_TCHECK(8); ND_PRINT("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", EXTRACT_BE_U_2(tptr), EXTRACT_BE_U_2(tptr + 2), (EXTRACT_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited", (EXTRACT_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled" ); break; case LDP_TLV_FEC: TLV_TCHECK(1); fec_type = EXTRACT_U_1(tptr); ND_PRINT("\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), fec_type); tptr+=1; tlv_tlen-=1; switch(fec_type) { case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: TLV_TCHECK(2); af = EXTRACT_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; if (af == AFNUM_INET) { i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv4 prefix (invalid length)"); else ND_PRINT(": IPv4 prefix %s", buf); } else if (af == AFNUM_INET6) { i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv6 prefix (invalid length)"); else ND_PRINT(": IPv6 prefix %s", buf); } else ND_PRINT(": Address family %u prefix", af); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: /* * We assume the type was supposed to be one of the MPLS * Pseudowire Types. */ TLV_TCHECK(7); vc_info_len = EXTRACT_U_1(tptr + 2); /* * According to RFC 4908, the VC info Length field can be zero, * in which case not only are there no interface parameters, * there's no VC ID. */ if (vc_info_len == 0) { ND_PRINT(": %s, %scontrol word, group-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", EXTRACT_BE_U_4(tptr + 3), vc_info_len); break; } /* Make sure we have the VC ID as well */ TLV_TCHECK(11); ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", EXTRACT_BE_U_4(tptr + 3), EXTRACT_BE_U_4(tptr + 7), vc_info_len); if (vc_info_len < 4) { /* minimum 4, for the VC ID */ ND_PRINT(" (invalid, < 4"); return(tlv_len+4); /* Type & Length fields not included */ } vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ /* Skip past the fixed information and the VC ID */ tptr+=11; tlv_tlen-=11; TLV_TCHECK(vc_info_len); while (vc_info_len > 2) { vc_info_tlv_type = EXTRACT_U_1(tptr); vc_info_tlv_len = EXTRACT_U_1(tptr + 1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) break; ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u", tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), vc_info_tlv_type, vc_info_tlv_len); switch(vc_info_tlv_type) { case LDP_FEC_MARTINI_IFPARM_MTU: ND_PRINT(": %u", EXTRACT_BE_U_2(tptr + 2)); break; case LDP_FEC_MARTINI_IFPARM_DESC: ND_PRINT(": "); for (idx = 2; idx < vc_info_tlv_len; idx++) safeputchar(ndo, EXTRACT_U_1(tptr + idx)); break; case LDP_FEC_MARTINI_IFPARM_VCCV: ND_PRINT("\n\t\t Control Channels (0x%02x) = [%s]", EXTRACT_U_1((tptr + 2)), bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", EXTRACT_U_1((tptr + 2)))); ND_PRINT("\n\t\t CV Types (0x%02x) = [%s]", EXTRACT_U_1((tptr + 3)), bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", EXTRACT_U_1((tptr + 3)))); break; default: print_unknown_data(ndo, tptr+2, "\n\t\t ", vc_info_tlv_len-2); break; } vc_info_len -= vc_info_tlv_len; tptr += vc_info_tlv_len; } break; } break; case LDP_TLV_GENERIC_LABEL: TLV_TCHECK(4); ND_PRINT("\n\t Label: %u", EXTRACT_BE_U_4(tptr) & 0xfffff); break; case LDP_TLV_STATUS: TLV_TCHECK(8); ui = EXTRACT_BE_U_4(tptr); tptr+=4; ND_PRINT("\n\t Status: 0x%02x, Flags: [%s and %s forward]", ui&0x3fffffff, ui&0x80000000 ? "Fatal error" : "Advisory Notification", ui&0x40000000 ? "do" : "don't"); ui = EXTRACT_BE_U_4(tptr); tptr+=4; if (ui) ND_PRINT(", causing Message ID: 0x%08x", ui); break; case LDP_TLV_FT_SESSION: TLV_TCHECK(8); ft_flags = EXTRACT_BE_U_2(tptr); ND_PRINT("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", ft_flags&0x8000 ? "" : "No ", ft_flags&0x8 ? "" : "Don't ", ft_flags&0x4 ? "" : "No ", ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", ft_flags&0x1 ? "" : "Don't "); tptr+=4; ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT(", Reconnect Timeout: %ums", ui); tptr+=4; ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT(", Recovery Time: %ums", ui); break; case LDP_TLV_MTU: TLV_TCHECK(2); ND_PRINT("\n\t MTU: %u", EXTRACT_BE_U_2(tptr)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case LDP_TLV_HOP_COUNT: case LDP_TLV_PATH_VECTOR: case LDP_TLV_ATM_LABEL: case LDP_TLV_FR_LABEL: case LDP_TLV_EXTD_STATUS: case LDP_TLV_RETURNED_PDU: case LDP_TLV_RETURNED_MSG: case LDP_TLV_ATM_SESSION_PARM: case LDP_TLV_FR_SESSION_PARM: case LDP_TLV_LABEL_REQUEST_MSG_ID: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlv_tlen); break; } return(tlv_len+4); /* Type & Length fields not included */ trunc: ND_PRINT("\n\t\t packet exceeded snapshot"); return 0; badtlv: ND_PRINT("\n\t\t TLV contents go past end of TLV"); return(tlv_len+4); /* Type & Length fields not included */ }
u_int chdlc_print(netdissect_options *ndo, const u_char *p, u_int length) { u_int proto; const u_char *bp = p; if (length < CHDLC_HDRLEN) goto trunc; ND_TCHECK_LEN(p, CHDLC_HDRLEN); proto = EXTRACT_BE_U_2(p + 2); if (ndo->ndo_eflag) { ND_PRINT("%s, ethertype %s (0x%04x), length %u: ", tok2str(chdlc_cast_values, "0x%02x", EXTRACT_U_1(p)), tok2str(ethertype_values, "Unknown", proto), proto, length); } length -= CHDLC_HDRLEN; p += CHDLC_HDRLEN; switch (proto) { case ETHERTYPE_IP: ip_print(ndo, p, length); break; case ETHERTYPE_IPV6: ip6_print(ndo, p, length); break; case CHDLC_TYPE_SLARP: chdlc_slarp_print(ndo, p, length); break; #if 0 case CHDLC_TYPE_CDP: chdlc_cdp_print(p, length); break; #endif case ETHERTYPE_MPLS: case ETHERTYPE_MPLS_MULTI: mpls_print(ndo, p, length); break; case ETHERTYPE_ISO: /* is the fudge byte set ? lets verify by spotting ISO headers */ if (length < 2) goto trunc; ND_TCHECK_2(p); if (EXTRACT_U_1(p + 1) == NLPID_CLNP || EXTRACT_U_1(p + 1) == NLPID_ESIS || EXTRACT_U_1(p + 1) == NLPID_ISIS) isoclns_print(ndo, p + 1, length - 1); else isoclns_print(ndo, p, length); break; default: if (!ndo->ndo_eflag) ND_PRINT("unknown CHDLC protocol (0x%04x)", proto); break; } return (CHDLC_HDRLEN); trunc: ND_PRINT("[|chdlc]"); return ndo->ndo_snapend - bp; }
static void chdlc_slarp_print(netdissect_options *ndo, const u_char *cp, u_int length) { const struct cisco_slarp *slarp; u_int sec,min,hrs,days; ND_PRINT("SLARP (length: %u), ",length); if (length < SLARP_MIN_LEN) goto trunc; slarp = (const struct cisco_slarp *)cp; ND_TCHECK_LEN(slarp, SLARP_MIN_LEN); switch (EXTRACT_BE_U_4(slarp->code)) { case SLARP_REQUEST: ND_PRINT("request"); /* * At least according to William "Chops" Westfield's * message in * * http://www.nethelp.no/net/cisco-hdlc.txt * * the address and mask aren't used in requests - * they're just zero. */ break; case SLARP_REPLY: ND_PRINT("reply %s/%s", ipaddr_string(ndo, slarp->un.addr.addr), ipaddr_string(ndo, slarp->un.addr.mask)); break; case SLARP_KEEPALIVE: ND_PRINT("keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x", EXTRACT_BE_U_4(slarp->un.keep.myseq), EXTRACT_BE_U_4(slarp->un.keep.yourseq), EXTRACT_BE_U_2(slarp->un.keep.rel)); if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */ cp += SLARP_MIN_LEN; ND_TCHECK_4(cp); sec = EXTRACT_BE_U_4(cp) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; ND_PRINT(", link uptime=%ud%uh%um%us",days,hrs,min,sec); } break; default: ND_PRINT("0x%02x unknown", EXTRACT_BE_U_4(slarp->code)); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo,cp+4,"\n\t",length-4); break; } if (SLARP_MAX_LEN < length && ndo->ndo_vflag) ND_PRINT(", (trailing junk: %u bytes)", length - SLARP_MAX_LEN); if (ndo->ndo_vflag > 1) print_unknown_data(ndo,cp+4,"\n\t",length-4); return; trunc: ND_PRINT("[|slarp]"); }
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); }