static int print_neighbors2(netdissect_options *ndo, register const u_char *bp, register const u_char *ep, register u_int len) { const u_char *laddr; register u_char metric, thresh, flags; register int ncount; ND_PRINT((ndo, " (v %d.%d):", (int)target_level & 0xff, (int)(target_level >> 8) & 0xff)); while (len > 0 && bp < ep) { ND_TCHECK2(bp[0], 8); laddr = bp; bp += 4; metric = *bp++; thresh = *bp++; flags = *bp++; ncount = *bp++; len -= 8; while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) { ND_PRINT((ndo, " [%s -> ", ipaddr_string(ndo, laddr))); ND_PRINT((ndo, "%s (%d/%d", ipaddr_string(ndo, bp), metric, thresh)); if (flags & DVMRP_NF_TUNNEL) ND_PRINT((ndo, "/tunnel")); if (flags & DVMRP_NF_SRCRT) ND_PRINT((ndo, "/srcrt")); if (flags & DVMRP_NF_QUERIER) ND_PRINT((ndo, "/querier")); if (flags & DVMRP_NF_DISABLED) ND_PRINT((ndo, "/disabled")); if (flags & DVMRP_NF_DOWN) ND_PRINT((ndo, "/down")); ND_PRINT((ndo, ")]")); bp += 4; len -= 4; } if (ncount != -1) { ND_PRINT((ndo, " [|]")); return (0); } } return (0); trunc: return (-1); }
static int ospf6_print_lsaprefix(netdissect_options *ndo, const uint8_t *tptr, u_int lsa_length) { const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr; u_int wordlen; struct in6_addr prefix; if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES) goto trunc; lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES; ND_TCHECK2(*lsapp, sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES); wordlen = (lsapp->lsa_p_len + 31) / 32; if (wordlen * 4 > sizeof(struct in6_addr)) { ND_PRINT((ndo, " bogus prefixlen /%d", lsapp->lsa_p_len)); goto trunc; } if (lsa_length < wordlen * 4) goto trunc; lsa_length -= wordlen * 4; ND_TCHECK2(lsapp->lsa_p_prefix, wordlen * 4); memset(&prefix, 0, sizeof(prefix)); memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4); ND_PRINT((ndo, "\n\t\t%s/%d", ip6addr_string(ndo, &prefix), lsapp->lsa_p_len)); if (lsapp->lsa_p_opt) { ND_PRINT((ndo, ", Options [%s]", bittok2str(ospf6_lsa_prefix_option_values, "none", lsapp->lsa_p_opt))); } ND_PRINT((ndo, ", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric))); return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4; trunc: return -1; }
/* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Parameter Tag | Parameter Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \ \ * / Parameter Value / * \ \ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static void m3ua_tags_print(netdissect_options *ndo, const u_char *buf, const u_int size) { const u_char *p = buf; int align; uint16_t hdr_tag; uint16_t hdr_len; while (p < buf + size) { if (p + sizeof(struct m3ua_param_header) > buf + size) goto corrupt; ND_TCHECK2(*p, sizeof(struct m3ua_param_header)); /* Parameter Tag */ hdr_tag = EXTRACT_16BITS(p); ND_PRINT((ndo, "\n\t\t\t%s: ", tok2str(ParamName, "Unknown Parameter (0x%04x)", hdr_tag))); /* Parameter Length */ hdr_len = EXTRACT_16BITS(p + 2); if (hdr_len < sizeof(struct m3ua_param_header)) goto corrupt; /* Parameter Value */ align = (p + hdr_len - buf) % 4; align = align ? 4 - align : 0; ND_TCHECK2(*p, hdr_len + align); tag_value_print(ndo, p, hdr_tag, hdr_len - sizeof(struct m3ua_param_header)); p += hdr_len + align; } return; corrupt: ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*buf, size); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
/* cp points to the Ver/Flags octet */ static void aoev1_print(netdissect_options *ndo, const u_char *cp, const u_int len) { const u_char *ep = cp + len; uint8_t flags, command; void (*cmd_decoder)(netdissect_options *, const u_char *, const u_int); if (len < AOEV1_COMMON_HDR_LEN) goto invalid; /* Flags */ flags = *cp & 0x0F; ND_PRINT((ndo, ", Flags: [%s]", bittok2str(aoev1_flag_str, "none", flags))); cp += 1; if (! ndo->ndo_vflag) return; /* Error */ ND_TCHECK2(*cp, 1); if (flags & AOEV1_FLAG_E) ND_PRINT((ndo, "\n\tError: %s", tok2str(aoev1_errcode_str, "Invalid (%u)", *cp))); cp += 1; /* Major */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\tMajor: 0x%04x", EXTRACT_16BITS(cp))); cp += 2; /* Minor */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", Minor: 0x%02x", *cp)); cp += 1; /* Command */ ND_TCHECK2(*cp, 1); command = *cp; cp += 1; ND_PRINT((ndo, ", Command: %s", tok2str(cmdcode_str, "Unknown (0x%02x)", command))); /* Tag */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", Tag: 0x%08x", EXTRACT_32BITS(cp))); cp += 4; /* Arg */ cmd_decoder = command == AOEV1_CMD_ISSUE_ATA_COMMAND ? aoev1_issue_print : command == AOEV1_CMD_QUERY_CONFIG_INFORMATION ? aoev1_query_print : command == AOEV1_CMD_MAC_MASK_LIST ? aoev1_mac_print : command == AOEV1_CMD_RESERVE_RELEASE ? aoev1_reserve_print : NULL; if (cmd_decoder != NULL) cmd_decoder(ndo, cp, len - AOEV1_COMMON_HDR_LEN); return; invalid: ND_PRINT((ndo, "%s", istr)); ND_TCHECK2(*cp, ep - cp); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
static void loopback_message_print(netdissect_options *ndo, const u_char *cp, const u_int len) { const u_char *ep = cp + len; uint16_t function; if (len < 2) goto corrupt; /* function */ ND_TCHECK2(*cp, 2); function = EXTRACT_LE_16BITS(cp); cp += 2; ND_PRINT((ndo, ", %s", tok2str(fcode_str, " invalid (%u)", function))); switch (function) { case LOOPBACK_REPLY: if (len < 4) goto corrupt; /* receipt number */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", receipt number %u", EXTRACT_LE_16BITS(cp))); cp += 2; /* data */ ND_PRINT((ndo, ", data (%u octets)", len - 4)); ND_TCHECK2(*cp, len - 4); break; case LOOPBACK_FWDDATA: if (len < 8) goto corrupt; /* forwarding address */ ND_TCHECK2(*cp, ETHER_ADDR_LEN); ND_PRINT((ndo, ", forwarding address %s", etheraddr_string(cp))); cp += ETHER_ADDR_LEN; /* data */ ND_PRINT((ndo, ", data (%u octets)", len - 8)); ND_TCHECK2(*cp, len - 8); break; default: ND_TCHECK2(*cp, len - 2); break; } return; corrupt: ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp, ep - cp); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
void radius_print(netdissect_options *ndo, const u_char *dat, u_int length) { register const struct radius_hdr *rad; u_int len, auth_idx; ND_TCHECK2(*dat, MIN_RADIUS_LEN); rad = (struct radius_hdr *)dat; len = EXTRACT_16BITS(&rad->len); if (len < MIN_RADIUS_LEN) { ND_PRINT((ndo, "%s", tstr)); return; } if (len > length) len = length; if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "RADIUS, %s (%u), id: 0x%02x length: %u", tok2str(radius_command_values,"Unknown Command",rad->code), rad->code, rad->id, len)); return; } else { ND_PRINT((ndo, "RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ", len, tok2str(radius_command_values,"Unknown Command",rad->code), rad->code, rad->id)); for(auth_idx=0; auth_idx < 16; auth_idx++) ND_PRINT((ndo, "%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((ndo, "%s", tstr)); }
static void aoev1_query_print(netdissect_options *ndo, const u_char *cp, const u_int len) { const u_char *ep = cp + len; uint16_t cslen; if (len < AOEV1_QUERY_ARG_LEN) goto invalid; /* Buffer Count */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\tBuffer Count: %u", EXTRACT_16BITS(cp))); cp += 2; /* Firmware Version */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", Firmware Version: %u", EXTRACT_16BITS(cp))); cp += 2; /* Sector Count */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", Sector Count: %u", *cp)); cp += 1; /* AoE/CCmd */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", AoE: %u, CCmd: %s", (*cp & 0xF0) >> 4, tok2str(aoev1_ccmd_str, "Unknown (0x02x)", *cp & 0x0F))); cp += 1; /* Config String Length */ ND_TCHECK2(*cp, 2); cslen = EXTRACT_16BITS(cp); cp += 2; if (cslen > AOEV1_MAX_CONFSTR_LEN || AOEV1_QUERY_ARG_LEN + cslen > len) goto invalid; /* Config String */ ND_TCHECK2(*cp, cslen); if (cslen) { ND_PRINT((ndo, "\n\tConfig String (length %u): ", cslen)); if (fn_printn(ndo, cp, cslen, ndo->ndo_snapend)) goto trunc; } return; invalid: ND_PRINT((ndo, "%s", istr)); ND_TCHECK2(*cp, ep - cp); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
/* 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_TCHECK2(*cp, 1); version = *cp; cp += 1; /* type */ ND_TCHECK2(*cp, 1); type = *cp; cp += 1; /* length */ ND_TCHECK2(*cp, 2); length = EXTRACT_16BITS(cp); cp += 2; /* xid */ ND_TCHECK2(*cp, 4); xid = EXTRACT_32BITS(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_TCHECK2(*cp, length - OF_HEADER_LEN); return cp + length - OF_HEADER_LEN; /* done with current message */ } invalid: /* fail current packet */ ND_PRINT((ndo, "%s", istr)); ND_TCHECK2(*cp, ep - cp); return ep; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; }
/* * Pre operation attributes. Print only if vflag > 1. */ static const uint32_t * parse_pre_op_attr(netdissect_options *ndo, const uint32_t *dp, int verbose) { ND_TCHECK(dp[0]); if (!EXTRACT_32BITS(&dp[0])) return (dp + 1); dp++; ND_TCHECK2(*dp, 24); if (verbose > 1) { return parse_wcc_attr(ndo, dp); } else { /* If not verbose enough, just skip over wcc_attr */ return (dp + 6); } trunc: return (NULL); }
int hbhopt_print(netdissect_options *ndo, register const u_char *bp) { const struct ip6_hbh *dp = (const struct ip6_hbh *)bp; int hbhlen = 0; ND_TCHECK(dp->ip6h_len); hbhlen = (int)((dp->ip6h_len + 1) << 3); ND_TCHECK2(*dp, hbhlen); ND_PRINT((ndo, "HBH ")); if (ndo->ndo_vflag) ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp)); return(hbhlen); trunc: ND_PRINT((ndo, "[|HBH]")); return(-1); }
/* RFC6506 Section 4.1 */ static int ospf6_decode_at(netdissect_options *ndo, const u_char *cp, const u_int len) { uint16_t authdatalen; if (len == 0) return 0; if (len < OSPF6_AT_HDRLEN) goto trunc; /* Authentication Type */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\tAuthentication Type %s", tok2str(ospf6_auth_type_str, "unknown (0x%04x)", EXTRACT_16BITS(cp)))); cp += 2; /* Auth Data Len */ ND_TCHECK2(*cp, 2); authdatalen = EXTRACT_16BITS(cp); ND_PRINT((ndo, ", Length %u", authdatalen)); if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len) goto trunc; cp += 2; /* Reserved */ ND_TCHECK2(*cp, 2); cp += 2; /* Security Association ID */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", SAID %u", EXTRACT_16BITS(cp))); cp += 2; /* Cryptographic Sequence Number (High-Order 32 Bits) */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", CSN 0x%08x", EXTRACT_32BITS(cp))); cp += 4; /* Cryptographic Sequence Number (Low-Order 32 Bits) */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ":%08x", EXTRACT_32BITS(cp))); cp += 4; /* Authentication Data */ ND_TCHECK2(*cp, authdatalen - OSPF6_AT_HDRLEN); if (ndo->ndo_vflag > 1) print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN); return 0; trunc: return 1; }
static const u_char * zmtp1_print_intermediate_part(netdissect_options *ndo, const u_char *cp, const u_int len) { u_int frame_offset; uint64_t remaining_len; ND_TCHECK2(*cp, 2); frame_offset = EXTRACT_16BITS(cp); ND_PRINT((ndo, "\n\t frame offset 0x%04x", frame_offset)); cp += 2; remaining_len = ndo->ndo_snapend - cp; /* without the frame length */ if (frame_offset == 0xFFFF) frame_offset = len - 2; /* always within the declared length */ else if (2 + frame_offset > len) { ND_PRINT((ndo, " (exceeds datagram declared length)")); goto trunc; } /* offset within declared length of the datagram */ if (frame_offset) { ND_PRINT((ndo, "\n\t frame intermediate part, %u bytes", frame_offset)); if (frame_offset > remaining_len) ND_PRINT((ndo, " (%"PRIu64" captured)", remaining_len)); if (ndo->ndo_vflag) { uint64_t len_printed = min(frame_offset, remaining_len); if (ndo->ndo_vflag == 1) len_printed = min(VBYTES, len_printed); if (len_printed > 1) { ND_PRINT((ndo, ", first %"PRIu64" byte(s):", len_printed)); hex_and_ascii_print(ndo, "\n\t ", cp, len_printed); ND_PRINT((ndo, "\n")); } } } return cp + frame_offset; trunc: ND_PRINT((ndo, "%s", tstr)); return cp + len; }
int dstopt_print(netdissect_options *ndo, register const u_char *bp) { const struct ip6_dest *dp = (const struct ip6_dest *)bp; int dstoptlen = 0; ND_TCHECK(dp->ip6d_len); dstoptlen = (int)((dp->ip6d_len + 1) << 3); ND_TCHECK2(*dp, dstoptlen); ND_PRINT((ndo, "DSTOPT ")); if (ndo->ndo_vflag) { ip6_opt_print(ndo, (const u_char *)dp + sizeof(*dp), dstoptlen - sizeof(*dp)); } return(dstoptlen); trunc: ND_PRINT((ndo, "[|DSTOPT]")); return(-1); }
/* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Reserved | Message Class | Message Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Message Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * \ \ * / / */ void m3ua_print(netdissect_options *ndo, const u_char *buf, const u_int size) { const struct m3ua_common_header *hdr = (const struct m3ua_common_header *) buf; const struct tok *dict; /* size includes the header */ if (size < sizeof(struct m3ua_common_header)) goto corrupt; ND_TCHECK(*hdr); if (hdr->v != M3UA_REL_1_0) return; dict = hdr->msg_class == M3UA_MSGC_MGMT ? MgmtMessages : hdr->msg_class == M3UA_MSGC_TRANSFER ? TransferMessages : hdr->msg_class == M3UA_MSGC_SSNM ? SS7Messages : hdr->msg_class == M3UA_MSGC_ASPSM ? ASPStateMessages : hdr->msg_class == M3UA_MSGC_ASPTM ? ASPTrafficMessages : hdr->msg_class == M3UA_MSGC_RKM ? RoutingKeyMgmtMessages : NULL; ND_PRINT((ndo, "\n\t\t%s", tok2str(MessageClasses, "Unknown message class %i", hdr->msg_class))); if (dict != NULL) ND_PRINT((ndo, " %s Message", tok2str(dict, "Unknown (0x%02x)", hdr->msg_type))); if (size != EXTRACT_32BITS(&hdr->len)) ND_PRINT((ndo, "\n\t\t\t@@@@@@ Corrupted length %u of message @@@@@@", EXTRACT_32BITS(&hdr->len))); else m3ua_tags_print(ndo, buf + sizeof(struct m3ua_common_header), EXTRACT_32BITS(&hdr->len) - sizeof(struct m3ua_common_header)); return; corrupt: ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*buf, size); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
static int lwres_printaddr(netdissect_options *ndo, lwres_addr_t *ap) { uint16_t l; const char *p; int i; ND_TCHECK(ap->length); l = EXTRACT_16BITS(&ap->length); /* XXX ap points to packed struct */ p = (const char *)&ap->length + sizeof(ap->length); ND_TCHECK2(*p, l); switch (EXTRACT_32BITS(&ap->family)) { case 1: /* IPv4 */ if (l < 4) return -1; ND_PRINT((ndo, " %s", ipaddr_string(ndo, p))); p += sizeof(struct in_addr); break; #ifdef INET6 case 2: /* IPv6 */ if (l < 16) return -1; ND_PRINT((ndo, " %s", ip6addr_string(ndo, p))); p += sizeof(struct in6_addr); break; #endif default: ND_PRINT((ndo, " %u/", EXTRACT_32BITS(&ap->family))); for (i = 0; i < l; i++) ND_PRINT((ndo, "%02x", *p++)); } return p - (const char *)ap; trunc: return -1; }
static int resp_print_string_error_integer(netdissect_options *ndo, register const u_char *bp, int length) { int length_cur = length, len, ret_len = 0; const u_char *bp_ptr = bp; /* * MOVE_FORWARD moves past the string that follows the (+-;) opcodes * +OK\r\n * -ERR ...\r\n * :02912309\r\n */ MOVE_FORWARD(bp_ptr, length_cur); len = (bp_ptr - bp); ND_TCHECK2(*bp, len); RESP_PRINT_SEGMENT(ndo, bp+1, len-1); ret_len = len /*<1byte>+<string>*/ + 2 /*<CRLF>*/; TEST_RET_LEN(ret_len); trunc: return (-1); }
static void trans2_qfsinfo(netdissect_options *ndo, const u_char *param, const u_char *data, int pcnt, int dcnt) { static int level = 0; const char *fmt=""; if (request) { ND_TCHECK2(*param, 2); level = EXTRACT_LE_16BITS(param); fmt = "InfoLevel=[d]\n"; smb_fdata(ndo, param, fmt, param + pcnt, unicodestr); } else { switch (level) { case 1: fmt = "idFileSystem=[W]\nSectorUnit=[D]\nUnit=[D]\nAvail=[D]\nSectorSize=[d]\n"; break; case 2: fmt = "CreationTime=[T2]VolNameLength=[lb]\nVolumeLabel=[c]\n"; break; case 0x105: fmt = "Capabilities=[W]\nMaxFileLen=[D]\nVolNameLen=[lD]\nVolume=[C]\n"; break; default: fmt = "UnknownLevel\n"; break; } smb_fdata(ndo, data, fmt, data + dcnt, unicodestr); } if (dcnt) { ND_PRINT((ndo, "data:\n")); smb_print_data(ndo, data, dcnt); } return; trunc: ND_PRINT((ndo, "%s", tstr)); }
/* * Print out a file name and return pointer to 32-bit word past it. * If packet was truncated, return 0. */ static const uint32_t * parsefn(netdissect_options *ndo, register const uint32_t *dp) { register uint32_t len; register const u_char *cp; /* Bail if we don't have the string length */ ND_TCHECK(*dp); /* Fetch string length; convert to host order */ len = *dp++; NTOHL(len); #ifndef CHERI_TCPDUMP_VULNERABILITY ND_TCHECK2(*dp, ((len + 3) & ~3)); #endif cp = (u_char *)dp; /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ dp += ((len + 3) & ~3) / sizeof(*dp); ND_PRINT((ndo, "\"")); #ifdef CHERI_TCPDUMP_VULNERABILITY (void) fn_printn(ndo, cp, len, NULL); #else if (fn_printn(ndo, cp, len, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } #endif ND_PRINT((ndo, "\"")); return (dp); trunc: return NULL; }
void vqp_print(netdissect_options *ndo, register const u_char *pptr, register u_int len) { const struct vqp_common_header_t *vqp_common_header; const struct vqp_obj_tlv_t *vqp_obj_tlv; const u_char *tptr; uint16_t vqp_obj_len; uint32_t vqp_obj_type; u_int tlen; uint8_t nitems; tptr=pptr; tlen = len; vqp_common_header = (const struct vqp_common_header_t *)pptr; ND_TCHECK(*vqp_common_header); if (sizeof(struct vqp_common_header_t) > tlen) goto trunc; /* * Sanity checking of the header. */ if (VQP_EXTRACT_VERSION(vqp_common_header->version) != VQP_VERSION) { ND_PRINT((ndo, "VQP version %u packet not supported", VQP_EXTRACT_VERSION(vqp_common_header->version))); return; } /* in non-verbose mode just lets print the basic Message Type */ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "VQPv%u %s Message, error-code %s (%u), length %u", VQP_EXTRACT_VERSION(vqp_common_header->version), tok2str(vqp_msg_type_values, "unknown (%u)",vqp_common_header->msg_type), tok2str(vqp_error_code_values, "unknown (%u)",vqp_common_header->error_code), vqp_common_header->error_code, len)); return; } /* ok they seem to want to know everything - lets fully decode it */ nitems = vqp_common_header->nitems; ND_PRINT((ndo, "\n\tVQPv%u, %s Message, error-code %s (%u), seq 0x%08x, items %u, length %u", VQP_EXTRACT_VERSION(vqp_common_header->version), tok2str(vqp_msg_type_values, "unknown (%u)",vqp_common_header->msg_type), tok2str(vqp_error_code_values, "unknown (%u)",vqp_common_header->error_code), vqp_common_header->error_code, EXTRACT_32BITS(&vqp_common_header->sequence), nitems, len)); /* skip VQP Common header */ tptr+=sizeof(const struct vqp_common_header_t); tlen-=sizeof(const struct vqp_common_header_t); while (nitems > 0 && tlen > 0) { vqp_obj_tlv = (const struct vqp_obj_tlv_t *)tptr; ND_TCHECK(*vqp_obj_tlv); if (sizeof(struct vqp_obj_tlv_t) > tlen) goto trunc; vqp_obj_type = EXTRACT_32BITS(vqp_obj_tlv->obj_type); vqp_obj_len = EXTRACT_16BITS(vqp_obj_tlv->obj_length); tptr+=sizeof(struct vqp_obj_tlv_t); tlen-=sizeof(struct vqp_obj_tlv_t); ND_PRINT((ndo, "\n\t %s Object (0x%08x), length %u, value: ", tok2str(vqp_obj_values, "Unknown", vqp_obj_type), vqp_obj_type, vqp_obj_len)); /* basic sanity check */ if (vqp_obj_type == 0 || vqp_obj_len ==0) { return; } /* did we capture enough for fully decoding the object ? */ ND_TCHECK2(*tptr, vqp_obj_len); if (vqp_obj_len > tlen) goto trunc; switch(vqp_obj_type) { case VQP_OBJ_IP_ADDRESS: if (vqp_obj_len != 4) goto trunc; ND_PRINT((ndo, "%s (0x%08x)", ipaddr_string(ndo, tptr), EXTRACT_32BITS(tptr))); break; /* those objects have similar semantics - fall through */ case VQP_OBJ_PORT_NAME: case VQP_OBJ_VLAN_NAME: case VQP_OBJ_VTP_DOMAIN: case VQP_OBJ_ETHERNET_PKT: safeputs(ndo, tptr, vqp_obj_len); break; /* those objects have similar semantics - fall through */ case VQP_OBJ_MAC_ADDRESS: case VQP_OBJ_MAC_NULL: if (vqp_obj_len != ETHER_ADDR_LEN) goto trunc; ND_PRINT((ndo, "%s", etheraddr_string(ndo, tptr))); break; default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo,tptr, "\n\t ", vqp_obj_len); break; } tptr += vqp_obj_len; tlen -= vqp_obj_len; nitems--; } return; trunc: ND_PRINT((ndo, "\n\t[|VQP]")); }
void eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int len) { const struct eigrp_common_header *eigrp_com_header; const struct eigrp_tlv_header *eigrp_tlv_header; const u_char *tptr,*tlv_tptr; u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length; uint8_t prefix[4]; union { const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm; const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version; const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int; const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext; const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup; const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int; const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext; } tlv_ptr; tptr=pptr; eigrp_com_header = (const struct eigrp_common_header *)pptr; ND_TCHECK(*eigrp_com_header); /* * Sanity checking of the header. */ if (eigrp_com_header->version != EIGRP_VERSION) { ND_PRINT((ndo, "EIGRP version %u packet not supported",eigrp_com_header->version)); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "EIGRP %s, length: %u", tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=len-sizeof(struct eigrp_common_header); /* FIXME print other header info */ ND_PRINT((ndo, "\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]\n\tseq: 0x%08x, ack: 0x%08x, AS: %u, length: %u", eigrp_com_header->version, tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode), eigrp_com_header->opcode, EXTRACT_16BITS(&eigrp_com_header->checksum), tok2str(eigrp_common_header_flag_values, "none", EXTRACT_32BITS(&eigrp_com_header->flags)), EXTRACT_32BITS(&eigrp_com_header->seq), EXTRACT_32BITS(&eigrp_com_header->ack), EXTRACT_32BITS(&eigrp_com_header->asn), tlen)); tptr+=sizeof(const struct eigrp_common_header); while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK2(*tptr, sizeof(struct eigrp_tlv_header)); eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr; eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length); eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type); if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) || eigrp_tlv_len > tlen) { print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ",tlen); return; } ND_PRINT((ndo, "\n\t %s TLV (0x%04x), length: %u", tok2str(eigrp_tlv_values, "Unknown", eigrp_tlv_type), eigrp_tlv_type, eigrp_tlv_len)); tlv_tptr=tptr+sizeof(struct eigrp_tlv_header); tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header); /* did we capture enough for fully decoding the object ? */ ND_TCHECK2(*tptr, eigrp_tlv_len); switch(eigrp_tlv_type) { case EIGRP_TLV_GENERAL_PARM: tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr; ND_PRINT((ndo, "\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u", EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime), tlv_ptr.eigrp_tlv_general_parm->k1, tlv_ptr.eigrp_tlv_general_parm->k2, tlv_ptr.eigrp_tlv_general_parm->k3, tlv_ptr.eigrp_tlv_general_parm->k4, tlv_ptr.eigrp_tlv_general_parm->k5)); break; case EIGRP_TLV_SW_VERSION: tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr; ND_PRINT((ndo, "\n\t IOS version: %u.%u, EIGRP version %u.%u", tlv_ptr.eigrp_tlv_sw_version->ios_major, tlv_ptr.eigrp_tlv_sw_version->ios_minor, tlv_ptr.eigrp_tlv_sw_version->eigrp_major, tlv_ptr.eigrp_tlv_sw_version->eigrp_minor)); break; case EIGRP_TLV_IP_INT: tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr; bit_length = tlv_ptr.eigrp_tlv_ip_int->plen; if (bit_length > 32) { ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length)); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length); ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(ndo, prefix), bit_length)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_int->nexthop))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu), tlv_ptr.eigrp_tlv_ip_int->hopcount, tlv_ptr.eigrp_tlv_ip_int->reliability, tlv_ptr.eigrp_tlv_ip_int->load)); break; case EIGRP_TLV_IP_EXT: tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr; bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen; if (bit_length > 32) { ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length)); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length); ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(ndo, prefix), bit_length)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_ext->nexthop))); ND_PRINT((ndo, "\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", ipaddr_string(ndo, tlv_ptr.eigrp_tlv_ip_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id), tlv_ptr.eigrp_tlv_ip_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu), tlv_ptr.eigrp_tlv_ip_ext->hopcount, tlv_ptr.eigrp_tlv_ip_ext->reliability, tlv_ptr.eigrp_tlv_ip_ext->load)); break; case EIGRP_TLV_AT_CABLE_SETUP: tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr; ND_PRINT((ndo, "\n\t Cable-range: %u-%u, Router-ID %u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id))); break; case EIGRP_TLV_AT_INT: tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr; ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end))); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2]))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu), tlv_ptr.eigrp_tlv_at_int->hopcount, tlv_ptr.eigrp_tlv_at_int->reliability, tlv_ptr.eigrp_tlv_at_int->load)); break; case EIGRP_TLV_AT_EXT: tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr; ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end))); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2]))); ND_PRINT((ndo, "\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id), tlv_ptr.eigrp_tlv_at_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag), EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu), tlv_ptr.eigrp_tlv_at_ext->hopcount, tlv_ptr.eigrp_tlv_at_ext->reliability, tlv_ptr.eigrp_tlv_at_ext->load)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case EIGRP_TLV_AUTH: case EIGRP_TLV_SEQ: case EIGRP_TLV_MCAST_SEQ: case EIGRP_TLV_IPX_INT: case EIGRP_TLV_IPX_EXT: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo,tlv_tptr,"\n\t ",tlv_tlen); break; } /* do we want to see an additionally hexdump ? */ if (ndo->ndo_vflag > 1) print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ", eigrp_tlv_len-sizeof(struct eigrp_tlv_header)); tptr+=eigrp_tlv_len; tlen-=eigrp_tlv_len; } return; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); }
static int ldp_pdu_print(netdissect_options *ndo, register 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(*ldp_com_header); /* * Sanity checking of the header. */ if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { ND_PRINT((ndo, "%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", EXTRACT_16BITS(&ldp_com_header->version))); return 0; } pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); if (pdu_len < sizeof(const struct ldp_common_header)-4) { /* length too short */ ND_PRINT((ndo, "%sLDP, pdu-length: %u (too short, < %u)", (ndo->ndo_vflag < 1) ? "" : "\n\t", pdu_len, (u_int)(sizeof(const struct ldp_common_header)-4))); return 0; } /* print the LSR-ID, label-space & length */ ND_PRINT((ndo, "%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", (ndo->ndo_vflag < 1) ? "" : "\n\t", ipaddr_string(ndo, &ldp_com_header->lsr_id), EXTRACT_16BITS(&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(const struct ldp_common_header); tlen = pdu_len - (sizeof(const struct ldp_common_header)-4); /* Type & Length fields not included */ while(tlen>0) { /* did we capture enough for fully decoding the msg header ? */ ND_TCHECK2(*tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; msg_len=EXTRACT_16BITS(ldp_msg_header->length); msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); if (msg_len < sizeof(struct ldp_msg_header)-4) { /* length too short */ /* FIXME vendor private / experimental check */ ND_PRINT((ndo, "\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((ndo, "\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_32BITS(&ldp_msg_header->id), LDP_MASK_U_BIT(EXTRACT_16BITS(&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_TCHECK2(*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((ndo, "\n\t\t packet exceeded snapshot")); return 0; }
static int ldp_tlv_print(netdissect_options *ndo, register const u_char *tptr, u_short msg_tlen) { struct ldp_tlv_header { uint8_t type[2]; uint8_t length[2]; }; 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(*ldp_tlv_header); tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); if (tlv_len + 4 > msg_tlen) { ND_PRINT((ndo, "\n\t\t TLV contents go past end of message")); return 0; } tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ ND_PRINT((ndo, "\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_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", LDP_MASK_F_BIT(EXTRACT_16BITS(&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((ndo, "\n\t Hold Time: %us, Flags: [%s Hello%s]", EXTRACT_16BITS(tptr), (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : "")); break; case LDP_TLV_IPV4_TRANSPORT_ADDR: TLV_TCHECK(4); ND_PRINT((ndo, "\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr))); break; case LDP_TLV_IPV6_TRANSPORT_ADDR: TLV_TCHECK(16); ND_PRINT((ndo, "\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr))); break; case LDP_TLV_CONFIG_SEQ_NUMBER: TLV_TCHECK(4); ND_PRINT((ndo, "\n\t Sequence Number: %u", EXTRACT_32BITS(tptr))); break; case LDP_TLV_ADDRESS_LIST: TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = EXTRACT_16BITS(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; ND_PRINT((ndo, "\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_TCHECK2(*tptr, sizeof(struct in_addr)); ND_PRINT((ndo, " %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_TCHECK2(*tptr, sizeof(struct in6_addr)); ND_PRINT((ndo, " %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((ndo, "\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2), (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited", (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled" )); break; case LDP_TLV_FEC: TLV_TCHECK(1); fec_type = *tptr; ND_PRINT((ndo, "\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_16BITS(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((ndo, ": IPv4 prefix (goes past end of TLV)")); else if (i == -1) ND_PRINT((ndo, ": IPv4 prefix (invalid length)")); else ND_PRINT((ndo, ": 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((ndo, ": IPv4 prefix (goes past end of TLV)")); else if (i == -1) ND_PRINT((ndo, ": IPv6 prefix (invalid length)")); else ND_PRINT((ndo, ": IPv6 prefix %s", buf)); } else ND_PRINT((ndo, ": Address family %u prefix", af)); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: /* * 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. */ TLV_TCHECK(7); vc_info_len = *(tptr+2); if (vc_info_len == 0) { ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-info-length: %u", tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", EXTRACT_32BITS(tptr+3), vc_info_len)); break; } /* Make sure we have the VC ID as well */ TLV_TCHECK(11); ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", EXTRACT_32BITS(tptr+3), EXTRACT_32BITS(tptr+7), vc_info_len)); if (vc_info_len < 4) { /* minimum 4, for the VC ID */ ND_PRINT((ndo, " (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 = *tptr; vc_info_tlv_len = *(tptr+1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) break; ND_PRINT((ndo, "\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((ndo, ": %u", EXTRACT_16BITS(tptr+2))); break; case LDP_FEC_MARTINI_IFPARM_DESC: ND_PRINT((ndo, ": ")); for (idx = 2; idx < vc_info_tlv_len; idx++) safeputchar(ndo, *(tptr + idx)); break; case LDP_FEC_MARTINI_IFPARM_VCCV: ND_PRINT((ndo, "\n\t\t Control Channels (0x%02x) = [%s]", *(tptr+2), bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", *(tptr+2)))); ND_PRINT((ndo, "\n\t\t CV Types (0x%02x) = [%s]", *(tptr+3), bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", *(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((ndo, "\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff)); break; case LDP_TLV_STATUS: TLV_TCHECK(8); ui = EXTRACT_32BITS(tptr); tptr+=4; ND_PRINT((ndo, "\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_32BITS(tptr); tptr+=4; if (ui) ND_PRINT((ndo, ", causing Message ID: 0x%08x", ui)); break; case LDP_TLV_FT_SESSION: TLV_TCHECK(8); ft_flags = EXTRACT_16BITS(tptr); ND_PRINT((ndo, "\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_32BITS(tptr); if (ui) ND_PRINT((ndo, ", Reconnect Timeout: %ums", ui)); tptr+=4; ui = EXTRACT_32BITS(tptr); if (ui) ND_PRINT((ndo, ", Recovery Time: %ums", ui)); break; case LDP_TLV_MTU: TLV_TCHECK(2); ND_PRINT((ndo, "\n\t MTU: %u", EXTRACT_16BITS(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((ndo, "\n\t\t packet exceeded snapshot")); return 0; badtlv: ND_PRINT((ndo, "\n\t\t TLV contents go past end of TLV")); return(tlv_len+4); /* Type & Length fields not included */ }
void cdp_print(netdissect_options *ndo, const u_char *pptr, u_int length, u_int caplen) { int type, len, i, j; const u_char *tptr; if (caplen < CDP_HEADER_LEN) { ND_PRINT((ndo, "%s", tstr)); return; } tptr = pptr; /* temporary pointer */ ND_TCHECK2(*tptr, CDP_HEADER_LEN); ND_PRINT((ndo, "CDPv%u, ttl: %us", *(tptr + CDP_HEADER_VERSION_OFFSET), *(tptr + CDP_HEADER_TTL_OFFSET))); if (ndo->ndo_vflag) ND_PRINT((ndo, ", checksum: 0x%04x (unverified), length %u", EXTRACT_16BITS(tptr+CDP_HEADER_CHECKSUM_OFFSET), length)); tptr += CDP_HEADER_LEN; while (tptr < (pptr+length)) { ND_TCHECK2(*tptr, CDP_TLV_HEADER_LEN); /* read out Type and Length */ type = EXTRACT_16BITS(tptr+CDP_TLV_TYPE_OFFSET); len = EXTRACT_16BITS(tptr+CDP_TLV_LEN_OFFSET); /* object length includes the 4 bytes header length */ if (len < CDP_TLV_HEADER_LEN) { if (ndo->ndo_vflag) ND_PRINT((ndo, "\n\t%s (0x%02x), TLV length: %u byte%s (too short)", tok2str(cdp_tlv_values,"unknown field type", type), type, len, PLURAL_SUFFIX(len))); /* plural */ else ND_PRINT((ndo, ", %s TLV length %u too short", tok2str(cdp_tlv_values,"unknown field type", type), len)); break; } tptr += CDP_TLV_HEADER_LEN; len -= CDP_TLV_HEADER_LEN; ND_TCHECK2(*tptr, len); if (ndo->ndo_vflag || type == 1) { /* in non-verbose mode just print Device-ID */ if (ndo->ndo_vflag) ND_PRINT((ndo, "\n\t%s (0x%02x), value length: %u byte%s: ", tok2str(cdp_tlv_values,"unknown field type", type), type, len, PLURAL_SUFFIX(len))); /* plural */ switch (type) { case 0x01: /* Device-ID */ if (!ndo->ndo_vflag) ND_PRINT((ndo, ", Device-ID ")); ND_PRINT((ndo, "'")); (void)fn_printn(ndo, tptr, len, NULL); ND_PRINT((ndo, "'")); break; case 0x02: /* Address */ if (cdp_print_addr(ndo, tptr, len) < 0) goto trunc; break; case 0x03: /* Port-ID */ ND_PRINT((ndo, "'")); (void)fn_printn(ndo, tptr, len, NULL); ND_PRINT((ndo, "'")); break; case 0x04: /* Capabilities */ if (len < 4) goto trunc; ND_PRINT((ndo, "(0x%08x): %s", EXTRACT_32BITS(tptr), bittok2str(cdp_capability_values, "none", EXTRACT_32BITS(tptr)))); break; case 0x05: /* Version */ ND_PRINT((ndo, "\n\t ")); for (i=0;i<len;i++) { j = *(tptr+i); if (j == '\n') /* lets rework the version string to get a nice indentation */ ND_PRINT((ndo, "\n\t ")); else fn_print_char(ndo, j); } break; case 0x06: /* Platform */ ND_PRINT((ndo, "'")); (void)fn_printn(ndo, tptr, len, NULL); ND_PRINT((ndo, "'")); break; case 0x07: /* Prefixes */ if (cdp_print_prefixes(ndo, tptr, len) < 0) goto trunc; break; case 0x08: /* Protocol Hello Option - not documented */ break; case 0x09: /* VTP Mgmt Domain - CDPv2 */ ND_PRINT((ndo, "'")); (void)fn_printn(ndo, tptr, len, NULL); ND_PRINT((ndo, "'")); break; case 0x0a: /* Native VLAN ID - CDPv2 */ if (len < 2) goto trunc; ND_PRINT((ndo, "%d", EXTRACT_16BITS(tptr))); break; case 0x0b: /* Duplex - CDPv2 */ if (len < 1) goto trunc; ND_PRINT((ndo, "%s", *(tptr) ? "full": "half")); break; /* http://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cata/186/2_12_m/english/release/notes/186rn21m.html * plus more details from other sources */ case 0x0e: /* ATA-186 VoIP VLAN request - incomplete doc. */ if (len < 3) goto trunc; ND_PRINT((ndo, "app %d, vlan %d", *(tptr), EXTRACT_16BITS(tptr + 1))); break; case 0x10: /* ATA-186 VoIP VLAN assignment - incomplete doc. */ ND_PRINT((ndo, "%1.2fW", cdp_get_number(tptr, len) / 1000.0)); break; case 0x11: /* MTU - not documented */ if (len < 4) goto trunc; ND_PRINT((ndo, "%u bytes", EXTRACT_32BITS(tptr))); break; case 0x12: /* AVVID trust bitmap - not documented */ if (len < 1) goto trunc; ND_PRINT((ndo, "0x%02x", *(tptr))); break; case 0x13: /* AVVID untrusted port CoS - not documented */ if (len < 1) goto trunc; ND_PRINT((ndo, "0x%02x", *(tptr))); break; case 0x14: /* System Name - not documented */ ND_PRINT((ndo, "'")); (void)fn_printn(ndo, tptr, len, NULL); ND_PRINT((ndo, "'")); break; case 0x16: /* System Object ID - not documented */ if (cdp_print_addr(ndo, tptr, len) < 0) goto trunc; break; case 0x17: /* Physical Location - not documented */ if (len < 1) goto trunc; ND_PRINT((ndo, "0x%02x", *(tptr))); if (len > 1) { ND_PRINT((ndo, "/")); (void)fn_printn(ndo, tptr + 1, len - 1, NULL); } break; default: print_unknown_data(ndo, tptr, "\n\t ", len); break; } } tptr = tptr+len; } if (ndo->ndo_vflag < 1) ND_PRINT((ndo, ", length %u", caplen)); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
static int cdp_print_addr(netdissect_options *ndo, const u_char * p, int l) { int pt, pl, al, num; const u_char *endp = p + l; static const u_char prot_ipv6[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd }; ND_TCHECK2(*p, 4); if (p + 4 > endp) goto trunc; num = EXTRACT_32BITS(p); p += 4; while (p < endp && num >= 0) { ND_TCHECK2(*p, 2); if (p + 2 > endp) goto trunc; pt = p[0]; /* type of "protocol" field */ pl = p[1]; /* length of "protocol" field */ p += 2; ND_TCHECK2(p[pl], 2); if (p + pl + 2 > endp) goto trunc; al = EXTRACT_16BITS(&p[pl]); /* address length */ if (pt == PT_NLPID && pl == 1 && *p == NLPID_IP && al == 4) { /* * IPv4: protocol type = NLPID, protocol length = 1 * (1-byte NLPID), protocol = 0xcc (NLPID for IPv4), * address length = 4 */ p += 3; ND_TCHECK2(*p, 4); if (p + 4 > endp) goto trunc; ND_PRINT((ndo, "IPv4 (%u) %s", num, ipaddr_string(ndo, p))); p += 4; } else if (pt == PT_IEEE_802_2 && pl == 8 && memcmp(p, prot_ipv6, 8) == 0 && al == 16) { /* * IPv6: protocol type = IEEE 802.2 header, * protocol length = 8 (size of LLC+SNAP header), * protocol = LLC+SNAP header with the IPv6 * Ethertype, address length = 16 */ p += 10; ND_TCHECK2(*p, al); if (p + al > endp) goto trunc; ND_PRINT((ndo, "IPv6 (%u) %s", num, ip6addr_string(ndo, p))); p += al; } else { /* * Generic case: just print raw data */ ND_TCHECK2(*p, pl); if (p + pl > endp) goto trunc; ND_PRINT((ndo, "pt=0x%02x, pl=%d, pb=", *(p - 2), pl)); while (pl-- > 0) ND_PRINT((ndo, " %02x", *p++)); ND_TCHECK2(*p, 2); if (p + 2 > endp) goto trunc; al = (*p << 8) + *(p + 1); ND_PRINT((ndo, ", al=%d, a=", al)); p += 2; ND_TCHECK2(*p, al); if (p + al > endp) goto trunc; while (al-- > 0) ND_PRINT((ndo, " %02x", *p++)); } num--; if (num) ND_PRINT((ndo, " ")); } return 0; trunc: return -1; }
static void print_trans2(netdissect_options *ndo, const u_char *words, const u_char *dat, const u_char *buf, const u_char *maxbuf) { u_int bcc; static const struct smbfnsint *fn = &trans2_fns[0]; const u_char *data, *param; const u_char *w = words + 1; const char *f1 = NULL, *f2 = NULL; int pcnt, dcnt; ND_TCHECK(words[0]); if (request) { ND_TCHECK2(w[14 * 2], 2); pcnt = EXTRACT_LE_16BITS(w + 9 * 2); param = buf + EXTRACT_LE_16BITS(w + 10 * 2); dcnt = EXTRACT_LE_16BITS(w + 11 * 2); data = buf + EXTRACT_LE_16BITS(w + 12 * 2); fn = smbfindint(EXTRACT_LE_16BITS(w + 14 * 2), trans2_fns); } else { if (words[0] == 0) { ND_PRINT((ndo, "%s\n", fn->name)); ND_PRINT((ndo, "Trans2Interim\n")); return; } ND_TCHECK2(w[7 * 2], 2); pcnt = EXTRACT_LE_16BITS(w + 3 * 2); param = buf + EXTRACT_LE_16BITS(w + 4 * 2); dcnt = EXTRACT_LE_16BITS(w + 6 * 2); data = buf + EXTRACT_LE_16BITS(w + 7 * 2); } ND_PRINT((ndo, "%s param_length=%d data_length=%d\n", fn->name, pcnt, dcnt)); if (request) { if (words[0] == 8) { smb_fdata(ndo, words + 1, "Trans2Secondary\nTotParam=[d]\nTotData=[d]\nParamCnt=[d]\nParamOff=[d]\nParamDisp=[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nHandle=[d]\n", maxbuf, unicodestr); return; } else { smb_fdata(ndo, words + 1, "TotParam=[d]\nTotData=[d]\nMaxParam=[d]\nMaxData=[d]\nMaxSetup=[b][P1]\nFlags=[w]\nTimeOut=[D]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nDataCnt=[d]\nDataOff=[d]\nSetupCnt=[b][P1]\n", words + 1 + 14 * 2, unicodestr); } f1 = fn->descript.req_f1; f2 = fn->descript.req_f2; } else { smb_fdata(ndo, words + 1, "TotParam=[d]\nTotData=[d]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nParamDisp[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nSetupCnt=[b][P1]\n", words + 1 + 10 * 2, unicodestr); f1 = fn->descript.rep_f1; f2 = fn->descript.rep_f2; } ND_TCHECK2(*dat, 2); bcc = EXTRACT_LE_16BITS(dat); ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); if (fn->descript.fn) (*fn->descript.fn)(ndo, param, data, pcnt, dcnt); else { smb_fdata(ndo, param, f1 ? f1 : "Parameters=\n", param + pcnt, unicodestr); smb_fdata(ndo, data, f2 ? f2 : "Data=\n", data + dcnt, unicodestr); } return; trunc: ND_PRINT((ndo, "%s", tstr)); }
static void aoev1_issue_print(netdissect_options *ndo, const u_char *cp, const u_int len) { const u_char *ep = cp + len; if (len < AOEV1_ISSUE_ARG_LEN) goto invalid; /* AFlags */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, "\n\tAFlags: [%s]", bittok2str(aoev1_aflag_str, "none", *cp))); cp += 1; /* Err/Feature */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", Err/Feature: %u", *cp)); cp += 1; /* Sector Count (not correlated with the length) */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", Sector Count: %u", *cp)); cp += 1; /* Cmd/Status */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", Cmd/Status: %u", *cp)); cp += 1; /* lba0 */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, "\n\tlba0: %u", *cp)); cp += 1; /* lba1 */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", lba1: %u", *cp)); cp += 1; /* lba2 */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", lba2: %u", *cp)); cp += 1; /* lba3 */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", lba3: %u", *cp)); cp += 1; /* lba4 */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", lba4: %u", *cp)); cp += 1; /* lba5 */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", lba5: %u", *cp)); cp += 1; /* Reserved */ ND_TCHECK2(*cp, 2); cp += 2; /* Data */ if (len > AOEV1_ISSUE_ARG_LEN) ND_PRINT((ndo, "\n\tData: %u bytes", len - AOEV1_ISSUE_ARG_LEN)); return; invalid: ND_PRINT((ndo, "%s", istr)); ND_TCHECK2(*cp, ep - cp); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
static int dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen) { u_int8_t optlen, i; ND_TCHECK(*option); if (*option >= 32) { ND_TCHECK(*(option+1)); optlen = *(option +1); if (optlen < 2) { if (*option >= 128) ND_PRINT((ndo, "CCID option %u optlen too short", *option)); else ND_PRINT((ndo, "%s optlen too short", tok2str(dccp_option_values, "Option %u", *option))); return 0; } } else optlen = 1; if (hlen < optlen) { if (*option >= 128) ND_PRINT((ndo, "CCID option %u optlen goes past header length", *option)); else ND_PRINT((ndo, "%s optlen goes past header length", tok2str(dccp_option_values, "Option %u", *option))); return 0; } ND_TCHECK2(*option, optlen); if (*option >= 128) { ND_PRINT((ndo, "CCID option %d", *option)); switch (optlen) { case 4: ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2))); break; case 6: ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); break; default: break; } } else { ND_PRINT((ndo, "%s", tok2str(dccp_option_values, "Option %u", *option))); switch (*option) { case 32: case 33: case 34: case 35: if (optlen < 3) { ND_PRINT((ndo, " optlen too short")); return optlen; } if (*(option + 2) < 10){ ND_PRINT((ndo, " %s", dccp_feature_nums[*(option + 2)])); for (i = 0; i < optlen - 3; i++) ND_PRINT((ndo, " %d", *(option + 3 + i))); } break; case 36: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 37: for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, " %d", *(option + 2 + i))); break; case 38: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 39: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 40: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 41: if (optlen == 4) ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); else ND_PRINT((ndo, " optlen != 4")); break; case 42: if (optlen == 4) ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); else ND_PRINT((ndo, " optlen != 4")); break; case 43: if (optlen == 6) ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); else if (optlen == 4) ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2))); else ND_PRINT((ndo, " optlen != 4 or 6")); break; case 44: if (optlen > 2) { ND_PRINT((ndo, " ")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; } } return optlen; trunc: ND_PRINT((ndo, "%s", tstr)); return 0; }
/** * dccp_print - show dccp packet * @bp - beginning of dccp packet * @data2 - beginning of enclosing * @len - lenght of ip packet */ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, u_int len) { const struct dccp_hdr *dh; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif const u_char *cp; u_short sport, dport; u_int hlen; u_int fixed_hdrlen; dh = (const struct dccp_hdr *)bp; ip = (struct ip *)data2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)data2; else ip6 = NULL; #endif /*INET6*/ /* make sure we have enough data to look at the X bit */ cp = (const u_char *)(dh + 1); if (cp > ndo->ndo_snapend) { ND_PRINT((ndo, "[Invalid packet|dccp]")); return; } if (len < sizeof(struct dccp_hdr)) { ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", len - (u_int)sizeof(struct dccp_hdr))); return; } /* get the length of the generic header */ fixed_hdrlen = dccp_basic_hdr_len(dh); if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK2(*dh, fixed_hdrlen); sport = EXTRACT_16BITS(&dh->dccph_sport); dport = EXTRACT_16BITS(&dh->dccph_dport); hlen = dh->dccph_doff * 4; #ifdef INET6 if (ip6) { ND_PRINT((ndo, "%s.%d > %s.%d: ", ip6addr_string(ndo, &ip6->ip6_src), sport, ip6addr_string(ndo, &ip6->ip6_dst), dport)); } else #endif /*INET6*/ { ND_PRINT((ndo, "%s.%d > %s.%d: ", ipaddr_string(ndo, &ip->ip_src), sport, ipaddr_string(ndo, &ip->ip_dst), dport)); } if (ndo->ndo_qflag) { ND_PRINT((ndo, " %d", len - hlen)); if (hlen > len) { ND_PRINT((ndo, "dccp [bad hdr length %u - too long, > %u]", hlen, len)); } return; } /* other variables in generic header */ if (ndo->ndo_vflag) { ND_PRINT((ndo, "CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh))); } /* checksum calculation */ if (ndo->ndo_vflag && ND_TTEST2(bp[0], len)) { u_int16_t sum = 0, dccp_sum; dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); ND_PRINT((ndo, "cksum 0x%04x ", dccp_sum)); if (IP_V(ip) == 4) sum = dccp_cksum(ndo, ip, dh, len); #ifdef INET6 else if (IP_V(ip) == 6) sum = dccp6_cksum(ip6, dh, len); #endif if (sum != 0) ND_PRINT((ndo, "(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum))); else ND_PRINT((ndo, "(correct), ")); } switch (DCCPH_TYPE(dh)) { case DCCP_PKT_REQUEST: { struct dccp_hdr_request *dhr = (struct dccp_hdr_request *)(bp + fixed_hdrlen); fixed_hdrlen += 4; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp request - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "request (service=%d) ", EXTRACT_32BITS(&dhr->dccph_req_service))); break; } case DCCP_PKT_RESPONSE: { struct dccp_hdr_response *dhr = (struct dccp_hdr_response *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp response - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "response (service=%d) ", EXTRACT_32BITS(&dhr->dccph_resp_service))); break; } case DCCP_PKT_DATA: ND_PRINT((ndo, "data ")); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp ack - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "ack ")); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp dataack - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "dataack ")); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp closereq - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "closereq ")); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp close - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "close ")); break; case DCCP_PKT_RESET: { struct dccp_hdr_reset *dhr = (struct dccp_hdr_reset *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp reset - %u bytes missing!", len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "reset (code=%s) ", dccp_reset_code(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp sync - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "sync ")); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp syncack - %u bytes missing!", len - fixed_hdrlen)); return; } ND_PRINT((ndo, "syncack ")); break; default: ND_PRINT((ndo, "invalid ")); break; } if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) dccp_print_ack_no(ndo, bp); if (ndo->ndo_vflag < 2) return; ND_PRINT((ndo, "seq %" PRIu64, dccp_seqno(bp))); /* process options */ if (hlen > fixed_hdrlen){ const u_char *cp; u_int optlen; cp = bp + fixed_hdrlen; ND_PRINT((ndo, " <")); hlen -= fixed_hdrlen; while(1){ optlen = dccp_print_option(ndo, cp, hlen); if (!optlen) break; if (hlen <= optlen) break; hlen -= optlen; cp += optlen; ND_PRINT((ndo, ", ")); } ND_PRINT((ndo, ">")); } return; trunc: ND_PRINT((ndo, "%s", tstr)); return; }
/* * Print a single PDU. */ static void rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) { const rpki_rtr_pdu *pdu_header; u_int pdu_type, pdu_len, hexdump; const u_char *msg; pdu_header = (const rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = EXTRACT_32BITS(pdu_header->length); ND_TCHECK2(*tptr, pdu_len); hexdump = FALSE; ND_PRINT((ndo, "%sRPKI-RTRv%u, %s PDU (%u), length: %u", indent_string(8), pdu_header->version, tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), pdu_type, pdu_len)); switch (pdu_type) { /* * The following PDUs share the message format. */ case RPKI_RTR_SERIAL_NOTIFY_PDU: case RPKI_RTR_SERIAL_QUERY_PDU: case RPKI_RTR_END_OF_DATA_PDU: msg = (const u_char *)(pdu_header + 1); ND_PRINT((ndo, "%sSession ID: 0x%04x, Serial: %u", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.session_id), EXTRACT_32BITS(msg))); break; /* * The following PDUs share the message format. */ case RPKI_RTR_RESET_QUERY_PDU: case RPKI_RTR_CACHE_RESET_PDU: /* * Zero payload PDUs. */ break; case RPKI_RTR_CACHE_RESPONSE_PDU: ND_PRINT((ndo, "%sSession ID: 0x%04x", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.session_id))); break; case RPKI_RTR_IPV4_PREFIX_PDU: { const rpki_rtr_pdu_ipv4_prefix *pdu; pdu = (const rpki_rtr_pdu_ipv4_prefix *)tptr; ND_PRINT((ndo, "%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ipaddr_string(ndo, pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags)); } break; case RPKI_RTR_IPV6_PREFIX_PDU: { const rpki_rtr_pdu_ipv6_prefix *pdu; pdu = (const rpki_rtr_pdu_ipv6_prefix *)tptr; ND_PRINT((ndo, "%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ip6addr_string(ndo, pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags)); } break; case RPKI_RTR_ERROR_REPORT_PDU: { const rpki_rtr_pdu_error_report *pdu; u_int encapsulated_pdu_length, text_length, tlen, error_code; pdu = (const rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); ND_TCHECK2(*tptr, encapsulated_pdu_length); tlen = pdu_len; error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); ND_PRINT((ndo, "%sError code: %s (%u), Encapsulated PDU length: %u", indent_string(indent+2), tok2str(rpki_rtr_error_codes, "Unknown", error_code), error_code, encapsulated_pdu_length)); tptr += sizeof(*pdu); tlen -= sizeof(*pdu); /* * Recurse if there is an encapsulated PDU. */ if (encapsulated_pdu_length && (encapsulated_pdu_length <= tlen)) { ND_PRINT((ndo, "%s-----encapsulated PDU-----", indent_string(indent+4))); rpki_rtr_pdu_print(ndo, tptr, indent+2); } tptr += encapsulated_pdu_length; tlen -= encapsulated_pdu_length; /* * Extract, trail-zero and print the Error message. */ text_length = 0; if (tlen > 4) { text_length = EXTRACT_32BITS(tptr); tptr += 4; tlen -= 4; } ND_TCHECK2(*tptr, text_length); if (text_length && (text_length <= tlen )) { ND_PRINT((ndo, "%sError text: ", indent_string(indent+2))); fn_printn(ndo, tptr, text_length, ndo->ndo_snapend); } } break; default: /* * Unknown data, please hexdump. */ hexdump = TRUE; } /* do we also want to see a hex dump ? */ if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) { print_unknown_data(ndo,tptr,"\n\t ", pdu_len); } return; trunc: ND_PRINT((ndo, "|trunc")); return; }
static void krb4_print(netdissect_options *ndo, const u_char *cp) { register const struct krb *kp; u_char type; u_short len; #define PRINT if ((cp = c_print(ndo, cp, ndo->ndo_snapend)) == NULL) goto trunc /* True if struct krb is little endian */ #define IS_LENDIAN(kp) (((kp)->type & 0x01) != 0) #define KTOHSP(kp, cp) (IS_LENDIAN(kp) ? EXTRACT_LE_16BITS(cp) : EXTRACT_16BITS(cp)) kp = (const struct krb *)cp; if ((&kp->type) >= ndo->ndo_snapend) { ND_PRINT((ndo, "%s", tstr)); return; } type = kp->type & (0xFF << 1); ND_PRINT((ndo, " %s %s: ", IS_LENDIAN(kp) ? "le" : "be", tok2str(type2str, NULL, type))); switch (type) { case AUTH_MSG_KDC_REQUEST: if ((cp = krb4_print_hdr(ndo, cp)) == NULL) return; cp += 4; /* ctime */ ND_TCHECK(*cp); ND_PRINT((ndo, " %dmin ", *cp++ * 5)); PRINT; ND_PRINT((ndo, ".")); PRINT; break; case AUTH_MSG_APPL_REQUEST: cp += 2; ND_TCHECK(*cp); ND_PRINT((ndo, "v%d ", *cp++)); PRINT; ND_TCHECK(*cp); ND_PRINT((ndo, " (%d)", *cp++)); ND_TCHECK(*cp); ND_PRINT((ndo, " (%d)", *cp)); break; case AUTH_MSG_KDC_REPLY: if ((cp = krb4_print_hdr(ndo, cp)) == NULL) return; cp += 10; /* timestamp + n + exp + kvno */ ND_TCHECK2(*cp, sizeof(short)); len = KTOHSP(kp, cp); ND_PRINT((ndo, " (%d)", len)); break; case AUTH_MSG_ERR_REPLY: if ((cp = krb4_print_hdr(ndo, cp)) == NULL) return; cp += 4; /* timestamp */ ND_TCHECK2(*cp, sizeof(short)); ND_PRINT((ndo, " %s ", tok2str(kerr2str, NULL, KTOHSP(kp, cp)))); cp += 4; PRINT; break; default: ND_PRINT((ndo, "(unknown)")); break; } return; trunc: ND_PRINT((ndo, "%s", tstr)); }