static int cdp_print_addr(const u_char * p, int l) { int pt, pl, al, num; const u_char *endp = p + l; #ifdef INET6 static u_char prot_ipv6[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd }; #endif TCHECK2(*p, 2); num = EXTRACT_32BITS(p); p += 4; while (p < endp && num >= 0) { 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; 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; TCHECK2(*p, 4); if (p + 4 > endp) goto trunc; printf("IPv4 (%u) %s", num, ipaddr_string(p)); p += 4; } #ifdef INET6 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; TCHECK2(*p, al); if (p + al > endp) goto trunc; printf("IPv6 (%u) %s", num, ip6addr_string(p)); p += al; } #endif else { /* * Generic case: just print raw data */ TCHECK2(*p, pl); if (p + pl > endp) goto trunc; printf("pt=0x%02x, pl=%d, pb=", *(p - 2), pl); while (pl-- > 0) printf(" %02x", *p++); TCHECK2(*p, 2); if (p + 2 > endp) goto trunc; al = (*p << 8) + *(p + 1); printf(", al=%d, a=", al); p += 2; TCHECK2(*p, al); if (p + al > endp) goto trunc; while (al-- > 0) printf(" %02x", *p++); } num--; if (num) printf(" "); } return 0; trunc: return -1; }
/* * Print a single link state advertisement. If truncated return 1, else 0. */ static int ospf6_print_lsa(register const struct lsa6 *lsap) { register const struct rlalink6 *rlp; #if 0 register const struct tos_metric *tosp; #endif register const rtrid_t *ap; #if 0 register const struct aslametric *almp; register const struct mcla *mcp; #endif register const struct llsa *llsap; register const struct lsa6_prefix *lsapp; #if 0 register const u_int32_t *lp; #endif register u_int prefixes; register int bytelen; register u_int length, lsa_length; u_int32_t flags32; const u_int8_t *tptr; if (ospf6_print_lshdr(&lsap->ls_hdr)) return (1); TCHECK(lsap->ls_hdr.ls_length); length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); /* * The LSA length includes the length of the header; * it must have a value that's at least that length. * If it does, find the length of what follows the * header. */ if (length < sizeof(struct lsa6_hdr)) return (1); lsa_length = length - sizeof(struct lsa6_hdr); tptr = (u_int8_t *)lsap+sizeof(struct lsa6_hdr); switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { case LS_TYPE_ROUTER | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); TCHECK(lsap->lsa_un.un_rla.rla_options); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options))); printf(", RLA-Flags [%s]", bittok2str(ospf6_rla_flag_values, "none", lsap->lsa_un.un_rla.rla_flags)); rlp = lsap->lsa_un.un_rla.rla_link; while (lsa_length != 0) { if (lsa_length < sizeof (*rlp)) return (1); lsa_length -= sizeof (*rlp); TCHECK(*rlp); switch (rlp->link_type) { case RLA_TYPE_VIRTUAL: printf("\n\t Virtual Link: Neighbor Router-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", ipaddr_string(&rlp->link_nrtid), ipaddr_string(&rlp->link_nifid), ipaddr_string(&rlp->link_ifid)); break; case RLA_TYPE_ROUTER: printf("\n\t Neighbor Router-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", ipaddr_string(&rlp->link_nrtid), ipaddr_string(&rlp->link_nifid), ipaddr_string(&rlp->link_ifid)); break; case RLA_TYPE_TRANSIT: printf("\n\t Neighbor Network-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", ipaddr_string(&rlp->link_nrtid), ipaddr_string(&rlp->link_nifid), ipaddr_string(&rlp->link_ifid)); break; default: printf("\n\t Unknown Router Links Type 0x%02x", rlp->link_type); return (0); } printf(", metric %d", EXTRACT_16BITS(&rlp->link_metric)); rlp++; } break; case LS_TYPE_NETWORK | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); TCHECK(lsap->lsa_un.un_nla.nla_options); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options))); printf("\n\t Connected Routers:"); ap = lsap->lsa_un.un_nla.nla_router; while (lsa_length != 0) { if (lsa_length < sizeof (*ap)) return (1); lsa_length -= sizeof (*ap); TCHECK(*ap); printf("\n\t\t%s", ipaddr_string(ap)); ++ap; } break; case LS_TYPE_INTER_AP | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); printf(", metric %u", EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); tptr = (u_int8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; while (lsa_length != 0) { bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_ASE | LS_SCOPE_AS: if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); TCHECK(lsap->lsa_un.un_asla.asla_metric); flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); printf("\n\t Flags [%s]", bittok2str(ospf6_asla_flag_values, "none", flags32)); printf(" metric %u", EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & ASLA_MASK_METRIC); tptr = (u_int8_t *)lsap->lsa_un.un_asla.asla_prefix; lsapp = (struct lsa6_prefix *)tptr; bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; lsa_length -= bytelen; tptr += bytelen; if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { struct in6_addr *fwdaddr6; fwdaddr6 = (struct in6_addr *)tptr; if (lsa_length < sizeof (*fwdaddr6)) return (1); lsa_length -= sizeof (*fwdaddr6); TCHECK(*fwdaddr6); printf(" forward %s", ip6addr_string(fwdaddr6)); tptr += sizeof(*fwdaddr6); } if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { if (lsa_length < sizeof (u_int32_t)) return (1); lsa_length -= sizeof (u_int32_t); TCHECK(*(u_int32_t *)tptr); printf(" tag %s", ipaddr_string((u_int32_t *)tptr)); tptr += sizeof(u_int32_t); } if (lsapp->lsa_p_metric) { if (lsa_length < sizeof (u_int32_t)) return (1); lsa_length -= sizeof (u_int32_t); TCHECK(*(u_int32_t *)tptr); printf(" RefLSID: %s", ipaddr_string((u_int32_t *)tptr)); tptr += sizeof(u_int32_t); } break; case LS_TYPE_LINK: /* Link LSA */ llsap = &lsap->lsa_un.un_llsa; if (lsa_length < sizeof (llsap->llsa_priandopt)) return (1); lsa_length -= sizeof (llsap->llsa_priandopt); TCHECK(llsap->llsa_priandopt); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&llsap->llsa_options))); if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) return (1); lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); printf("\n\t Priority %d, Link-local address %s, Prefixes %d:", llsap->llsa_priority, ip6addr_string(&llsap->llsa_lladdr), prefixes); tptr = (u_int8_t *)llsap->llsa_prefix; while (prefixes > 0) { bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; prefixes--; lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: /* Intra-Area-Prefix LSA */ if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); ospf6_print_ls_type( EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), &lsap->lsa_un.un_intra_ap.intra_ap_lsid); if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); printf("\n\t Prefixes %d:", prefixes); tptr = (u_int8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; while (prefixes > 0) { bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; prefixes--; lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: if (ospf_print_grace_lsa(tptr, lsa_length) == -1) { return 1; } break; case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: if (ospf_print_te_lsa(tptr, lsa_length) == -1) { return 1; } break; default: if(!print_unknown_data(tptr, "\n\t ", lsa_length)) { return (1); } break; } return (0); trunc: return (1); }
void sunrpc_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2) { const struct sunrpc_msg *rp; const struct ip *ip; const struct ip6_hdr *ip6; uint32_t x; char srcid[20], dstid[20]; /*fits 32bit*/ rp = (const struct sunrpc_msg *)bp; if (!ndo->ndo_nflag) { nd_snprintf(srcid, sizeof(srcid), "0x%x", EXTRACT_BE_U_4(rp->rm_xid)); strlcpy(dstid, "sunrpc", sizeof(dstid)); } else { nd_snprintf(srcid, sizeof(srcid), "0x%x", EXTRACT_BE_U_4(rp->rm_xid)); nd_snprintf(dstid, sizeof(dstid), "0x%x", SUNRPC_PMAPPORT); } switch (IP_V((const struct ip *)bp2)) { case 4: ip = (const struct ip *)bp2; ND_PRINT("%s.%s > %s.%s: %u", ipaddr_string(ndo, ip->ip_src), srcid, ipaddr_string(ndo, ip->ip_dst), dstid, length); break; case 6: ip6 = (const struct ip6_hdr *)bp2; ND_PRINT("%s.%s > %s.%s: %u", ip6addr_string(ndo, ip6->ip6_src), srcid, ip6addr_string(ndo, ip6->ip6_dst), dstid, length); break; default: ND_PRINT("%s.%s > %s.%s: %u", "?", srcid, "?", dstid, length); break; } ND_PRINT(" %s", tok2str(proc2str, " proc #%u", EXTRACT_BE_U_4(rp->rm_call.cb_proc))); x = EXTRACT_BE_U_4(rp->rm_call.cb_rpcvers); if (x != 2) ND_PRINT(" [rpcver %u]", x); switch (EXTRACT_BE_U_4(rp->rm_call.cb_proc)) { case SUNRPC_PMAPPROC_SET: case SUNRPC_PMAPPROC_UNSET: case SUNRPC_PMAPPROC_GETPORT: case SUNRPC_PMAPPROC_CALLIT: x = EXTRACT_BE_U_4(rp->rm_call.cb_prog); if (!ndo->ndo_nflag) ND_PRINT(" %s", progstr(x)); else ND_PRINT(" %u", x); ND_PRINT(".%u", EXTRACT_BE_U_4(rp->rm_call.cb_vers)); break; } }
void mldv2_query_print(const u_char *bp, u_int len) { struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; u_int mrc, qqic; int mrd, qqi; int mant, exp; u_int nsrcs; u_int i; if (len < MLD_V2_QUERY_MINLEN) { printf(" [invalid len %d]", len); return; } TCHECK(icp->icmp6_data16[0]); mrc = ntohs(icp->icmp6_data16[0]); if (mrc & MLDV2_MRC_FLOAT) { mant = MLD_MRC_MANT(mrc); exp = MLD_MRC_EXP(mrc); mrd = MLDV2_MRD(mant, exp); } else { mrd = mrc; } if (vflag) { (void)printf(" [max resp delay=%d]", mrd); } TCHECK2(bp[8], sizeof(struct in6_addr)); printf(" [gaddr %s", ip6addr_string(&bp[8])); if (vflag) { TCHECK(bp[MLDV2_QUERY_QQIC]); if (bp[MLDV2_QUERY_QRV] & MLDV2_QUERY_QRV_SFLAG) { printf(" sflag"); } if (MLD_QRV(bp[MLDV2_QUERY_QRV])) { printf(" robustness=%d", MLD_QRV(bp[MLDV2_QUERY_QRV])); } qqic = bp[MLDV2_QUERY_QQIC]; if (qqic & MLDV2_QQIC_FLOAT) { mant = MLD_QQIC_MANT(qqic); exp = MLD_QQIC_EXP(qqic); qqi = MLDV2_QQI(mant, exp); } else { qqi = bp[MLDV2_QUERY_QQIC]; } printf(" qqi=%d", qqi); } TCHECK2(bp[MLDV2_QUERY_NSRCS], 2); nsrcs = ntohs(*(u_short *)&bp[MLDV2_QUERY_NSRCS]); if (nsrcs > 0) { if (len < MLD_V2_QUERY_MINLEN + nsrcs * sizeof(struct in6_addr)) printf(" [invalid number of sources]"); else if (vflag > 1) { printf(" {"); for (i = 0; i < nsrcs; i++) { TCHECK2(bp[MLDV2_QUERY_SRC0 + i * sizeof(struct in6_addr)], sizeof(struct in6_addr)); printf(" %s", ip6addr_string(&bp[MLDV2_QUERY_SRC0 + i * sizeof(struct in6_addr)])); } printf(" }"); } else printf(", %d source(s)", nsrcs); } printf("]"); return; trunc: (void)printf("[|icmp6]"); return; }
void sctp_print(const u_char *bp, const u_char *bp2, u_int sctpPacketLength) { const struct sctpHeader *sctpPktHdr; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif const void *endPacketPtr; u_short sourcePort, destPort; int chunkCount; const struct sctpChunkDesc *chunkDescPtr; const void *nextChunk; const char *sep; sctpPktHdr = (const struct sctpHeader*) bp; endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength; if( (u_long) endPacketPtr > (u_long) snapend) endPacketPtr = (const void *) snapend; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; #endif TCHECK(*sctpPktHdr); if (sctpPacketLength < sizeof(struct sctpHeader)) { (void)printf("truncated-sctp - %ld bytes missing!", (long)sctpPacketLength-sizeof(struct sctpHeader)); return; } sourcePort = EXTRACT_16BITS(&sctpPktHdr->source); destPort = EXTRACT_16BITS(&sctpPktHdr->destination); #ifdef INET6 if (ip6) { (void)printf("%s.%d > %s.%d: sctp", ip6addr_string(&ip6->ip6_src), sourcePort, ip6addr_string(&ip6->ip6_dst), destPort); } else #endif { (void)printf("%s.%d > %s.%d: sctp", ipaddr_string(&ip->ip_src), sourcePort, ipaddr_string(&ip->ip_dst), destPort); } fflush(stdout); if (vflag >= 2) sep = "\n\t"; else sep = " ("; for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *) ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader)); chunkDescPtr != NULL && ( (const void *) ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc)) <= endPacketPtr); chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++) { u_int16_t chunkLength; const u_char *chunkEnd; u_int16_t align; TCHECK(*chunkDescPtr); chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength); if (chunkLength < sizeof(*chunkDescPtr)) { printf("%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength); break; } TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength); chunkEnd = ((const u_char*)chunkDescPtr + chunkLength); align=chunkLength % 4; if (align != 0) align = 4 - align; nextChunk = (const void *) (chunkEnd + align); printf("%s%d) ", sep, chunkCount+1); switch (chunkDescPtr->chunkID) { case SCTP_DATA : { const struct sctpDataPart *dataHdrPtr; printf("[DATA] "); if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) printf("(U)"); if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) printf("(B)"); if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) printf("(E)"); if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) || ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) printf(" "); dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1); printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN)); printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId)); printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence)); printf("[PPID 0x%x] ", EXTRACT_32BITS(&dataHdrPtr->payloadtype)); fflush(stdout); if (vflag >= 2) { const u_char *payloadPtr; printf("[Payload"); if (!suppress_default_print) { payloadPtr = (const u_char *) (++dataHdrPtr); printf(":"); if (htons(chunkDescPtr->chunkLength) < sizeof(struct sctpDataPart)+ sizeof(struct sctpChunkDesc)+1) { printf("bogus chunk length %u]", htons(chunkDescPtr->chunkLength)); return; } default_print(payloadPtr, htons(chunkDescPtr->chunkLength) - (sizeof(struct sctpDataPart)+ sizeof(struct sctpChunkDesc))); } else printf("]"); } break; } case SCTP_INITIATION : { const struct sctpInitiation *init; printf("[INIT] "); init=(const struct sctpInitiation*)(chunkDescPtr+1); printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); #if(0) if( (init+1) < chunkEnd ) printf(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif break; } case SCTP_INITIATION_ACK : { const struct sctpInitiation *init; printf("[INIT ACK] "); init=(const struct sctpInitiation*)(chunkDescPtr+1); printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); #if(0) if( (init+1) < chunkEnd ) printf(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif break; } case SCTP_SELECTIVE_ACK: { const struct sctpSelectiveAck *sack; const struct sctpSelectiveFrag *frag; int fragNo, tsnNo; const u_char *dupTSN; printf("[SACK] "); sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1); printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN)); printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd)); printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc)); printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns)); for (frag = ( (const struct sctpSelectiveFrag *) ((const struct sctpSelectiveAck *) sack+1)), fragNo=0; (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc); frag++, fragNo++) printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ", fragNo+1, EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart), EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd)); for (dupTSN = (const u_char *)frag, tsnNo=0; (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns); dupTSN += 4, tsnNo++) printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, EXTRACT_32BITS(dupTSN)); break; } case SCTP_HEARTBEAT_REQUEST : { const struct sctpHBsender *hb; hb=(const struct sctpHBsender*)chunkDescPtr; printf("[HB REQ] "); break; } case SCTP_HEARTBEAT_ACK : printf("[HB ACK] "); break; case SCTP_ABORT_ASSOCIATION : printf("[ABORT] "); break; case SCTP_SHUTDOWN : printf("[SHUTDOWN] "); break; case SCTP_SHUTDOWN_ACK : printf("[SHUTDOWN ACK] "); break; case SCTP_OPERATION_ERR : printf("[OP ERR] "); break; case SCTP_COOKIE_ECHO : printf("[COOKIE ECHO] "); break; case SCTP_COOKIE_ACK : printf("[COOKIE ACK] "); break; case SCTP_ECN_ECHO : printf("[ECN ECHO] "); break; case SCTP_ECN_CWR : printf("[ECN CWR] "); break; case SCTP_SHUTDOWN_COMPLETE : printf("[SHUTDOWN COMPLETE] "); break; case SCTP_FORWARD_CUM_TSN : printf("[FOR CUM TSN] "); break; case SCTP_RELIABLE_CNTL : printf("[REL CTRL] "); break; case SCTP_RELIABLE_CNTL_ACK : printf("[REL CTRL ACK] "); break; default : printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID); return; } if (vflag < 2) sep = ", ("; } return; trunc: printf("[|sctp]"); return; }
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 */ }
void icmp6_opt_print(register const u_char *bp, int resid) { register const struct nd_opt_hdr *op; register const struct nd_opt_hdr *opl; /* why there's no struct? */ register const struct nd_opt_prefix_info *opp; register const struct icmp6_opts_redirect *opr; register const struct nd_opt_mtu *opm; register const u_char *ep; int opts_len; #if 0 register const struct ip6_hdr *ip; register const char *str; register const struct ip6_hdr *oip; register const struct udphdr *ouh; register int hlen, dport; char buf[256]; #endif #if 0 #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc #endif #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return op = (struct nd_opt_hdr *)bp; #if 0 ip = (struct ip6_hdr *)bp2; oip = &dp->icmp6_ip6; str = buf; #endif /* 'ep' points to the end of avaible data. */ ep = snapend; ECHECK(op->nd_opt_len); if (resid <= 0) return; if (op->nd_opt_len == 0) goto trunc; if (bp + (op->nd_opt_len << 3) > ep) goto trunc; switch (op->nd_opt_type) { case ND_OPT_SOURCE_LINKADDR: opl = (struct nd_opt_hdr *)op; #if 1 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) goto trunc; #else TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); #endif printf("(src lladdr: %s", etheraddr_string((u_char *)(opl + 1))); if (opl->nd_opt_len != 1) printf("!"); printf(")"); icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), resid - (op->nd_opt_len << 3)); break; case ND_OPT_TARGET_LINKADDR: opl = (struct nd_opt_hdr *)op; #if 1 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) goto trunc; #else TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); #endif printf("(tgt lladdr: %s", etheraddr_string((u_char *)(opl + 1))); if (opl->nd_opt_len != 1) printf("!"); printf(")"); icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), resid - (op->nd_opt_len << 3)); break; case ND_OPT_PREFIX_INFORMATION: opp = (struct nd_opt_prefix_info *)op; TCHECK(opp->nd_opt_pi_prefix); printf("(prefix info: "); if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) printf("L"); if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) printf("A"); if (opp->nd_opt_pi_flags_reserved) printf(" "); printf("valid_ltime="); if ((u_int32_t)ntohl(opp->nd_opt_pi_valid_time) == ~0U) printf("infinity"); else { printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_valid_time)); } printf(", "); printf("preferred_ltime="); if ((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time) == ~0U) printf("infinity"); else { printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_preferred_time)); } printf(", "); printf("prefix=%s/%d", ip6addr_string(&opp->nd_opt_pi_prefix), opp->nd_opt_pi_prefix_len); if (opp->nd_opt_pi_len != 4) printf("!"); printf(")"); icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), resid - (op->nd_opt_len << 3)); break; case ND_OPT_REDIRECTED_HEADER: opr = (struct icmp6_opts_redirect *)op; printf("(redirect)"); /* xxx */ icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), resid - (op->nd_opt_len << 3)); break; case ND_OPT_MTU: opm = (struct nd_opt_mtu *)op; TCHECK(opm->nd_opt_mtu_mtu); printf("(mtu: "); printf("mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu)); if (opm->nd_opt_mtu_len != 1) printf("!"); printf(")"); icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), resid - (op->nd_opt_len << 3)); break; default: opts_len = op->nd_opt_len; printf("(unknown opt_type=%d, opt_len=%d)", op->nd_opt_type, opts_len); if (opts_len == 0) opts_len = 1; /* XXX */ icmp6_opt_print((const u_char *)op + (opts_len << 3), resid - (opts_len << 3)); break; } return; trunc: fputs("[ndp opt]", stdout); return; #if 0 #undef TCHECK #endif #undef ECHECK }
/** * dccp_print - show dccp packet * @bp - beginning of dccp packet * @data2 - beginning of enclosing * @len - lenght of ip packet */ void dccp_print(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 extlen = 0; 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*/ cp = (const u_char *)(dh + 1); if (cp > snapend) { printf("[Invalid packet|dccp]"); return; } if (len < sizeof(struct dccp_hdr)) { printf("truncated-dccp - %ld bytes missing!", (long)len - sizeof(struct dccp_hdr)); return; } sport = EXTRACT_16BITS(&dh->dccph_sport); dport = EXTRACT_16BITS(&dh->dccph_dport); hlen = dh->dccph_doff * 4; #ifdef INET6 if (ip6) { (void)printf("%s.%d > %s.%d: ", ip6addr_string(&ip6->ip6_src), sport, ip6addr_string(&ip6->ip6_dst), dport); } else #endif /*INET6*/ { (void)printf("%s.%d > %s.%d: ", ipaddr_string(&ip->ip_src), sport, ipaddr_string(&ip->ip_dst), dport); } fflush(stdout); if (qflag) { (void)printf(" %d", len - hlen); if (hlen > len) { (void)printf("dccp [bad hdr length %u - too long, > %u]", hlen, len); } return; } /* other variables in generic header */ if (vflag) { (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); } /* checksum calculation */ if (vflag && TTEST2(bp[0], len)) { u_int16_t sum = 0, dccp_sum; dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); (void)printf("cksum 0x%04x ", dccp_sum); if (IP_V(ip) == 4) sum = dccp_cksum(ip, dh, len); #ifdef INET6 else if (IP_V(ip) == 6) sum = dccp6_cksum(ip6, dh, len); #endif if (sum != 0) (void)printf("(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum)); else (void)printf("(correct), "); } switch (DCCPH_TYPE(dh)) { case DCCP_PKT_REQUEST: { struct dccp_hdr_request *dhr = (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh)); TCHECK(*dhr); (void)printf("request (service=%d) ", EXTRACT_32BITS(&dhr->dccph_req_service)); extlen += 4; break; } case DCCP_PKT_RESPONSE: { struct dccp_hdr_response *dhr = (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh)); TCHECK(*dhr); (void)printf("response (service=%d) ", EXTRACT_32BITS(&dhr->dccph_resp_service)); extlen += 12; break; } case DCCP_PKT_DATA: (void)printf("data "); break; case DCCP_PKT_ACK: { (void)printf("ack "); extlen += 8; break; } case DCCP_PKT_DATAACK: { (void)printf("dataack "); extlen += 8; break; } case DCCP_PKT_CLOSEREQ: (void)printf("closereq "); extlen += 8; break; case DCCP_PKT_CLOSE: (void)printf("close "); extlen += 8; break; case DCCP_PKT_RESET: { struct dccp_hdr_reset *dhr = (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh)); TCHECK(*dhr); (void)printf("reset (code=%s) ", dccp_reset_code(dhr->dccph_reset_code)); extlen += 12; break; } case DCCP_PKT_SYNC: (void)printf("sync "); extlen += 8; break; case DCCP_PKT_SYNCACK: (void)printf("syncack "); extlen += 8; break; default: (void)printf("invalid "); break; } if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST)) dccp_print_ack_no(bp); if (vflag < 2) return; (void)printf("seq %" PRIu64, dccp_seqno(dh)); /* process options */ if (hlen > dccp_basic_hdr_len(dh) + extlen){ const u_char *cp; u_int optlen; cp = bp + dccp_basic_hdr_len(dh) + extlen; printf(" <"); hlen -= dccp_basic_hdr_len(dh) + extlen; while(1){ TCHECK(*cp); optlen = dccp_print_option(cp); if (!optlen) goto trunc2; if (hlen <= optlen) break; hlen -= optlen; cp += optlen; printf(", "); } printf(">"); } return; trunc: printf("%s", tstr); trunc2: return; }
/* * Print a single PDU. */ static u_int rpki_rtr_pdu_print(netdissect_options *ndo, const u_char *tptr, const u_int len, const u_char recurse, const u_int indent) { const rpki_rtr_pdu *pdu_header; u_int pdu_type, pdu_len, hexdump; const u_char *msg; /* Protocol Version */ ND_TCHECK_1(tptr); if (GET_U_1(tptr) != 0) { /* Skip the rest of the input buffer because even if this is * a well-formed PDU of a future RPKI-Router protocol version * followed by a well-formed PDU of RPKI-Router protocol * version 0, there is no way to know exactly how to skip the * current PDU. */ ND_PRINT("%sRPKI-RTRv%u (unknown)", indent_string(8), GET_U_1(tptr)); return len; } if (len < sizeof(rpki_rtr_pdu)) { ND_PRINT("(%u bytes is too few to decode)", len); goto invalid; } ND_TCHECK_LEN(tptr, sizeof(rpki_rtr_pdu)); pdu_header = (const rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = GET_BE_U_4(pdu_header->length); /* Do not check bounds with pdu_len yet, do it in the case blocks * below to make it possible to decode at least the beginning of * a truncated Error Report PDU or a truncated encapsulated PDU. */ hexdump = FALSE; ND_PRINT("%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); if (pdu_len < sizeof(rpki_rtr_pdu) || pdu_len > len) goto invalid; 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: if (pdu_len != sizeof(rpki_rtr_pdu) + 4) goto invalid; ND_TCHECK_LEN(tptr, pdu_len); msg = (const u_char *)(pdu_header + 1); ND_PRINT("%sSession ID: 0x%04x, Serial: %u", indent_string(indent+2), GET_BE_U_2(pdu_header->u.session_id), GET_BE_U_4(msg)); break; /* * The following PDUs share the message format. */ case RPKI_RTR_RESET_QUERY_PDU: case RPKI_RTR_CACHE_RESET_PDU: if (pdu_len != sizeof(rpki_rtr_pdu)) goto invalid; /* no additional boundary to check */ /* * Zero payload PDUs. */ break; case RPKI_RTR_CACHE_RESPONSE_PDU: if (pdu_len != sizeof(rpki_rtr_pdu)) goto invalid; /* no additional boundary to check */ ND_PRINT("%sSession ID: 0x%04x", indent_string(indent+2), GET_BE_U_2(pdu_header->u.session_id)); break; case RPKI_RTR_IPV4_PREFIX_PDU: { const rpki_rtr_pdu_ipv4_prefix *pdu; if (pdu_len != sizeof(rpki_rtr_pdu) + 12) goto invalid; ND_TCHECK_LEN(tptr, pdu_len); pdu = (const rpki_rtr_pdu_ipv4_prefix *)tptr; ND_PRINT("%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, GET_BE_U_4(pdu->as), pdu->flags); } break; case RPKI_RTR_IPV6_PREFIX_PDU: { const rpki_rtr_pdu_ipv6_prefix *pdu; if (pdu_len != sizeof(rpki_rtr_pdu) + 24) goto invalid; ND_TCHECK_LEN(tptr, pdu_len); pdu = (const rpki_rtr_pdu_ipv6_prefix *)tptr; ND_PRINT("%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, GET_BE_U_4(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; tlen = sizeof(rpki_rtr_pdu); /* Do not test for the "Length of Error Text" data element yet. */ if (pdu_len < tlen + 4) goto invalid; ND_TCHECK_LEN(tptr, tlen + 4); /* Safe up to and including the "Length of Encapsulated PDU" * data element, more data elements may be present. */ pdu = (const rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = GET_BE_U_4(pdu->encapsulated_pdu_length); tlen += 4; error_code = GET_BE_U_2(pdu->pdu_header.u.error_code); ND_PRINT("%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); if (encapsulated_pdu_length) { /* Section 5.10 of RFC 6810 says: * "An Error Report PDU MUST NOT be sent for an Error Report PDU." * * However, as far as the protocol encoding goes Error Report PDUs can * happen to be nested in each other, however many times, in which case * the decoder should still print such semantically incorrect PDUs. * * That said, "the Erroneous PDU field MAY be truncated" (ibid), thus * to keep things simple this implementation decodes only the two * outermost layers of PDUs and makes bounds checks in the outer and * the inner PDU independently. */ if (pdu_len < tlen + encapsulated_pdu_length) goto invalid; if (! recurse) { ND_TCHECK_LEN(tptr, tlen + encapsulated_pdu_length); } else { ND_PRINT("%s-----encapsulated PDU-----", indent_string(indent+4)); rpki_rtr_pdu_print(ndo, tptr + tlen, encapsulated_pdu_length, 0, indent + 2); } tlen += encapsulated_pdu_length; } if (pdu_len < tlen + 4) goto invalid; ND_TCHECK_LEN(tptr, tlen + 4); /* Safe up to and including the "Length of Error Text" data element, * one more data element may be present. */ /* * Extract, trail-zero and print the Error message. */ text_length = GET_BE_U_4(tptr + tlen); tlen += 4; if (text_length) { if (pdu_len < tlen + text_length) goto invalid; /* nd_printn() makes the bounds check */ ND_PRINT("%sError text: ", indent_string(indent+2)); if (nd_printn(ndo, tptr + tlen, text_length, ndo->ndo_snapend)) goto trunc; } } break; default: ND_TCHECK_LEN(tptr, pdu_len); /* * 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 pdu_len; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(tptr, len); return len; trunc: nd_print_trunc(ndo); return len; }
int ldp_tlv_print(register const u_char *tptr) { struct ldp_tlv_header { u_int8_t type[2]; u_int8_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; tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ printf("\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: printf("\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: printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr)); break; #ifdef INET6 case LDP_TLV_IPV6_TRANSPORT_ADDR: printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr)); break; #endif case LDP_TLV_CONFIG_SEQ_NUMBER: printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)); break; case LDP_TLV_ADDRESS_LIST: af = EXTRACT_16BITS(tptr); tptr+=AFNUM_LEN; tlv_tlen -= AFNUM_LEN; printf("\n\t Address Family: "); if (af == AFNUM_INET) { printf("IPv4, addresses:"); while(tlv_tlen >= sizeof(struct in_addr)) { printf(" %s",ipaddr_string(tptr)); tlv_tlen-=sizeof(struct in_addr); tptr+=sizeof(struct in_addr); } } #ifdef INET6 else if (af == AFNUM_INET6) { printf("IPv6, addresses:"); while(tlv_tlen >= sizeof(struct in6_addr)) { printf(" %s",ip6addr_string(tptr)); tlv_tlen-=sizeof(struct in6_addr); tptr+=sizeof(struct in6_addr); } } #endif break; case LDP_TLV_COMMON_SESSION: printf("\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: fec_type = *tptr; printf("\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), fec_type); tptr+=1; switch(fec_type) { case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: af = EXTRACT_16BITS(tptr); tptr+=2; if (af == AFNUM_INET) { i=decode_prefix4(tptr,buf,sizeof(buf)); printf(": IPv4 prefix %s",buf); } #ifdef INET6 else if (af == AFNUM_INET6) { i=decode_prefix6(tptr,buf,sizeof(buf)); printf(": IPv6 prefix %s",buf); } #endif break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: if (!TTEST2(*tptr, 11)) goto trunc; vc_info_len = *(tptr+2); printf(": %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 == 0) /* infinite loop protection */ break; tptr+=11; if (!TTEST2(*tptr, vc_info_len)) goto trunc; 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; printf("\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: printf(": %u",EXTRACT_16BITS(tptr+2)); break; case LDP_FEC_MARTINI_IFPARM_DESC: printf(": "); for (idx = 2; idx < vc_info_tlv_len; idx++) safeputchar(*(tptr+idx)); break; case LDP_FEC_MARTINI_IFPARM_VCCV: printf("\n\t\t Control Channels (0x%02x) = [%s]", *(tptr+2), bittok2str(ldp_fec_martini_ifparm_vccv_cc_values,"none",*(tptr+2))); printf("\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(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: printf("\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff); break; case LDP_TLV_STATUS: ui = EXTRACT_32BITS(tptr); tptr+=4; printf("\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) printf(", causing Message ID: 0x%08x", ui); break; case LDP_TLV_FT_SESSION: ft_flags = EXTRACT_16BITS(tptr); printf("\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) printf(", Reconnect Timeout: %ums", ui); tptr+=4; ui = EXTRACT_32BITS(tptr); if (ui) printf(", Recovery Time: %ums", ui); 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 (vflag <= 1) print_unknown_data(tptr,"\n\t ",tlv_tlen); break; } return(tlv_len+4); /* Type & Length fields not included */ trunc: printf("\n\t\t packet exceeded snapshot"); return 0; }
static void ip6_opt_print(netdissect_options *ndo, const u_char *bp, int len) { int i; int optlen = 0; if (len == 0) return; for (i = 0; i < len; i += optlen) { if (bp[i] == IP6OPT_PAD1) optlen = 1; else { if (i + 1 < len) optlen = bp[i + 1] + 2; else goto trunc; } if (i + optlen > len) goto trunc; switch (bp[i]) { case IP6OPT_PAD1: ND_PRINT((ndo, "(pad1)")); break; case IP6OPT_PADN: if (len - i < IP6OPT_MINLEN) { ND_PRINT((ndo, "(padn: trunc)")); goto trunc; } ND_PRINT((ndo, "(padn)")); break; case IP6OPT_ROUTER_ALERT: if (len - i < IP6OPT_RTALERT_LEN) { ND_PRINT((ndo, "(rtalert: trunc)")); goto trunc; } if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { ND_PRINT((ndo, "(rtalert: invalid len %d)", bp[i + 1])); goto trunc; } ND_PRINT((ndo, "(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2]))); break; case IP6OPT_JUMBO: if (len - i < IP6OPT_JUMBO_LEN) { ND_PRINT((ndo, "(jumbo: trunc)")); goto trunc; } if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { ND_PRINT((ndo, "(jumbo: invalid len %d)", bp[i + 1])); goto trunc; } ND_PRINT((ndo, "(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2]))); break; case IP6OPT_HOME_ADDRESS: if (len - i < IP6OPT_HOMEADDR_MINLEN) { ND_PRINT((ndo, "(homeaddr: trunc)")); goto trunc; } if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) { ND_PRINT((ndo, "(homeaddr: invalid len %d)", bp[i + 1])); goto trunc; } ND_PRINT((ndo, "(homeaddr: %s", ip6addr_string(ndo, &bp[i + 2]))); if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) { ip6_sopt_print(ndo, &bp[i + IP6OPT_HOMEADDR_MINLEN], (optlen - IP6OPT_HOMEADDR_MINLEN)); } ND_PRINT((ndo, ")")); break; default: if (len - i < IP6OPT_MINLEN) { ND_PRINT((ndo, "(type %d: trunc)", bp[i])); goto trunc; } ND_PRINT((ndo, "(opt_type 0x%02x: len=%d)", bp[i], bp[i + 1])); break; } } ND_PRINT((ndo, " ")); return; trunc: ND_PRINT((ndo, "[trunc] ")); }
/* * Print dhcp6 packets */ void dhcp6_print(const u_char *cp, u_int length) { struct dhcp6 *dh6; struct dhcp6_relay *dh6relay; const u_char *ep; u_char *extp; const char *name; printf("dhcp6"); ep = (u_char *)snapend; if (cp + length < ep) ep = cp + length; dh6 = (struct dhcp6 *)cp; dh6relay = (struct dhcp6_relay *)cp; TCHECK(dh6->dh6_xid); switch (dh6->dh6_msgtype) { case DH6_SOLICIT: name = "solicit"; break; case DH6_ADVERTISE: name = "advertise"; break; case DH6_REQUEST: name = "request"; break; case DH6_CONFIRM: name = "confirm"; break; case DH6_RENEW: name = "renew"; break; case DH6_REBIND: name = "rebind"; break; case DH6_REPLY: name = "reply"; break; case DH6_RELEASE: name = "release"; break; case DH6_DECLINE: name = "decline"; break; case DH6_RECONFIGURE: name = "reconfigure"; break; case DH6_INFORM_REQ: name= "inf-req"; break; case DH6_RELAY_FORW: name= "relay-fwd"; break; case DH6_RELAY_REPLY: name= "relay-reply"; break; default: name = NULL; break; } if (!vflag) { if (name) printf(" %s", name); else if (dh6->dh6_msgtype != DH6_RELAY_FORW && dh6->dh6_msgtype != DH6_RELAY_REPLY) { printf(" msgtype-%u", dh6->dh6_msgtype); } return; } /* XXX relay agent messages have to be handled differently */ if (name) printf(" %s (", name); /*)*/ else printf(" msgtype-%u (", dh6->dh6_msgtype); /*)*/ if (dh6->dh6_msgtype != DH6_RELAY_FORW && dh6->dh6_msgtype != DH6_RELAY_REPLY) { printf("xid=%x", EXTRACT_32BITS(&dh6->dh6_xid) & DH6_XIDMASK); extp = (u_char *)(dh6 + 1); dhcp6opt_print(extp, ep); } else { /* relay messages */ struct in6_addr addr6; TCHECK(dh6relay->dh6relay_peeraddr); memcpy(&addr6, dh6relay->dh6relay_linkaddr, sizeof (addr6)); printf("linkaddr=%s", ip6addr_string(&addr6)); memcpy(&addr6, dh6relay->dh6relay_peeraddr, sizeof (addr6)); printf(" peeraddr=%s", ip6addr_string(&addr6)); dhcp6opt_print((u_char *)(dh6relay + 1), ep); } /*(*/ printf(")"); return; trunc: printf("[|dhcp6]"); }
static void dhcp6opt_print(const u_char *cp, const u_char *ep) { struct dhcp6opt *dh6o; u_char *tp; size_t i; u_int16_t opttype; size_t optlen; u_int16_t val16; u_int32_t val32; struct dhcp6_ia ia; struct dhcp6_ia_prefix ia_prefix; struct dhcp6_ia_addr ia_addr; struct dhcp6_auth authopt; u_int authinfolen, authrealmlen; if (cp == ep) return; while (cp < ep) { if (ep < cp + sizeof(*dh6o)) goto trunc; dh6o = (struct dhcp6opt *)cp; optlen = EXTRACT_16BITS(&dh6o->dh6opt_len); if (ep < cp + sizeof(*dh6o) + optlen) goto trunc; opttype = EXTRACT_16BITS(&dh6o->dh6opt_type); printf(" (%s", dhcp6opt_name(opttype)); switch (opttype) { case DH6OPT_CLIENTID: case DH6OPT_SERVERID: if (optlen < 2) { /*(*/ printf(" ?)"); break; } tp = (u_char *)(dh6o + 1); switch (EXTRACT_16BITS(tp)) { case 1: if (optlen >= 2 + 6) { printf(" hwaddr/time type %u time %u ", EXTRACT_16BITS(&tp[2]), EXTRACT_32BITS(&tp[4])); for (i = 8; i < optlen; i++) printf("%02x", tp[i]); /*(*/ printf(")"); } else { /*(*/ printf(" ?)"); } break; case 2: if (optlen >= 2 + 8) { printf(" vid "); for (i = 2; i < 2 + 8; i++) printf("%02x", tp[i]); /*(*/ printf(")"); } else { /*(*/ printf(" ?)"); } break; case 3: if (optlen >= 2 + 2) { printf(" hwaddr type %u ", EXTRACT_16BITS(&tp[2])); for (i = 4; i < optlen; i++) printf("%02x", tp[i]); /*(*/ printf(")"); } else { /*(*/ printf(" ?)"); } break; default: printf(" type %d)", EXTRACT_16BITS(tp)); break; } break; case DH6OPT_IA_ADDR: if (optlen < sizeof(ia_addr) - 4) { printf(" ?)"); break; } memcpy(&ia_addr, (u_char *)dh6o, sizeof(ia_addr)); printf(" %s", ip6addr_string(&ia_addr.dh6opt_ia_addr_addr)); ia_addr.dh6opt_ia_addr_pltime = ntohl(ia_addr.dh6opt_ia_addr_pltime); ia_addr.dh6opt_ia_addr_vltime = ntohl(ia_addr.dh6opt_ia_addr_vltime); printf(" pltime:%lu vltime:%lu", (unsigned long)ia_addr.dh6opt_ia_addr_pltime, (unsigned long)ia_addr.dh6opt_ia_addr_vltime); if (optlen > sizeof(ia_addr) - 4) { /* there are sub-options */ dhcp6opt_print((u_char *)dh6o + sizeof(ia_addr), (u_char *)(dh6o + 1) + optlen); } printf(")"); break; case DH6OPT_ORO: if (optlen % 2) { printf(" ?)"); break; } tp = (u_char *)(dh6o + 1); for (i = 0; i < optlen; i += 2) { u_int16_t opt; memcpy(&opt, &tp[i], sizeof(opt)); printf(" %s", dhcp6opt_name(ntohs(opt))); } printf(")"); break; case DH6OPT_PREFERENCE: if (optlen != 1) { printf(" ?)"); break; } printf(" %d)", *((u_char *)(dh6o + 1) + 1)); break; case DH6OPT_ELAPSED_TIME: if (optlen != 2) { printf(" ?)"); break; } memcpy(&val16, dh6o + 1, sizeof(val16)); val16 = ntohs(val16); printf(" %d)", (int)val16); break; case DH6OPT_RELAY_MSG: printf(" ("); dhcp6_print((const u_char *)(dh6o + 1), optlen); printf(")"); break; case DH6OPT_AUTH: if (optlen < sizeof(authopt) - sizeof(*dh6o)) { printf(" ?)"); break; } memcpy(&authopt, dh6o, sizeof(authopt)); switch (authopt.dh6opt_auth_proto) { case DH6OPT_AUTHPROTO_DELAYED: printf(" proto: delayed"); break; case DH6OPT_AUTHPROTO_RECONFIG: printf(" proto: reconfigure"); break; default: printf(" proto: %d", authopt.dh6opt_auth_proto); break; } switch (authopt.dh6opt_auth_alg) { case DH6OPT_AUTHALG_HMACMD5: /* XXX: may depend on the protocol */ printf(", alg: HMAC-MD5"); break; default: printf(", alg: %d", authopt.dh6opt_auth_alg); break; } switch (authopt.dh6opt_auth_rdm) { case DH6OPT_AUTHRDM_MONOCOUNTER: printf(", RDM: mono"); break; default: printf(", RDM: %d", authopt.dh6opt_auth_rdm); break; } tp = (u_char *)&authopt.dh6opt_auth_rdinfo; printf(", RD:"); for (i = 0; i < 4; i++, tp += sizeof(val16)) printf(" %04x", EXTRACT_16BITS(tp)); /* protocol dependent part */ tp = (u_char *)dh6o + sizeof(authopt); authinfolen = optlen + sizeof(*dh6o) - sizeof(authopt); switch (authopt.dh6opt_auth_proto) { case DH6OPT_AUTHPROTO_DELAYED: if (authinfolen == 0) break; if (authinfolen < 20) { printf(" ??"); break; } authrealmlen = authinfolen - 20; if (authrealmlen > 0) { printf(", realm: "); } for (i = 0; i < authrealmlen; i++, tp++) printf("%02x", *tp); printf(", key ID: %08x", EXTRACT_32BITS(tp)); tp += 4; printf(", HMAC-MD5:"); for (i = 0; i < 4; i++, tp+= 4) printf(" %08x", EXTRACT_32BITS(tp)); break; case DH6OPT_AUTHPROTO_RECONFIG: if (authinfolen != 17) { printf(" ??"); break; } switch (*tp++) { case DH6OPT_AUTHRECONFIG_KEY: printf(" reconfig-key"); break; case DH6OPT_AUTHRECONFIG_HMACMD5: printf(" type: HMAC-MD5"); break; default: printf(" type: ??"); break; } printf(" value:"); for (i = 0; i < 4; i++, tp+= 4) printf(" %08x", EXTRACT_32BITS(tp)); break; default: printf(" ??"); break; } printf(")"); break; case DH6OPT_RAPID_COMMIT: /* nothing todo */ printf(")"); break; case DH6OPT_INTERFACE_ID: /* * Since we cannot predict the encoding, print hex dump * at most 10 characters. */ for (i = 0; i < optlen && i < 10; i++) printf("%02x", ((u_char *)(dh6o + 1))[i]); break; case DH6OPT_RECONF_MSG: tp = (u_char *)(dh6o + 1); switch (*tp) { case DH6_RENEW: printf(" for renew)"); break; case DH6_INFORM_REQ: printf(" for inf-req)"); break; default: printf(" for ?\?\?(%02x))", *tp); break; } break; case DH6OPT_RECONF_ACCEPT: /* nothing todo */ printf(")"); break; case DH6OPT_SIP_SERVER_A: case DH6OPT_DNS: case DH6OPT_NTP_SERVERS: case DH6OPT_NIS_SERVERS: case DH6OPT_NISP_SERVERS: case DH6OPT_BCMCS_SERVER_A: if (optlen % 16) { printf(" ?)"); break; } tp = (u_char *)(dh6o + 1); for (i = 0; i < optlen; i += 16) printf(" %s", ip6addr_string(&tp[i])); printf(")"); break; case DH6OPT_STATUS_CODE: if (optlen < 2) { printf(" ?)"); break; } memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16)); val16 = ntohs(val16); printf(" %s)", dhcp6stcode(val16)); break; case DH6OPT_IA_NA: case DH6OPT_IA_PD: if (optlen < sizeof(ia) - 4) { printf(" ?)"); break; } memcpy(&ia, (u_char *)dh6o, sizeof(ia)); ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid); ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1); ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2); printf(" IAID:%lu T1:%lu T2:%lu", (unsigned long)ia.dh6opt_ia_iaid, (unsigned long)ia.dh6opt_ia_t1, (unsigned long)ia.dh6opt_ia_t2); if (optlen > sizeof(ia) - 4) { /* there are sub-options */ dhcp6opt_print((u_char *)dh6o + sizeof(ia), (u_char *)(dh6o + 1) + optlen); } printf(")"); break; case DH6OPT_IA_PD_PREFIX: if (optlen < sizeof(ia_prefix) - 4) { printf(" ?)"); break; } memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix)); printf(" %s/%d", ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr), ia_prefix.dh6opt_ia_prefix_plen); ia_prefix.dh6opt_ia_prefix_pltime = ntohl(ia_prefix.dh6opt_ia_prefix_pltime); ia_prefix.dh6opt_ia_prefix_vltime = ntohl(ia_prefix.dh6opt_ia_prefix_vltime); printf(" pltime:%lu vltime:%lu", (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime, (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime); if (optlen > sizeof(ia_prefix) - 4) { /* there are sub-options */ dhcp6opt_print((u_char *)dh6o + sizeof(ia_prefix), (u_char *)(dh6o + 1) + optlen); } printf(")"); break; case DH6OPT_LIFETIME: if (optlen != 4) { printf(" ?)"); break; } memcpy(&val32, dh6o + 1, sizeof(val32)); val32 = ntohl(val32); printf(" %d)", (int)val32); break; default: printf(")"); break; } cp += sizeof(*dh6o) + optlen; } return; trunc: printf("[|dhcp6ext]"); }
void tcp_print(register const u_char *bp, register u_int length, register const u_char *bp2, int fragmented) { register const struct tcphdr *tp; register const struct ip *ip; register u_char flags; register u_int hlen; register char ch; u_int16_t sport, dport, win, urp; u_int32_t seq, ack, thseq, thack; u_int utoval; u_int16_t magic; register int rev; #ifdef INET6 register const struct ip6_hdr *ip6; #endif tp = (struct tcphdr *)bp; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ ch = '\0'; if (!TTEST(tp->th_dport)) { (void)printf("%s > %s: [|tcp]", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); return; } sport = EXTRACT_16BITS(&tp->th_sport); dport = EXTRACT_16BITS(&tp->th_dport); hlen = TH_OFF(tp) * 4; #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ip6addr_string(&ip6->ip6_src), tcpport_string(sport), ip6addr_string(&ip6->ip6_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } if (hlen < sizeof(*tp)) { (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp)); return; } TCHECK(*tp); seq = EXTRACT_32BITS(&tp->th_seq); ack = EXTRACT_32BITS(&tp->th_ack); win = EXTRACT_16BITS(&tp->th_win); urp = EXTRACT_16BITS(&tp->th_urp); if (qflag) { (void)printf("tcp %d", length - hlen); if (hlen > length) { (void)printf(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = tp->th_flags; printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!Sflag && (flags & TH_ACK)) { /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ rev = 0; #ifdef INET6 if (ip6) { register struct tcp_seq_hash6 *th; struct tcp_seq_hash6 *tcp_seq_hash; const struct in6_addr *src, *dst; struct tha6 tha; tcp_seq_hash = tcp_seq_hash6; src = &ip6->ip6_src; dst = &ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(src, dst, sizeof ip6->ip6_dst) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, dst, sizeof ip6->ip6_dst); UNALIGNED_MEMCPY(&tha.dst, src, sizeof ip6->ip6_src); tha.port = dport << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof ip6->ip6_dst); UNALIGNED_MEMCPY(&tha.src, src, sizeof ip6->ip6_src); tha.port = sport << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash6 *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { #else /*INET6*/ { #endif /*INET6*/ register struct tcp_seq_hash *th; struct tcp_seq_hash *tcp_seq_hash; const struct in_addr *src, *dst; struct tha tha; tcp_seq_hash = tcp_seq_hash4; src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, dst, sizeof ip->ip_dst); UNALIGNED_MEMCPY(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof ip->ip_dst); UNALIGNED_MEMCPY(&tha.src, src, sizeof ip->ip_src); tha.port = sport << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } } else {
void olsr_print (packetbody_t pptr, u_int length, int is_ipv6) { union { __capability const struct olsr_common *common; __capability const struct olsr_msg4 *msg4; __capability const struct olsr_msg6 *msg6; __capability const struct olsr_hello *hello; __capability const struct olsr_hello_link *hello_link; __capability const struct olsr_tc *tc; __capability const struct olsr_hna4 *hna; } ptr; u_int msg_type, msg_len, msg_tlen, hello_len; u_int16_t name_entry_type, name_entry_len; u_int name_entry_padding; u_int8_t link_type, neighbor_type; packetbody_t tptr, msg_data; tptr = pptr; if (length < sizeof(struct olsr_common)) { goto trunc; } if (!PACKET_HAS_SPACE(tptr, sizeof(struct olsr_common))) { goto trunc; } ptr.common = (__capability struct olsr_common *)tptr; length = MIN(length, EXTRACT_16BITS(ptr.common->packet_len)); printf("OLSRv%i, seq 0x%04x, length %u", (is_ipv6 == 0) ? 4 : 6, EXTRACT_16BITS(ptr.common->packet_seq), length); tptr += sizeof(struct olsr_common); /* * In non-verbose mode, just print version. */ if (vflag < 1) { return; } while (tptr < (pptr+length)) { union { __capability struct olsr_msg4 *v4; __capability struct olsr_msg6 *v6; } msgptr; int msg_len_valid = 0; if (!PACKET_HAS_SPACE(tptr, sizeof(struct olsr_msg4))) goto trunc; #if INET6 if (is_ipv6) { msgptr.v6 = (__capability struct olsr_msg6 *) tptr; msg_type = msgptr.v6->msg_type; msg_len = EXTRACT_16BITS(msgptr.v6->msg_len); if ((msg_len >= sizeof (struct olsr_msg6)) && (msg_len <= length)) msg_len_valid = 1; /* infinite loop check */ if (msg_type == 0 || msg_len == 0) { return; } printf("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, ip6addr_string(msgptr.v6->originator), msgptr.v6->ttl, msgptr.v6->hopcount, ME_TO_DOUBLE(msgptr.v6->vtime), EXTRACT_16BITS(msgptr.v6->msg_seq), msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); msg_tlen = msg_len - sizeof(struct olsr_msg6); msg_data = tptr + sizeof(struct olsr_msg6); } else /* (!is_ipv6) */ #endif /* INET6 */ { msgptr.v4 = (__capability struct olsr_msg4 *) tptr; msg_type = msgptr.v4->msg_type; msg_len = EXTRACT_16BITS(msgptr.v4->msg_len); if ((msg_len >= sizeof (struct olsr_msg4)) && (msg_len <= length)) msg_len_valid = 1; /* infinite loop check */ if (msg_type == 0 || msg_len == 0) { return; } printf("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, ipaddr_string(msgptr.v4->originator), msgptr.v4->ttl, msgptr.v4->hopcount, ME_TO_DOUBLE(msgptr.v4->vtime), EXTRACT_16BITS(msgptr.v4->msg_seq), msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); msg_tlen = msg_len - sizeof(struct olsr_msg4); msg_data = tptr + sizeof(struct olsr_msg4); } switch (msg_type) { case OLSR_HELLO_MSG: case OLSR_HELLO_LQ_MSG: if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hello))) goto trunc; ptr.hello = (__capability struct olsr_hello *)msg_data; printf("\n\t hello-time %.3lfs, MPR willingness %u", ME_TO_DOUBLE(ptr.hello->htime), ptr.hello->will); msg_data += sizeof(struct olsr_hello); msg_tlen -= sizeof(struct olsr_hello); while (msg_tlen >= sizeof(struct olsr_hello_link)) { int hello_len_valid = 0; /* * link-type. */ if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hello_link))) goto trunc; ptr.hello_link = (__capability struct olsr_hello_link *)msg_data; hello_len = EXTRACT_16BITS(ptr.hello_link->len); link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code); neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code); if ((hello_len <= msg_tlen) && (hello_len >= sizeof(struct olsr_hello_link))) hello_len_valid = 1; printf("\n\t link-type %s, neighbor-type %s, len %u%s", tok2str(olsr_link_type_values, "Unknown", link_type), tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type), hello_len, (hello_len_valid == 0) ? " (invalid)" : ""); if (hello_len_valid == 0) break; msg_data += sizeof(struct olsr_hello_link); msg_tlen -= sizeof(struct olsr_hello_link); hello_len -= sizeof(struct olsr_hello_link); if (msg_type == OLSR_HELLO_MSG) { olsr_print_neighbor(msg_data, hello_len); } else { #if INET6 if (is_ipv6) olsr_print_lq_neighbor6(msg_data, hello_len); else #endif olsr_print_lq_neighbor4(msg_data, hello_len); } msg_data += hello_len; msg_tlen -= hello_len; } break; case OLSR_TC_MSG: case OLSR_TC_LQ_MSG: if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_tc))) goto trunc; ptr.tc = (__capability struct olsr_tc *)msg_data; printf("\n\t advertised neighbor seq 0x%04x", EXTRACT_16BITS(ptr.tc->ans_seq)); msg_data += sizeof(struct olsr_tc); msg_tlen -= sizeof(struct olsr_tc); if (msg_type == OLSR_TC_MSG) { olsr_print_neighbor(msg_data, msg_tlen); } else { #if INET6 if (is_ipv6) olsr_print_lq_neighbor6(msg_data, msg_tlen); else #endif olsr_print_lq_neighbor4(msg_data, msg_tlen); } break; case OLSR_MID_MSG: { size_t addr_size = sizeof(struct in_addr); #if INET6 if (is_ipv6) addr_size = sizeof(struct in6_addr); #endif while (msg_tlen >= addr_size) { if (!PACKET_HAS_SPACE(msg_data, addr_size)) goto trunc; printf("\n\t interface address %s", #if INET6 is_ipv6 ? ip6addr_string(msg_data) : #endif ipaddr_string(msg_data)); msg_data += addr_size; msg_tlen -= addr_size; } break; } case OLSR_HNA_MSG: printf("\n\t Advertised networks (total %u)", (unsigned int) (msg_tlen / sizeof(struct olsr_hna6))); #if INET6 if (is_ipv6) { int i = 0; while (msg_tlen >= sizeof(struct olsr_hna6)) { __capability struct olsr_hna6 *hna6; if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hna6))) goto trunc; hna6 = (__capability struct olsr_hna6 *)msg_data; printf("\n\t #%i: %s/%u", i, ip6addr_string(hna6->network), mask62plen (hna6->mask)); msg_data += sizeof(struct olsr_hna6); msg_tlen -= sizeof(struct olsr_hna6); } } else #endif { int col = 0; while (msg_tlen >= sizeof(struct olsr_hna4)) { if (!PACKET_HAS_SPACE(msg_data, sizeof(struct olsr_hna4))) goto trunc; ptr.hna = (__capability struct olsr_hna4 *)msg_data; /* print 4 prefixes per line */ if (col == 0) printf ("\n\t "); else printf (", "); printf("%s/%u", ipaddr_string(ptr.hna->network), mask2plen(EXTRACT_32BITS(ptr.hna->mask))); msg_data += sizeof(struct olsr_hna4); msg_tlen -= sizeof(struct olsr_hna4); col = (col + 1) % 4; } } break; case OLSR_NAMESERVICE_MSG: { u_int name_entries = EXTRACT_16BITS(msg_data+2); u_int addr_size = 4; int name_entries_valid = 0; u_int i; if (is_ipv6) addr_size = 16; if ((name_entries > 0) && ((name_entries * (4 + addr_size)) <= msg_tlen)) name_entries_valid = 1; if (msg_tlen < 4) goto trunc; if (!PACKET_HAS_SPACE(msg_data, 4)) goto trunc; printf("\n\t Version %u, Entries %u%s", EXTRACT_16BITS(msg_data), name_entries, (name_entries_valid == 0) ? " (invalid)" : ""); if (name_entries_valid == 0) break; msg_data += 4; msg_tlen -= 4; for (i = 0; i < name_entries; i++) { int name_entry_len_valid = 0; if (msg_tlen < 4) break; if (!PACKET_HAS_SPACE(msg_data, 4)) goto trunc; name_entry_type = EXTRACT_16BITS(msg_data); name_entry_len = EXTRACT_16BITS(msg_data+2); msg_data += 4; msg_tlen -= 4; if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen)) name_entry_len_valid = 1; printf("\n\t #%u: type %#06x, length %u%s", (unsigned int) i, name_entry_type, name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : ""); if (name_entry_len_valid == 0) break; /* 32-bit alignment */ name_entry_padding = 0; if (name_entry_len%4 != 0) name_entry_padding = 4-(name_entry_len%4); if (msg_tlen < addr_size + name_entry_len + name_entry_padding) goto trunc; if (!PACKET_HAS_SPACE(msg_data, addr_size + name_entry_len + name_entry_padding)) goto trunc; #if INET6 if (is_ipv6) printf(", address %s, name \"", ip6addr_string(msg_data)); else #endif printf(", address %s, name \"", ipaddr_string(msg_data)); fn_printn(msg_data + addr_size, name_entry_len, NULL); printf("\""); msg_data += addr_size + name_entry_len + name_entry_padding; msg_tlen -= addr_size + name_entry_len + name_entry_padding; } /* for (i = 0; i < name_entries; i++) */ break; } /* case OLSR_NAMESERVICE_MSG */ /* * FIXME those are the defined messages that lack a decoder * you are welcome to contribute code ;-) */ case OLSR_POWERINFO_MSG: default: print_unknown_data(msg_data, "\n\t ", msg_tlen); break; } /* switch (msg_type) */ tptr += msg_len; } /* while (tptr < (pptr+length)) */ return; trunc: printf("[|olsr]"); }
void sunrpcrequest_print(packetbody_t bp, register u_int length, packetbody_t bp2) { __capability const struct sunrpc_msg *rp; __capability const struct ip *ip; #ifdef INET6 __capability const struct ip6_hdr *ip6; #endif u_int32_t x; char srcid[20], dstid[20]; /*fits 32bit*/ rp = (__capability const struct sunrpc_msg *)bp; if (!nflag) { snprintf(srcid, sizeof(srcid), "0x%x", EXTRACT_32BITS(&rp->rm_xid)); strlcpy(dstid, "sunrpc", sizeof(dstid)); } else { snprintf(srcid, sizeof(srcid), "0x%x", EXTRACT_32BITS(&rp->rm_xid)); snprintf(dstid, sizeof(dstid), "0x%x", SUNRPC_PMAPPORT); } switch (IP_V((__capability const struct ip *)bp2)) { case 4: ip = (__capability const struct ip *)bp2; printf("%s.%s > %s.%s: %d", ipaddr_string(&ip->ip_src), srcid, ipaddr_string(&ip->ip_dst), dstid, length); break; #ifdef INET6 case 6: ip6 = (__capability const struct ip6_hdr *)bp2; printf("%s.%s > %s.%s: %d", ip6addr_string(&ip6->ip6_src), srcid, ip6addr_string(&ip6->ip6_dst), dstid, length); break; #endif default: printf("%s.%s > %s.%s: %d", "?", srcid, "?", dstid, length); break; } printf(" %s", tok2str(proc2str, " proc #%u", EXTRACT_32BITS(&rp->rm_call.cb_proc))); x = EXTRACT_32BITS(&rp->rm_call.cb_rpcvers); if (x != 2) printf(" [rpcver %u]", x); switch (EXTRACT_32BITS(&rp->rm_call.cb_proc)) { case SUNRPC_PMAPPROC_SET: case SUNRPC_PMAPPROC_UNSET: case SUNRPC_PMAPPROC_GETPORT: case SUNRPC_PMAPPROC_CALLIT: x = EXTRACT_32BITS(&rp->rm_call.cb_prog); if (!nflag) printf(" %s", progstr(x)); else printf(" %u", x); printf(".%u", EXTRACT_32BITS(&rp->rm_call.cb_vers)); break; } }
void tcp_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2, int fragmented) { const struct tcphdr *tp; const struct ip *ip; u_char flags; u_int hlen; char ch; uint16_t sport, dport, win, urp; uint32_t seq, ack, thseq, thack; u_int utoval; uint16_t magic; int rev; const struct ip6_hdr *ip6; ndo->ndo_protocol = "tcp"; tp = (const struct tcphdr *)bp; ip = (const struct ip *)bp2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; ch = '\0'; if (!ND_TTEST_2(tp->th_dport)) { if (ip6) { ND_PRINT("%s > %s:", ip6addr_string(ndo, ip6->ip6_src), ip6addr_string(ndo, ip6->ip6_dst)); } else { ND_PRINT("%s > %s:", ipaddr_string(ndo, ip->ip_src), ipaddr_string(ndo, ip->ip_dst)); } nd_print_trunc(ndo); return; } sport = GET_BE_U_2(tp->th_sport); dport = GET_BE_U_2(tp->th_dport); if (ip6) { if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", ip6addr_string(ndo, ip6->ip6_src), tcpport_string(ndo, sport), ip6addr_string(ndo, ip6->ip6_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } else { if (GET_U_1(ip->ip_p) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", ipaddr_string(ndo, ip->ip_src), tcpport_string(ndo, sport), ipaddr_string(ndo, ip->ip_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } ND_TCHECK_SIZE(tp); hlen = TH_OFF(tp) * 4; if (hlen < sizeof(*tp)) { ND_PRINT(" tcp %u [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp)); return; } seq = GET_BE_U_4(tp->th_seq); ack = GET_BE_U_4(tp->th_ack); win = GET_BE_U_2(tp->th_win); urp = GET_BE_U_2(tp->th_urp); if (ndo->ndo_qflag) { ND_PRINT("tcp %u", length - hlen); if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = GET_U_1(tp->th_flags); ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!ndo->ndo_Sflag && (flags & TH_ACK)) { /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ rev = 0; if (ip6) { struct tcp_seq_hash6 *th; struct tcp_seq_hash6 *tcp_seq_hash; const void *src, *dst; struct tha6 tha; tcp_seq_hash = tcp_seq_hash6; src = (const void *)ip6->ip6_src; dst = (const void *)ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash6' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash6 *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { struct tcp_seq_hash *th; struct tcp_seq_hash *tcp_seq_hash; struct tha tha; tcp_seq_hash = tcp_seq_hash4; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.dst, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.src, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash4' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } } else { /*fool gcc*/ thseq = thack = rev = 0; } if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); return; } if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { /* Check the checksum, if possible. */ uint16_t sum, tcp_sum; if (IP_V(ip) == 4) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp_cksum(ndo, ip, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } else if (IP_V(ip) == 6 && ip6->ip6_plen) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp6_cksum(ndo, ip6, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } } length -= hlen; if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { ND_PRINT(", seq %u", seq); if (length > 0) { ND_PRINT(":%u", seq + length); } } if (flags & TH_ACK) { ND_PRINT(", ack %u", ack); } ND_PRINT(", win %u", win); if (flags & TH_URG) ND_PRINT(", urg %u", urp); /* * Handle any options. */ if (hlen > sizeof(*tp)) { const u_char *cp; u_int i, opt, datalen; u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); ND_PRINT(", options ["); while (hlen > 0) { if (ch != '\0') ND_PRINT("%c", ch); ND_TCHECK_1(cp); opt = GET_U_1(cp); cp++; if (ZEROLENOPT(opt)) len = 1; else { ND_TCHECK_1(cp); len = GET_U_1(cp); cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); } ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt)); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_2(cp)); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); ND_PRINT(" %u", GET_U_1(cp)); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { ND_PRINT(" invalid sack"); } else { uint32_t s, e; ND_PRINT(" %u ", datalen / 8); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = GET_BE_U_4(cp + i); LENCHECK(i + 8); e = GET_BE_U_4(cp + i + 4); if (rev) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } ND_PRINT("{%u:%u}", s, e); } } break; case TCPOPT_CC: case TCPOPT_CCNEW: case TCPOPT_CCECHO: case TCPOPT_ECHO: case TCPOPT_ECHOREPLY: /* * those options share their semantics. * fall through */ datalen = 4; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_4(cp)); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); ND_PRINT(" val %u ecr %u", GET_BE_U_4(cp), GET_BE_U_4(cp + 4)); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); ND_PRINT(" "); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ndo, ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: ND_PRINT("valid"); break; case SIGNATURE_INVALID: nd_print_invalid(ndo); break; case CANT_CHECK_SIGNATURE: ND_PRINT("can't check - "); for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); #endif break; case TCPOPT_SCPS: datalen = 2; LENCHECK(datalen); ND_PRINT(" cap %02x id %u", GET_U_1(cp), GET_U_1(cp + 1)); break; case TCPOPT_TCPAO: datalen = len - 2; /* RFC 5925 Section 2.2: * "The Length value MUST be greater than or equal to 4." * (This includes the Kind and Length fields already processed * at this point.) */ if (datalen < 2) { nd_print_invalid(ndo); } else { LENCHECK(1); ND_PRINT(" keyid %u", GET_U_1(cp)); LENCHECK(2); ND_PRINT(" rnextkeyid %u", GET_U_1(cp + 1)); if (datalen > 2) { ND_PRINT(" mac 0x"); for (i = 2; i < datalen; i++) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } } } break; case TCPOPT_EOL: case TCPOPT_NOP: case TCPOPT_SACKOK: /* * Nothing interesting. * fall through */ break; case TCPOPT_UTO: datalen = 2; LENCHECK(datalen); utoval = GET_BE_U_2(cp); ND_PRINT(" 0x%x", utoval); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; ND_PRINT(" %u", utoval); break; case TCPOPT_MPTCP: datalen = len - 2; LENCHECK(datalen); if (!mptcp_print(ndo, cp-2, len, flags)) goto bad; break; case TCPOPT_FASTOPEN: datalen = len - 2; LENCHECK(datalen); ND_PRINT(" "); print_tcp_fastopen_option(ndo, cp, datalen, FALSE); break; case TCPOPT_EXPERIMENT2: datalen = len - 2; LENCHECK(datalen); if (datalen < 2) goto bad; /* RFC6994 */ magic = GET_BE_U_2(cp); ND_PRINT("-"); switch(magic) { case 0xf989: /* TCP Fast Open RFC 7413 */ print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE); break; default: /* Unknown magic number */ ND_PRINT("%04x", magic); break; } break; default: datalen = len - 2; if (datalen) ND_PRINT(" 0x"); for (i = 0; i < datalen; ++i) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) ND_PRINT("[len %u]", len); ch = ','; if (opt == TCPOPT_EOL) break; } ND_PRINT("]"); }
void sctp_print(const u_char *bp, /* beginning of sctp packet */ const u_char *bp2, /* beginning of enclosing */ u_int sctpPacketLength) /* ip packet */ { const struct sctpHeader *sctpPktHdr; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif const void *endPacketPtr; u_short sourcePort, destPort; int chunkCount; const struct sctpChunkDesc *chunkDescPtr; const void *nextChunk; const char *sep; int isforces = 0; sctpPktHdr = (const struct sctpHeader*) bp; endPacketPtr = (const u_char*)sctpPktHdr+sctpPacketLength; if( (u_long) endPacketPtr > (u_long) snapend) endPacketPtr = (const void *) snapend; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ TCHECK(*sctpPktHdr); if (sctpPacketLength < sizeof(struct sctpHeader)) { (void)printf("truncated-sctp - %ld bytes missing!", (long)sctpPacketLength-sizeof(struct sctpHeader)); return; } /* sctpPacketLength -= sizeof(struct sctpHeader); packet length */ /* is now only as long as the payload */ sourcePort = EXTRACT_16BITS(&sctpPktHdr->source); destPort = EXTRACT_16BITS(&sctpPktHdr->destination); #ifdef INET6 if (ip6) { (void)printf("%s.%d > %s.%d: sctp", ip6addr_string(&ip6->ip6_src), sourcePort, ip6addr_string(&ip6->ip6_dst), destPort); } else #endif /*INET6*/ { (void)printf("%s.%d > %s.%d: sctp", ipaddr_string(&ip->ip_src), sourcePort, ipaddr_string(&ip->ip_dst), destPort); } fflush(stdout); if (isForCES_port(sourcePort)) { printf("[%s]", tok2str(ForCES_channels, NULL, sourcePort)); isforces = 1; } if (isForCES_port(destPort)) { printf("[%s]", tok2str(ForCES_channels, NULL, destPort)); isforces = 1; } if (vflag >= 2) sep = "\n\t"; else sep = " ("; /* cycle through all chunks, printing information on each one */ for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *) ((const u_char*) sctpPktHdr + sizeof(struct sctpHeader)); chunkDescPtr != NULL && ( (const void *) ((const u_char *) chunkDescPtr + sizeof(struct sctpChunkDesc)) <= endPacketPtr); chunkDescPtr = (const struct sctpChunkDesc *) nextChunk, chunkCount++) { u_int16_t chunkLength; const u_char *chunkEnd; u_int16_t align; TCHECK(*chunkDescPtr); chunkLength = EXTRACT_16BITS(&chunkDescPtr->chunkLength); if (chunkLength < sizeof(*chunkDescPtr)) { printf("%s%d) [Bad chunk length %u]", sep, chunkCount+1, chunkLength); break; } TCHECK2(*((u_int8_t *)chunkDescPtr), chunkLength); chunkEnd = ((const u_char*)chunkDescPtr + chunkLength); align=chunkLength % 4; if (align != 0) align = 4 - align; nextChunk = (const void *) (chunkEnd + align); printf("%s%d) ", sep, chunkCount+1); switch (chunkDescPtr->chunkID) { case SCTP_DATA : { const struct sctpDataPart *dataHdrPtr; printf("[DATA] "); if ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) printf("(U)"); if ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) printf("(B)"); if ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) printf("(E)"); if( ((chunkDescPtr->chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) || ((chunkDescPtr->chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || ((chunkDescPtr->chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) printf(" "); dataHdrPtr=(const struct sctpDataPart*)(chunkDescPtr+1); u_int32_t ppid = EXTRACT_32BITS(&dataHdrPtr->payloadtype); printf("[TSN: %u] ", EXTRACT_32BITS(&dataHdrPtr->TSN)); printf("[SID: %u] ", EXTRACT_16BITS(&dataHdrPtr->streamId)); printf("[SSEQ %u] ", EXTRACT_16BITS(&dataHdrPtr->sequence)); printf("[PPID %s] ", tok2str(PayloadProto_idents, "0x%x", ppid)); fflush(stdout); if (!isforces) { isforces = (ppid == SCTP_PPID_FORCES_HP) || (ppid == SCTP_PPID_FORCES_MP) || (ppid == SCTP_PPID_FORCES_LP); } const u_char *payloadPtr = (const u_char *) (dataHdrPtr + 1); if (EXTRACT_16BITS(&chunkDescPtr->chunkLength) < sizeof(struct sctpDataPart) + sizeof(struct sctpChunkDesc) + 1) { printf("bogus chunk length %u]", EXTRACT_16BITS(&chunkDescPtr->chunkLength)); return; } u_int payload_size = EXTRACT_16BITS(&chunkDescPtr->chunkLength) - (sizeof(struct sctpDataPart) + sizeof(struct sctpChunkDesc)); if (isforces) { forces_print(payloadPtr, payload_size); } else if (vflag >= 2) { /* if verbose output is specified */ /* at the command line */ switch (ppid) { case SCTP_PPID_M3UA : print_m3ua(payloadPtr, payload_size); break; default: printf("[Payload"); if (!suppress_default_print) { printf(":"); default_print(payloadPtr, payload_size); } printf("]"); break; } } break; } case SCTP_INITIATION : { const struct sctpInitiation *init; printf("[INIT] "); init=(const struct sctpInitiation*)(chunkDescPtr+1); printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); #if(0) /* ALC you can add code for optional params here */ if( (init+1) < chunkEnd ) printf(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif break; } case SCTP_INITIATION_ACK : { const struct sctpInitiation *init; printf("[INIT ACK] "); init=(const struct sctpInitiation*)(chunkDescPtr+1); printf("[init tag: %u] ", EXTRACT_32BITS(&init->initTag)); printf("[rwnd: %u] ", EXTRACT_32BITS(&init->rcvWindowCredit)); printf("[OS: %u] ", EXTRACT_16BITS(&init->NumPreopenStreams)); printf("[MIS: %u] ", EXTRACT_16BITS(&init->MaxInboundStreams)); printf("[init TSN: %u] ", EXTRACT_32BITS(&init->initialTSN)); #if(0) /* ALC you can add code for optional params here */ if( (init+1) < chunkEnd ) printf(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif break; } case SCTP_SELECTIVE_ACK: { const struct sctpSelectiveAck *sack; const struct sctpSelectiveFrag *frag; int fragNo, tsnNo; const u_char *dupTSN; printf("[SACK] "); sack=(const struct sctpSelectiveAck*)(chunkDescPtr+1); printf("[cum ack %u] ", EXTRACT_32BITS(&sack->highestConseqTSN)); printf("[a_rwnd %u] ", EXTRACT_32BITS(&sack->updatedRwnd)); printf("[#gap acks %u] ", EXTRACT_16BITS(&sack->numberOfdesc)); printf("[#dup tsns %u] ", EXTRACT_16BITS(&sack->numDupTsns)); /* print gaps */ for (frag = ( (const struct sctpSelectiveFrag *) ((const struct sctpSelectiveAck *) sack+1)), fragNo=0; (const void *)frag < nextChunk && fragNo < EXTRACT_16BITS(&sack->numberOfdesc); frag++, fragNo++) printf("\n\t\t[gap ack block #%d: start = %u, end = %u] ", fragNo+1, EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentStart), EXTRACT_32BITS(&sack->highestConseqTSN) + EXTRACT_16BITS(&frag->fragmentEnd)); /* print duplicate TSNs */ for (dupTSN = (const u_char *)frag, tsnNo=0; (const void *) dupTSN < nextChunk && tsnNo<EXTRACT_16BITS(&sack->numDupTsns); dupTSN += 4, tsnNo++) printf("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, EXTRACT_32BITS(dupTSN)); break; } case SCTP_HEARTBEAT_REQUEST : printf("[HB REQ] "); break; case SCTP_HEARTBEAT_ACK : printf("[HB ACK] "); break; case SCTP_ABORT_ASSOCIATION : printf("[ABORT] "); break; case SCTP_SHUTDOWN : printf("[SHUTDOWN] "); break; case SCTP_SHUTDOWN_ACK : printf("[SHUTDOWN ACK] "); break; case SCTP_OPERATION_ERR : printf("[OP ERR] "); break; case SCTP_COOKIE_ECHO : printf("[COOKIE ECHO] "); break; case SCTP_COOKIE_ACK : printf("[COOKIE ACK] "); break; case SCTP_ECN_ECHO : printf("[ECN ECHO] "); break; case SCTP_ECN_CWR : printf("[ECN CWR] "); break; case SCTP_SHUTDOWN_COMPLETE : printf("[SHUTDOWN COMPLETE] "); break; case SCTP_FORWARD_CUM_TSN : printf("[FOR CUM TSN] "); break; case SCTP_RELIABLE_CNTL : printf("[REL CTRL] "); break; case SCTP_RELIABLE_CNTL_ACK : printf("[REL CTRL ACK] "); break; default : printf("[Unknown chunk type: 0x%x]", chunkDescPtr->chunkID); return; } if (vflag < 2) sep = ", ("; } return; trunc: printf("[|sctp]"); return; }
void icmp6_print(const u_char *bp, u_int length, const u_char *bp2) { register const struct icmp6_hdr *dp; register const struct ip6_hdr *ip; register const char *str; register const struct ip6_hdr *oip; register const struct udphdr *ouh; register int hlen, dport; register const u_char *ep; char buf[256]; int icmp6len; #if 0 #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc #endif dp = (struct icmp6_hdr *)bp; ip = (struct ip6_hdr *)bp2; oip = (struct ip6_hdr *)(dp + 1); str = buf; /* 'ep' points to the end of avaible data. */ ep = snapend; if (ip->ip6_plen) icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) - (bp - bp2)); else /* XXX: jumbo payload case... */ icmp6len = snapend - bp; #if 0 (void)printf("%s > %s: ", ip6addr_string(&ip->ip6_src), ip6addr_string(&ip->ip6_dst)); #endif TCHECK(dp->icmp6_code); switch (dp->icmp6_type) { case ICMP6_DST_UNREACH: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_DST_UNREACH_NOROUTE: printf("icmp6: %s unreachable route", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_DST_UNREACH_ADMIN: printf("icmp6: %s unreachable prohibited", ip6addr_string(&oip->ip6_dst)); break; #ifdef ICMP6_DST_UNREACH_BEYONDSCOPE case ICMP6_DST_UNREACH_BEYONDSCOPE: #else case ICMP6_DST_UNREACH_NOTNEIGHBOR: #endif printf("icmp6: %s beyond scope of source address %s", ip6addr_string(&oip->ip6_dst), ip6addr_string(&oip->ip6_src)); break; case ICMP6_DST_UNREACH_ADDR: printf("icmp6: %s unreachable address", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_DST_UNREACH_NOPORT: TCHECK(oip->ip6_nxt); hlen = sizeof(struct ip6_hdr); ouh = (struct udphdr *)(((u_char *)oip) + hlen); TCHECK(ouh->uh_dport); dport = ntohs(ouh->uh_dport); switch (oip->ip6_nxt) { case IPPROTO_TCP: printf("icmp6: %s tcp port %s unreachable", ip6addr_string(&oip->ip6_dst), tcpport_string(dport)); break; case IPPROTO_UDP: printf("icmp6: %s udp port %s unreachable", ip6addr_string(&oip->ip6_dst), udpport_string(dport)); break; default: printf("icmp6: %s protocol %d port %d unreachable", ip6addr_string(&oip->ip6_dst), oip->ip6_nxt, dport); break; } break; default: printf("icmp6: %s unreachable code-#%d", ip6addr_string(&oip->ip6_dst), dp->icmp6_code); break; } break; case ICMP6_PACKET_TOO_BIG: TCHECK(dp->icmp6_mtu); printf("icmp6: too big %u", (u_int32_t)ntohl(dp->icmp6_mtu)); break; case ICMP6_TIME_EXCEEDED: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_TIME_EXCEED_TRANSIT: printf("icmp6: time exceeded in-transit for %s", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_TIME_EXCEED_REASSEMBLY: printf("icmp6: ip6 reassembly time exceeded"); break; default: printf("icmp6: time exceeded code-#%d", dp->icmp6_code); break; } break; case ICMP6_PARAM_PROB: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_PARAMPROB_HEADER: printf("icmp6: parameter problem errorneous - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; case ICMP6_PARAMPROB_NEXTHEADER: printf("icmp6: parameter problem next header - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; case ICMP6_PARAMPROB_OPTION: printf("icmp6: parameter problem option - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; default: printf("icmp6: parameter problem code-#%d", dp->icmp6_code); break; } break; case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: printf("icmp6: echo %s", dp->icmp6_type == ICMP6_ECHO_REQUEST ? "request" : "reply"); if (vflag) { TCHECK(dp->icmp6_seq); printf(" (id:%04x seq:%u)", ntohs(dp->icmp6_id), ntohs(dp->icmp6_seq)); } break; case ICMP6_MEMBERSHIP_QUERY: printf("icmp6: multicast listener query "); if (length == MLD_V1_QUERY_MINLEN) { mld6_print((const u_char *)dp); } else if (length >= MLD_V2_QUERY_MINLEN) { printf("v2 "); mldv2_query_print((const u_char *)dp, length); } else { printf("unknown-version (len %u) ", length); } break; case ICMP6_MEMBERSHIP_REPORT: printf("icmp6: multicast listener report "); mld6_print((const u_char *)dp); break; case ICMP6_MEMBERSHIP_REDUCTION: printf("icmp6: multicast listener done "); mld6_print((const u_char *)dp); break; case ND_ROUTER_SOLICIT: printf("icmp6: router solicitation "); if (vflag) { #define RTSOLLEN 8 icmp6_opt_print((const u_char *)dp + RTSOLLEN, icmp6len - RTSOLLEN); } break; case ND_ROUTER_ADVERT: printf("icmp6: router advertisement"); if (vflag) { struct nd_router_advert *p; p = (struct nd_router_advert *)dp; TCHECK(p->nd_ra_retransmit); printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit); if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) printf("M"); if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) printf("O"); if (p->nd_ra_flags_reserved != 0) printf(" "); printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime)); printf("reachable_time=%u, ", (u_int32_t)ntohl(p->nd_ra_reachable)); printf("retrans_time=%u)", (u_int32_t)ntohl(p->nd_ra_retransmit)); #define RTADVLEN 16 icmp6_opt_print((const u_char *)dp + RTADVLEN, icmp6len - RTADVLEN); } break; case ND_NEIGHBOR_SOLICIT: { struct nd_neighbor_solicit *p; p = (struct nd_neighbor_solicit *)dp; TCHECK(p->nd_ns_target); printf("icmp6: neighbor sol: who has %s", ip6addr_string(&p->nd_ns_target)); if (vflag) { #define NDSOLLEN 24 icmp6_opt_print((const u_char *)dp + NDSOLLEN, icmp6len - NDSOLLEN); } } break; case ND_NEIGHBOR_ADVERT: { struct nd_neighbor_advert *p; p = (struct nd_neighbor_advert *)dp; TCHECK(p->nd_na_target); printf("icmp6: neighbor adv: tgt is %s", ip6addr_string(&p->nd_na_target)); if (vflag) { #define ND_NA_FLAG_ALL \ (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE) /* we don't need ntohl() here. see advanced-api-04. */ if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) { #undef ND_NA_FLAG_ALL u_int32_t flags; flags = p->nd_na_flags_reserved; printf("("); if (flags & ND_NA_FLAG_ROUTER) printf("R"); if (flags & ND_NA_FLAG_SOLICITED) printf("S"); if (flags & ND_NA_FLAG_OVERRIDE) printf("O"); printf(")"); } #define NDADVLEN 24 icmp6_opt_print((const u_char *)dp + NDADVLEN, icmp6len - NDADVLEN); } } break; case ND_REDIRECT: { #define RDR(i) ((struct nd_redirect *)(i)) char tgtbuf[INET6_ADDRSTRLEN], dstbuf[INET6_ADDRSTRLEN]; TCHECK(RDR(dp)->nd_rd_dst); inet_ntop(AF_INET6, &RDR(dp)->nd_rd_target, tgtbuf, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &RDR(dp)->nd_rd_dst, dstbuf, INET6_ADDRSTRLEN); printf("icmp6: redirect %s to %s", dstbuf, tgtbuf); #define REDIRECTLEN 40 if (vflag) { icmp6_opt_print((const u_char *)dp + REDIRECTLEN, icmp6len - REDIRECTLEN); } break; } case ICMP6_ROUTER_RENUMBERING: switch (dp->icmp6_code) { case ICMP6_ROUTER_RENUMBERING_COMMAND: printf("icmp6: router renum command"); break; case ICMP6_ROUTER_RENUMBERING_RESULT: printf("icmp6: router renum result"); break; default: printf("icmp6: router renum code-#%d", dp->icmp6_code); break; } break; #ifdef ICMP6_WRUREQUEST case ICMP6_WRUREQUEST: /*ICMP6_FQDN_QUERY*/ { int siz; siz = ep - (u_char *)(dp + 1); if (siz == 4) printf("icmp6: who-are-you request"); else { printf("icmp6: FQDN request"); if (vflag) { if (siz < 8) printf("?(icmp6_data %d bytes)", siz); else if (8 < siz) printf("?(extra %d bytes)", siz - 8); } } break; } #endif /*ICMP6_WRUREQUEST*/ #ifdef ICMP6_WRUREPLY case ICMP6_WRUREPLY: /*ICMP6_FQDN_REPLY*/ { enum { UNKNOWN, WRU, FQDN } mode = UNKNOWN; u_char const *buf; u_char const *cp = NULL; buf = (u_char *)(dp + 1); /* fair guess */ if (buf[12] == ep - buf - 13) mode = FQDN; else if (dp->icmp6_code == 1) mode = FQDN; /* wild guess */ if (mode == UNKNOWN) { cp = buf + 4; while (cp < ep) { if (!isprint(*cp++)) mode = FQDN; } } #ifndef abs #define abs(a) ((0 < (a)) ? (a) : -(a)) #endif if (mode == UNKNOWN && 2 < abs(buf[12] - (ep - buf - 13))) mode = WRU; if (mode == UNKNOWN) mode = FQDN; if (mode == WRU) { cp = buf + 4; printf("icmp6: who-are-you reply(\""); } else if (mode == FQDN) { cp = buf + 13; printf("icmp6: FQDN reply(\""); } for (; cp < ep; cp++) printf((isprint(*cp) ? "%c" : "\\%03o"), *cp); printf("\""); if (vflag) { printf(",%s", mode == FQDN ? "FQDN" : "WRU"); if (mode == FQDN) { int ttl; ttl = (int)ntohl(*(u_int32_t *)&buf[8]); if (dp->icmp6_code == 1) printf(",TTL=unknown"); else if (ttl < 0) printf(",TTL=%d:invalid", ttl); else printf(",TTL=%d", ttl); if (buf[12] != ep - buf - 13) { (void)printf(",invalid namelen:%d/%u", buf[12], (unsigned int)(ep - buf - 13)); } } } printf(")"); break; } #endif /*ICMP6_WRUREPLY*/ case MLDV2_LISTENER_REPORT: printf("multicast listener report v2"); mldv2_report_print((const u_char *) dp, length); break; default: printf("icmp6: type-#%d", dp->icmp6_type); break; } if (vflag) { u_int16_t sum; if (TTEST2(dp->icmp6_type, length)) { sum = icmp6_cksum(ip, dp, length); if (sum != 0) printf(" [bad icmp6 cksum %x!]", sum); else printf(" [icmp6 cksum ok]"); } } return; trunc: fputs("[|icmp6]", stdout); #if 0 #undef TCHECK #endif }
void tcp_print(const u_char *bp, u_int length, const u_char *bp2) { const struct tcphdr *tp; const struct ip *ip; u_char flags; int hlen; char ch; struct tcp_seq_hash *th = NULL; int rev = 0; u_int16_t sport, dport, win, urp; tcp_seq seq, ack; #ifdef INET6 const struct ip6_hdr *ip6; #endif tp = (struct tcphdr *)bp; switch (((struct ip *)bp2)->ip_v) { case 4: ip = (struct ip *)bp2; #ifdef INET6 ip6 = NULL; #endif break; #ifdef INET6 case 6: ip = NULL; ip6 = (struct ip6_hdr *)bp2; break; #endif default: (void)printf("invalid ip version"); return; } ch = '\0'; if (length < sizeof(*tp)) { (void)printf("truncated-tcp %u", length); return; } if (!TTEST(tp->th_dport)) { #ifdef INET6 if (ip6) { (void)printf("%s > %s: [|tcp]", ip6addr_string(&ip6->ip6_src), ip6addr_string(&ip6->ip6_dst)); } else #endif /*INET6*/ { (void)printf("%s > %s: [|tcp]", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); } return; } sport = ntohs(tp->th_sport); dport = ntohs(tp->th_dport); #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ip6addr_string(&ip6->ip6_src), tcpport_string(sport), ip6addr_string(&ip6->ip6_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } if (!qflag && TTEST(tp->th_seq) && !TTEST(tp->th_ack)) (void)printf("%u ", ntohl(tp->th_seq)); TCHECK(*tp); seq = ntohl(tp->th_seq); ack = ntohl(tp->th_ack); win = ntohs(tp->th_win); urp = ntohs(tp->th_urp); hlen = tp->th_off * 4; if (qflag) { (void)printf("tcp %d", length - tp->th_off * 4); return; } else if (packettype != PT_TCP) { /* * If data present and NFS port used, assume NFS. * Pass offset of data plus 4 bytes for RPC TCP msg length * to NFS print routines. */ u_int len = length - hlen; if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend && dport == NFS_PORT) { nfsreq_print((u_char *)tp + hlen + 4, len, bp2); return; } else if ((u_char *)tp + 4 + sizeof(struct rpc_msg) <= snapend && sport == NFS_PORT) { nfsreply_print((u_char *)tp + hlen + 4, len, bp2); return; } } if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH| TH_ECNECHO|TH_CWR)) { if (flags & TH_SYN) putchar('S'); if (flags & TH_FIN) putchar('F'); if (flags & TH_RST) putchar('R'); if (flags & TH_PUSH) putchar('P'); if (flags & TH_CWR) putchar('W'); /* congestion _W_indow reduced (ECN) */ if (flags & TH_ECNECHO) putchar('E'); /* ecn _E_cho sent (ECN) */ } else putchar('.'); if (!Sflag && (flags & TH_ACK)) { struct tha tha; /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ #ifdef INET6 bzero(&tha, sizeof(tha)); rev = 0; if (ip6) { if (sport > dport) { rev = 1; } else if (sport == dport) { int i; for (i = 0; i < 4; i++) { if (((u_int32_t *)(&ip6->ip6_src))[i] > ((u_int32_t *)(&ip6->ip6_dst))[i]) { rev = 1; break; } } } if (rev) { tha.src = ip6->ip6_dst; tha.dst = ip6->ip6_src; tha.port = dport << 16 | sport; } else { tha.dst = ip6->ip6_dst; tha.src = ip6->ip6_src; tha.port = sport << 16 | dport; } } else { if (sport > dport || (sport == dport && ip->ip_src.s_addr > ip->ip_dst.s_addr)) { rev = 1; } if (rev) { *(struct in_addr *)&tha.src = ip->ip_dst; *(struct in_addr *)&tha.dst = ip->ip_src; tha.port = dport << 16 | sport; } else { *(struct in_addr *)&tha.dst = ip->ip_dst; *(struct in_addr *)&tha.src = ip->ip_src; tha.port = sport << 16 | dport; } } #else if (sport < dport || (sport == dport && ip->ip_src.s_addr < ip->ip_dst.s_addr)) { tha.src = ip->ip_src, tha.dst = ip->ip_dst; tha.port = sport << 16 | dport; rev = 0; } else { tha.src = ip->ip_dst, tha.dst = ip->ip_src; tha.port = dport << 16 | sport; rev = 1; } #endif for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (!memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr))) break; if (!th->nxt || flags & TH_SYN) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } } hlen = tp->th_off * 4; if (hlen > length) { (void)printf(" [bad hdr length]"); return; } if (ip && ip->ip_v == 4 && vflag) { if (TTEST2(tp->th_sport, length)) { u_int16_t sum, tcp_sum; sum = tcp_cksum(ip, tp, length); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" [bad tcp cksum %x! -> %x]", tcp_sum, in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" [tcp sum ok]"); } } #ifdef INET6 if (ip6 && ip6->ip6_plen && vflag) { if (TTEST2(tp->th_sport, length)) { u_int16_t sum, tcp_sum; sum = tcp6_cksum(ip6, tp, length); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" [bad tcp cksum %x! -> %x]", tcp_sum, in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" [tcp sum ok]"); } } #endif /* OS Fingerprint */ if (oflag && (flags & (TH_SYN|TH_ACK)) == TH_SYN) { struct pf_osfp_enlist *head = NULL; struct pf_osfp_entry *fp; unsigned long left; left = (unsigned long)(snapend - (const u_char *)tp); if (left >= hlen) head = pf_osfp_fingerprint_hdr(ip, ip6, tp); if (head) { int prev = 0; printf(" (src OS:"); SLIST_FOREACH(fp, head, fp_entry) { if (fp->fp_enflags & PF_OSFP_EXPANDED) continue; if (prev) printf(","); printf(" %s", fp->fp_class_nm); if (fp->fp_version_nm[0]) printf(" %s", fp->fp_version_nm); if (fp->fp_subtype_nm[0]) printf(" %s", fp->fp_subtype_nm); prev = 1; } printf(")"); } else { if (left < hlen) printf(" (src OS: short-pkt)"); else printf(" (src OS: unknown)"); } }
void mldv2_report_print(const u_char *bp, u_int len) { struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; u_int group, nsrcs, ngroups; u_int i, j; if (len < MLDV2_REPORT_MINLEN) { printf(" [invalid len %d]", len); return; } TCHECK(icp->icmp6_data16[1]); ngroups = ntohs(icp->icmp6_data16[1]); printf(", %d group record(s)", ngroups); if (vflag > 0) { /* Print the group records */ group = MLDV2_REPORT_GROUP0; for (i = 0; i < ngroups; i++) { /* type(1) + auxlen(1) + numsrc(2) + grp(16) */ if (len < group + MLDV2_REPORT_MINGRPLEN) { printf(" [invalid number of groups]"); return; } TCHECK2(bp[group + MLDV2_RGROUP_MADDR], sizeof(struct in6_addr)); printf(" [gaddr %s", ip6addr_string(&bp[group + MLDV2_RGROUP_MADDR])); printf(" %s", tok2str(mldv2report2str, " [v2-report-#%d]", bp[group])); nsrcs = (bp[group + MLDV2_RGROUP_NSRCS] << 8) + bp[group + MLDV2_RGROUP_NSRCS + 1]; /* Check the number of sources and print them */ if (len < group + MLDV2_REPORT_MINGRPLEN + (nsrcs * sizeof(struct in6_addr))) { printf(" [invalid number of sources %d]", nsrcs); return; } if (vflag == 1) printf(", %d source(s)", nsrcs); else { /* Print the sources */ (void)printf(" {"); for (j = 0; j < nsrcs; j++) { TCHECK2(bp[group + MLDV2_REPORT_MINGRPLEN + j * sizeof(struct in6_addr)], sizeof(struct in6_addr)); printf(" %s", ip6addr_string(&bp[group + MLDV2_REPORT_MINGRPLEN + j * sizeof(struct in6_addr)])); } (void)printf(" }"); } /* Next group record */ group += MLDV2_REPORT_MINGRPLEN + nsrcs * sizeof(struct in6_addr); printf("]"); } } return; trunc: (void)printf("[|icmp6]"); return; }
/** * 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; const struct ip6_hdr *ip6; const u_char *cp; u_short sport, dport; u_int hlen; u_int fixed_hdrlen; uint8_t dccph_type; dh = (const struct dccp_hdr *)bp; ip = (const struct ip *)data2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)data2; else ip6 = NULL; /* 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; if (ip6) { ND_PRINT((ndo, "%s.%d > %s.%d: ", ip6addr_string(ndo, &ip6->ip6_src), sport, ip6addr_string(ndo, &ip6->ip6_dst), dport)); } else { ND_PRINT((ndo, "%s.%d > %s.%d: ", ipaddr_string(ndo, &ip->ip_src), sport, ipaddr_string(ndo, &ip->ip_dst), dport)); } ND_PRINT((ndo, "DCCP")); if (ndo->ndo_qflag) { ND_PRINT((ndo, " %d", len - hlen)); if (hlen > len) { ND_PRINT((ndo, " [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)) { uint16_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); else if (IP_V(ip) == 6) sum = dccp6_cksum(ndo, ip6, dh, len); if (sum != 0) ND_PRINT((ndo, "(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum))); else ND_PRINT((ndo, "(correct)")); } if (ndo->ndo_vflag) ND_PRINT((ndo, ")")); ND_PRINT((ndo, " ")); dccph_type = DCCPH_TYPE(dh); switch (dccph_type) { case DCCP_PKT_REQUEST: { const struct dccp_hdr_request *dhr = (const struct dccp_hdr_request *)(bp + fixed_hdrlen); fixed_hdrlen += 4; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "%s (service=%d) ", tok2str(dccp_pkt_type_str, "", dccph_type), EXTRACT_32BITS(&dhr->dccph_req_service))); break; } case DCCP_PKT_RESPONSE: { const struct dccp_hdr_response *dhr = (const struct dccp_hdr_response *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "%s (service=%d) ", tok2str(dccp_pkt_type_str, "", dccph_type), EXTRACT_32BITS(&dhr->dccph_resp_service))); break; } case DCCP_PKT_DATA: ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_RESET: { const struct dccp_hdr_reset *dhr = (const struct dccp_hdr_reset *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); ND_PRINT((ndo, "%s (code=%s) ", tok2str(dccp_pkt_type_str, "", dccph_type), dccp_reset_code(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), len - fixed_hdrlen)); return; } ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; default: ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type))); 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){ 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; }
void tcp_print(register const u_char *bp, register u_int length, register const u_char *bp2, int fragmented) { register const struct tcphdr *tp; register const struct ip *ip; register u_char flags; register u_int hlen; register char ch; u_int16_t sport, dport, win, urp; u_int32_t seq, ack, thseq, thack; u_int utoval; int threv; #ifdef INET6 register const struct ip6_hdr *ip6; #endif tp = (struct tcphdr *)bp; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ ch = '\0'; if (!TTEST(tp->th_dport)) { (void)printf("%s > %s: [|tcp]", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); return; } sport = EXTRACT_16BITS(&tp->th_sport); dport = EXTRACT_16BITS(&tp->th_dport); hlen = TH_OFF(tp) * 4; /* * If data present, header length valid, and NFS port used, * assume NFS. * Pass offset of data plus 4 bytes for RPC TCP msg length * to NFS print routines. */ if (!qflag && hlen >= sizeof(*tp) && hlen <= length && (length - hlen) >= 4) { u_char *fraglenp; u_int32_t fraglen; register struct sunrpc_msg *rp; enum sunrpc_msg_type direction; fraglenp = (u_char *)tp + hlen; if (TTEST2(*fraglenp, 4)) { fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF; if (fraglen > (length - hlen) - 4) fraglen = (length - hlen) - 4; rp = (struct sunrpc_msg *)(fraglenp + 4); if (TTEST(rp->rm_direction)) { direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); if (dport == NFS_PORT && direction == SUNRPC_CALL) { nfsreq_print((u_char *)rp, fraglen, (u_char *)ip); return; } if (sport == NFS_PORT && direction == SUNRPC_REPLY) { nfsreply_print((u_char *)rp, fraglen, (u_char *)ip); return; } } } } #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ip6addr_string(&ip6->ip6_src), tcpport_string(sport), ip6addr_string(&ip6->ip6_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } if (hlen < sizeof(*tp)) { (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp)); return; } TCHECK(*tp); seq = EXTRACT_32BITS(&tp->th_seq); ack = EXTRACT_32BITS(&tp->th_ack); win = EXTRACT_16BITS(&tp->th_win); urp = EXTRACT_16BITS(&tp->th_urp); if (qflag) { (void)printf("tcp %d", length - hlen); if (hlen > length) { (void)printf(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = tp->th_flags; printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!Sflag && (flags & TH_ACK)) { register struct tcp_seq_hash *th; const void *src, *dst; register int rev; struct tha tha; /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ #ifdef INET6 rev = 0; if (ip6) { src = &ip6->ip6_src; dst = &ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip6->ip6_dst); memcpy(&tha.dst, src, sizeof ip6->ip6_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip6->ip6_dst); memcpy(&tha.src, src, sizeof ip6->ip6_src); tha.port = sport << 16 | dport; } } else { /* * Zero out the tha structure; the src and dst * fields are big enough to hold an IPv6 * address, but we only have IPv4 addresses * and thus must clear out the remaining 124 * bits. * * XXX - should we just clear those bytes after * copying the IPv4 addresses, rather than * zeroing out the entire structure and then * overwriting some of the zeroes? * * XXX - this could fail if we see TCP packets * with an IPv6 address with the lower 124 bits * all zero and also see TCP packes with an * IPv4 address with the same 32 bits as the * upper 32 bits of the IPv6 address in question. * Can that happen? Is it likely enough to be * an issue? */ memset(&tha, 0, sizeof(tha)); src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip->ip_dst); memcpy(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip->ip_dst); memcpy(&tha.src, src, sizeof ip->ip_src); tha.port = sport << 16 | dport; } } #else rev = 0; src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip->ip_dst); memcpy(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip->ip_dst); memcpy(&tha.src, src, sizeof ip->ip_src); tha.port = sport << 16 | dport; } #endif threv = rev; for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { /*fool gcc*/ thseq = thack = threv = 0; } if (hlen > length) { (void)printf(" [bad hdr length %u - too long, > %u]", hlen, length); return; } if (IP_V(ip) == 4 && vflag && !Kflag && !fragmented) { u_int16_t sum, tcp_sum; if (TTEST2(tp->th_sport, length)) { sum = tcp_cksum(ip, tp, length); (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" (correct)"); } } #ifdef INET6 if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !Kflag && !fragmented) { u_int16_t sum,tcp_sum; if (TTEST2(tp->th_sport, length)) { sum = nextproto6_cksum(ip6, (u_short *)tp, length, IPPROTO_TCP); (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" (correct)"); } } #endif length -= hlen; if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { (void)printf(", seq %u", seq); if (length > 0) { (void)printf(":%u", seq + length); } } if (flags & TH_ACK) { (void)printf(", ack %u", ack); } (void)printf(", win %d", win); if (flags & TH_URG) (void)printf(", urg %d", urp); /* * Handle any options. */ if (hlen > sizeof(*tp)) { register const u_char *cp; register u_int i, opt, datalen; register u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); printf(", options ["); while (hlen > 0) { if (ch != '\0') putchar(ch); TCHECK(*cp); opt = *cp++; if (ZEROLENOPT(opt)) len = 1; else { TCHECK(*cp); len = *cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt)); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); (void)printf(" %u", EXTRACT_16BITS(cp)); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); (void)printf(" %u", *cp); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { (void)printf("malformed sack"); } else { u_int32_t s, e; (void)printf(" %d ", datalen / 8); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = EXTRACT_32BITS(cp + i); LENCHECK(i + 8); e = EXTRACT_32BITS(cp + i + 4); if (threv) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } (void)printf("{%u:%u}", s, e); } } break; case TCPOPT_CC: case TCPOPT_CCNEW: case TCPOPT_CCECHO: case TCPOPT_ECHO: case TCPOPT_ECHOREPLY: /* * those options share their semantics. * fall through */ datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); (void)printf(" val %u ecr %u", EXTRACT_32BITS(cp), EXTRACT_32BITS(cp + 4)); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: (void)printf("valid"); break; case SIGNATURE_INVALID: (void)printf("invalid"); break; case CANT_CHECK_SIGNATURE: (void)printf("can't check - "); for (i = 0; i < TCP_SIGLEN; ++i) (void)printf("%02x", cp[i]); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) (void)printf("%02x", cp[i]); #endif break; case TCPOPT_AUTH: (void)printf("keyid %d", *cp++); datalen = len - 3; for (i = 0; i < datalen; ++i) { LENCHECK(i); (void)printf("%02x", cp[i]); } break; case TCPOPT_EOL: case TCPOPT_NOP: case TCPOPT_SACKOK: /* * Nothing interesting. * fall through */ break; case TCPOPT_UTO: datalen = 2; LENCHECK(datalen); utoval = EXTRACT_16BITS(cp); (void)printf("0x%x", utoval); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; (void)printf(" %u", utoval); break; default: datalen = len - 2; for (i = 0; i < datalen; ++i) { LENCHECK(i); (void)printf("%02x", cp[i]); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) (void)printf("[len %d]", len); ch = ','; if (opt == TCPOPT_EOL) break; } putchar(']'); }
static void mobility_opt_print(const u_char *bp, int len) { int i; int optlen; for (i = 0; i < len; i += optlen) { if (bp[i] == IP6MOPT_PAD1) optlen = 1; else { if (i + 1 < len) optlen = bp[i + 1] + 2; else goto trunc; } if (i + optlen > len) goto trunc; switch (bp[i]) { case IP6MOPT_PAD1: printf("(pad1)"); break; case IP6MOPT_PADN: if (len - i < IP6MOPT_MINLEN) { printf("(padn: trunc)"); goto trunc; } printf("(padn)"); break; case IP6MOPT_REFRESH: if (len - i < IP6MOPT_REFRESH_MINLEN) { printf("(refresh: trunc)"); goto trunc; } /* units of 4 secs */ printf("(refresh: %d)", EXTRACT_16BITS(&bp[i+2]) << 2); break; case IP6MOPT_ALTCOA: if (len - i < IP6MOPT_ALTCOA_MINLEN) { printf("(altcoa: trunc)"); goto trunc; } printf("(alt-CoA: %s)", ip6addr_string(&bp[i+2])); break; case IP6MOPT_NONCEID: if (len - i < IP6MOPT_NONCEID_MINLEN) { printf("(ni: trunc)"); goto trunc; } printf("(ni: ho=0x%04x co=0x%04x)", EXTRACT_16BITS(&bp[i+2]), EXTRACT_16BITS(&bp[i+4])); break; case IP6MOPT_AUTH: if (len - i < IP6MOPT_AUTH_MINLEN) { printf("(auth: trunc)"); goto trunc; } printf("(auth)"); break; default: if (len - i < IP6MOPT_MINLEN) { printf("(sopt_type %d: trunc)", bp[i]); goto trunc; } printf("(type-0x%02x: len=%d)", bp[i], bp[i + 1]); break; } } return; trunc: printf("[trunc] "); }
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]"); }
void ip6_opt_print(const u_char *bp, int len) { int i; int optlen = 0; for (i = 0; i < len; i += optlen) { if (bp[i] == IP6OPT_PAD1) optlen = 1; else { if (i + 1 < len) optlen = bp[i + 1] + 2; else goto trunc; } if (i + optlen > len) goto trunc; switch (bp[i]) { case IP6OPT_PAD1: printf("(pad1)"); break; case IP6OPT_PADN: if (len - i < IP6OPT_MINLEN) { printf("(padn: trunc)"); goto trunc; } printf("(padn)"); break; case IP6OPT_ROUTER_ALERT: if (len - i < IP6OPT_RTALERT_LEN) { printf("(rtalert: trunc)"); goto trunc; } if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) { printf("(rtalert: invalid len %d)", bp[i + 1]); goto trunc; } printf("(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2])); break; case IP6OPT_JUMBO: if (len - i < IP6OPT_JUMBO_LEN) { printf("(jumbo: trunc)"); goto trunc; } if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) { printf("(jumbo: invalid len %d)", bp[i + 1]); goto trunc; } printf("(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2])); break; case IP6OPT_HOME_ADDRESS: if (len - i < IP6OPT_HOMEADDR_MINLEN) { printf("(homeaddr: trunc)"); goto trunc; } if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) { printf("(homeaddr: invalid len %d)", bp[i + 1]); goto trunc; } printf("(homeaddr: %s", ip6addr_string(&bp[i + 2])); if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN], (optlen - IP6OPT_HOMEADDR_MINLEN)); } printf(")"); break; case IP6OPT_BINDING_UPDATE: if (len - i < IP6OPT_BU_MINLEN) { printf("(bu: trunc)"); goto trunc; } if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) { printf("(bu: invalid len %d)", bp[i + 1]); goto trunc; } printf("(bu: "); if (bp[i + 2] & 0x80) printf("A"); if (bp[i + 2] & 0x40) printf("H"); if (bp[i + 2] & 0x20) printf("S"); if (bp[i + 2] & 0x10) printf("D"); if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4]) printf("res"); printf(", sequence: %u", bp[i + 5]); printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 6])); if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN], (optlen - IP6OPT_BU_MINLEN)); } printf(")"); break; case IP6OPT_BINDING_ACK: if (len - i < IP6OPT_BA_MINLEN) { printf("(ba: trunc)"); goto trunc; } if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) { printf("(ba: invalid len %d)", bp[i + 1]); goto trunc; } printf("(ba: "); printf("status: %u", bp[i + 2]); if (bp[i + 3]) printf("res"); printf(", sequence: %u", bp[i + 4]); printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 5])); printf(", refresh: %u", EXTRACT_32BITS(&bp[i + 9])); if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN], (optlen - IP6OPT_BA_MINLEN)); } printf(")"); break; case IP6OPT_BINDING_REQ: if (len - i < IP6OPT_BR_MINLEN) { printf("(br: trunc)"); goto trunc; } printf("(br"); if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) { ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN], (optlen - IP6OPT_BR_MINLEN)); } printf(")"); break; default: if (len - i < IP6OPT_MINLEN) { printf("(type %d: trunc)", bp[i]); goto trunc; } printf("(opt_type 0x%02x: len=%d) ", bp[i], bp[i + 1]); break; } } #if 0 end: #endif return; trunc: printf("[trunc] "); }
/* * Print a single PDU. */ static void rpki_rtr_pdu_print (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 = (rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = EXTRACT_32BITS(pdu_header->length); hexdump = FALSE; printf("%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); printf("%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: printf("%sSession ID: 0x%04x", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.session_id)); break; case RPKI_RTR_IPV4_PREFIX_PDU: { rpki_rtr_pdu_ipv4_prefix *pdu; pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr; printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ipaddr_string(pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags); } break; #ifdef INET6 case RPKI_RTR_IPV6_PREFIX_PDU: { rpki_rtr_pdu_ipv6_prefix *pdu; pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr; printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ip6addr_string(pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags); } break; #endif case RPKI_RTR_ERROR_REPORT_PDU: { rpki_rtr_pdu_error_report *pdu; u_int encapsulated_pdu_length, text_length, tlen, error_code; u_char buf[80]; pdu = (rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); tlen = pdu_len; error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); printf("%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)) { printf("%s-----encapsulated PDU-----", indent_string(indent+4)); rpki_rtr_pdu_print(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; } if (text_length && (text_length <= tlen )) { memcpy(buf, tptr, MIN(sizeof(buf)-1, text_length)); buf[text_length] = '\0'; printf("%sError text: %s", indent_string(indent+2), buf); } } break; default: /* * Unknown data, please hexdump. */ hexdump = TRUE; } /* do we also want to see a hex dump ? */ if (vflag > 1 || (vflag && hexdump)) { print_unknown_data(tptr,"\n\t ", pdu_len); } }
static void ip6_sopt_print(const u_char *bp, int len) { int i; int optlen; for (i = 0; i < len; i += optlen) { if (bp[i] == IP6OPT_PAD1) optlen = 1; else { if (i + 1 < len) optlen = bp[i + 1] + 2; else goto trunc; } if (i + optlen > len) goto trunc; switch (bp[i]) { case IP6OPT_PAD1: printf(", pad1"); break; case IP6OPT_PADN: if (len - i < IP6OPT_MINLEN) { printf(", padn: trunc"); goto trunc; } printf(", padn"); break; case IP6SOPT_UI: if (len - i < IP6SOPT_UI_MINLEN) { printf(", ui: trunc"); goto trunc; } printf(", ui: 0x%04x ", EXTRACT_16BITS(&bp[i + 2])); break; case IP6SOPT_ALTCOA: if (len - i < IP6SOPT_ALTCOA_MINLEN) { printf(", altcoa: trunc"); goto trunc; } printf(", alt-CoA: %s", ip6addr_string(&bp[i+2])); break; case IP6SOPT_AUTH: if (len - i < IP6SOPT_AUTH_MINLEN) { printf(", auth: trunc"); goto trunc; } printf(", auth spi: 0x%08x", EXTRACT_32BITS(&bp[i + 2])); break; default: if (len - i < IP6OPT_MINLEN) { printf(", sopt_type %d: trunc)", bp[i]); goto trunc; } printf(", sopt_type 0x%02x: len=%d", bp[i], bp[i + 1]); break; } } return; trunc: printf("[trunc] "); }
void pgm_print(register const u_char *bp, register u_int length, register const u_char *bp2) { register const struct pgm_header *pgm; register const struct ip *ip; register char ch; u_int16_t sport, dport; int addr_size; const void *nla; int nla_af; #ifdef INET6 char nla_buf[INET6_ADDRSTRLEN]; register const struct ip6_hdr *ip6; #else char nla_buf[INET_ADDRSTRLEN]; #endif u_int8_t opt_type, opt_len, flags1, flags2; u_int32_t seq, opts_len, len, offset; pgm = (struct pgm_header *)bp; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (struct ip6_hdr *)bp2; else ip6 = NULL; #else /* INET6 */ if (IP_V(ip) == 6) { (void)printf("Can't handle IPv6"); return; } #endif /* INET6 */ ch = '\0'; if (!TTEST(pgm->pgm_dport)) { #ifdef INET6 if (ip6) { (void)printf("%s > %s: [|pgm]", ip6addr_string(&ip6->ip6_src), ip6addr_string(&ip6->ip6_dst)); return; } else #endif /* INET6 */ { (void)printf("%s > %s: [|pgm]", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); return; } } sport = EXTRACT_16BITS(&pgm->pgm_sport); dport = EXTRACT_16BITS(&pgm->pgm_dport); #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_PGM) { (void)printf("%s.%s > %s.%s: ", ip6addr_string(&ip6->ip6_src), tcpport_string(sport), ip6addr_string(&ip6->ip6_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_PGM) { (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } TCHECK(*pgm); (void)printf("PGM, length %u", pgm->pgm_length); if (!vflag) return; if (length > pgm->pgm_length) length = pgm->pgm_length; (void)printf(" 0x%02x%02x%02x%02x%02x%02x ", pgm->pgm_gsid[0], pgm->pgm_gsid[1], pgm->pgm_gsid[2], pgm->pgm_gsid[3], pgm->pgm_gsid[4], pgm->pgm_gsid[5]); switch (pgm->pgm_type) { case PGM_SPM: { struct pgm_spm *spm; spm = (struct pgm_spm *)(pgm + 1); TCHECK(*spm); switch (EXTRACT_16BITS(&spm->pgms_nla_afi)) { case AFI_IP: addr_size = sizeof(struct in_addr); nla_af = AF_INET; break; #ifdef INET6 case AFI_IP6: addr_size = sizeof(struct in6_addr); nla_af = AF_INET6; break; #endif default: goto trunc; break; } bp = (u_char *) (spm + 1); TCHECK2(*bp, addr_size); nla = bp; bp += addr_size; inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); (void)printf("SPM seq %u trail %u lead %u nla %s", EXTRACT_32BITS(&spm->pgms_seq), EXTRACT_32BITS(&spm->pgms_trailseq), EXTRACT_32BITS(&spm->pgms_leadseq), nla_buf); break; } case PGM_POLL: { struct pgm_poll *poll; poll = (struct pgm_poll *)(pgm + 1); TCHECK(*poll); (void)printf("POLL seq %u round %u", EXTRACT_32BITS(&poll->pgmp_seq), EXTRACT_16BITS(&poll->pgmp_round)); bp = (u_char *) (poll + 1); break; } case PGM_POLR: { struct pgm_polr *polr; u_int32_t ivl, rnd, mask; polr = (struct pgm_polr *)(pgm + 1); TCHECK(*polr); switch (EXTRACT_16BITS(&polr->pgmp_nla_afi)) { case AFI_IP: addr_size = sizeof(struct in_addr); nla_af = AF_INET; break; #ifdef INET6 case AFI_IP6: addr_size = sizeof(struct in6_addr); nla_af = AF_INET6; break; #endif default: goto trunc; break; } bp = (u_char *) (polr + 1); TCHECK2(*bp, addr_size); nla = bp; bp += addr_size; inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); TCHECK2(*bp, sizeof(u_int32_t)); ivl = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); TCHECK2(*bp, sizeof(u_int32_t)); rnd = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); TCHECK2(*bp, sizeof(u_int32_t)); mask = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf("POLR seq %u round %u nla %s ivl %u rnd 0x%08x " "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq), EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask); break; } case PGM_ODATA: { struct pgm_data *odata; odata = (struct pgm_data *)(pgm + 1); TCHECK(*odata); (void)printf("ODATA trail %u seq %u", EXTRACT_32BITS(&odata->pgmd_trailseq), EXTRACT_32BITS(&odata->pgmd_seq)); bp = (u_char *) (odata + 1); break; } case PGM_RDATA: { struct pgm_data *rdata; rdata = (struct pgm_data *)(pgm + 1); TCHECK(*rdata); (void)printf("RDATA trail %u seq %u", EXTRACT_32BITS(&rdata->pgmd_trailseq), EXTRACT_32BITS(&rdata->pgmd_seq)); bp = (u_char *) (rdata + 1); break; } case PGM_NAK: case PGM_NULLNAK: case PGM_NCF: { struct pgm_nak *nak; const void *source, *group; int source_af, group_af; #ifdef INET6 char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN]; #else char source_buf[INET_ADDRSTRLEN], group_buf[INET_ADDRSTRLEN]; #endif nak = (struct pgm_nak *)(pgm + 1); TCHECK(*nak); /* * Skip past the source, saving info along the way * and stopping if we don't have enough. */ switch (EXTRACT_16BITS(&nak->pgmn_source_afi)) { case AFI_IP: addr_size = sizeof(struct in_addr); source_af = AF_INET; break; #ifdef INET6 case AFI_IP6: addr_size = sizeof(struct in6_addr); source_af = AF_INET6; break; #endif default: goto trunc; break; } bp = (u_char *) (nak + 1); TCHECK2(*bp, addr_size); source = bp; bp += addr_size; /* * Skip past the group, saving info along the way * and stopping if we don't have enough. */ switch (EXTRACT_16BITS(bp)) { case AFI_IP: addr_size = sizeof(struct in_addr); group_af = AF_INET; break; #ifdef INET6 case AFI_IP6: addr_size = sizeof(struct in6_addr); group_af = AF_INET6; break; #endif default: goto trunc; break; } bp += (2 * sizeof(u_int16_t)); TCHECK2(*bp, addr_size); group = bp; bp += addr_size; /* * Options decoding can go here. */ inet_ntop(source_af, source, source_buf, sizeof(source_buf)); inet_ntop(group_af, group, group_buf, sizeof(group_buf)); switch (pgm->pgm_type) { case PGM_NAK: (void)printf("NAK "); break; case PGM_NULLNAK: (void)printf("NNAK "); break; case PGM_NCF: (void)printf("NCF "); break; default: break; } (void)printf("(%s -> %s), seq %u", source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq)); break; } case PGM_ACK: { struct pgm_ack *ack; ack = (struct pgm_ack *)(pgm + 1); TCHECK(*ack); (void)printf("ACK seq %u", EXTRACT_32BITS(&ack->pgma_rx_max_seq)); bp = (u_char *) (ack + 1); break; } case PGM_SPMR: (void)printf("SPMR"); break; default: (void)printf("UNKNOWN type %0x02x", pgm->pgm_type); break; } if (pgm->pgm_options & PGM_OPT_BIT_PRESENT) { /* * make sure there's enough for the first option header */ if (!TTEST2(*bp, PGM_MIN_OPT_LEN)) { (void)printf("[|OPT]"); return; } /* * That option header MUST be an OPT_LENGTH option * (see the first paragraph of section 9.1 in RFC 3208). */ opt_type = *bp++; if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) { (void)printf("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK); return; } opt_len = *bp++; if (opt_len != 4) { (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len); return; } opts_len = EXTRACT_16BITS(bp); if (opts_len < 4) { (void)printf("[Bad total option length %u < 4]", opts_len); return; } bp += sizeof(u_int16_t); (void)printf(" OPTS LEN %d", opts_len); opts_len -= 4; while (opts_len) { if (opts_len < PGM_MIN_OPT_LEN) { (void)printf("[Total option length leaves no room for final option]"); return; } opt_type = *bp++; opt_len = *bp++; if (opt_len < PGM_MIN_OPT_LEN) { (void)printf("[Bad option, length %u < %u]", opt_len, PGM_MIN_OPT_LEN); break; } if (opts_len < opt_len) { (void)printf("[Total option length leaves no room for final option]"); return; } if (!TTEST2(*bp, opt_len - 2)) { (void)printf(" [|OPT]"); return; } switch (opt_type & PGM_OPT_MASK) { case PGM_OPT_LENGTH: if (opt_len != 4) { (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len); return; } (void)printf(" OPTS LEN (extra?) %d", EXTRACT_16BITS(bp)); bp += sizeof(u_int16_t); opts_len -= 4; break; case PGM_OPT_FRAGMENT: if (opt_len != 16) { (void)printf("[Bad OPT_FRAGMENT option, length %u != 16]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; seq = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); offset = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); len = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf(" FRAG seq %u off %u len %u", seq, offset, len); opts_len -= 16; break; case PGM_OPT_NAK_LIST: flags1 = *bp++; flags2 = *bp++; opt_len -= sizeof(u_int32_t); /* option header */ (void)printf(" NAK LIST"); while (opt_len) { if (opt_len < sizeof(u_int32_t)) { (void)printf("[Option length not a multiple of 4]"); return; } TCHECK2(*bp, sizeof(u_int32_t)); (void)printf(" %u", EXTRACT_32BITS(bp)); bp += sizeof(u_int32_t); opt_len -= sizeof(u_int32_t); opts_len -= sizeof(u_int32_t); } break; case PGM_OPT_JOIN: if (opt_len != 8) { (void)printf("[Bad OPT_JOIN option, length %u != 8]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; seq = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf(" JOIN %u", seq); opts_len -= 8; break; case PGM_OPT_NAK_BO_IVL: if (opt_len != 12) { (void)printf("[Bad OPT_NAK_BO_IVL option, length %u != 12]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; offset = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); seq = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf(" BACKOFF ivl %u ivlseq %u", offset, seq); opts_len -= 12; break; case PGM_OPT_NAK_BO_RNG: if (opt_len != 12) { (void)printf("[Bad OPT_NAK_BO_RNG option, length %u != 12]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; offset = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); seq = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf(" BACKOFF max %u min %u", offset, seq); opts_len -= 12; break; case PGM_OPT_REDIRECT: flags1 = *bp++; flags2 = *bp++; switch (EXTRACT_16BITS(bp)) { case AFI_IP: addr_size = sizeof(struct in_addr); nla_af = AF_INET; break; #ifdef INET6 case AFI_IP6: addr_size = sizeof(struct in6_addr); nla_af = AF_INET6; break; #endif default: goto trunc; break; } bp += (2 * sizeof(u_int16_t)); if (opt_len != 4 + addr_size) { (void)printf("[Bad OPT_REDIRECT option, length %u != 4 + address size]", opt_len); return; } TCHECK2(*bp, addr_size); nla = bp; bp += addr_size; inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); (void)printf(" REDIRECT %s", (char *)nla); opts_len -= 4 + addr_size; break; case PGM_OPT_PARITY_PRM: if (opt_len != 8) { (void)printf("[Bad OPT_PARITY_PRM option, length %u != 8]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; len = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf(" PARITY MAXTGS %u", len); opts_len -= 8; break; case PGM_OPT_PARITY_GRP: if (opt_len != 8) { (void)printf("[Bad OPT_PARITY_GRP option, length %u != 8]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; seq = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf(" PARITY GROUP %u", seq); opts_len -= 8; break; case PGM_OPT_CURR_TGSIZE: if (opt_len != 8) { (void)printf("[Bad OPT_CURR_TGSIZE option, length %u != 8]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; len = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); (void)printf(" PARITY ATGS %u", len); opts_len -= 8; break; case PGM_OPT_NBR_UNREACH: if (opt_len != 4) { (void)printf("[Bad OPT_NBR_UNREACH option, length %u != 4]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; (void)printf(" NBR_UNREACH"); opts_len -= 4; break; case PGM_OPT_PATH_NLA: (void)printf(" PATH_NLA [%d]", opt_len); bp += opt_len; opts_len -= opt_len; break; case PGM_OPT_SYN: if (opt_len != 4) { (void)printf("[Bad OPT_SYN option, length %u != 4]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; (void)printf(" SYN"); opts_len -= 4; break; case PGM_OPT_FIN: if (opt_len != 4) { (void)printf("[Bad OPT_FIN option, length %u != 4]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; (void)printf(" FIN"); opts_len -= 4; break; case PGM_OPT_RST: if (opt_len != 4) { (void)printf("[Bad OPT_RST option, length %u != 4]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; (void)printf(" RST"); opts_len -= 4; break; case PGM_OPT_CR: (void)printf(" CR"); bp += opt_len; opts_len -= opt_len; break; case PGM_OPT_CRQST: if (opt_len != 4) { (void)printf("[Bad OPT_CRQST option, length %u != 4]", opt_len); return; } flags1 = *bp++; flags2 = *bp++; (void)printf(" CRQST"); opts_len -= 4; break; case PGM_OPT_PGMCC_DATA: flags1 = *bp++; flags2 = *bp++; offset = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); switch (EXTRACT_16BITS(bp)) { case AFI_IP: addr_size = sizeof(struct in_addr); nla_af = AF_INET; break; #ifdef INET6 case AFI_IP6: addr_size = sizeof(struct in6_addr); nla_af = AF_INET6; break; #endif default: goto trunc; break; } bp += (2 * sizeof(u_int16_t)); if (opt_len != 12 + addr_size) { (void)printf("[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len); return; } TCHECK2(*bp, addr_size); nla = bp; bp += addr_size; inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); (void)printf(" PGMCC DATA %u %s", offset, (char*)nla); opts_len -= 16; break; case PGM_OPT_PGMCC_FEEDBACK: flags1 = *bp++; flags2 = *bp++; offset = EXTRACT_32BITS(bp); bp += sizeof(u_int32_t); switch (EXTRACT_16BITS(bp)) { case AFI_IP: addr_size = sizeof(struct in_addr); nla_af = AF_INET; break; #ifdef INET6 case AFI_IP6: addr_size = sizeof(struct in6_addr); nla_af = AF_INET6; break; #endif default: goto trunc; break; } bp += (2 * sizeof(u_int16_t)); if (opt_len != 12 + addr_size) { (void)printf("[Bad OPT_PGMCC_FEEDBACK option, length %u != 12 + address size]", opt_len); return; } TCHECK2(*bp, addr_size); nla = bp; bp += addr_size; inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); (void)printf(" PGMCC FEEDBACK %u %s", offset, (char*)nla); opts_len -= 16; break; default: (void)printf(" OPT_%02X [%d] ", opt_type, opt_len); bp += opt_len; opts_len -= opt_len; break; } if (opt_type & PGM_OPT_END) break; } } (void)printf(" [%u]", EXTRACT_16BITS(&pgm->pgm_length)); return; trunc: fputs("[|pgm]", stdout); if (ch != '\0') putchar('>'); }
void sctp_print(netdissect_options *ndo, const u_char *bp, /* beginning of sctp packet */ const u_char *bp2, /* beginning of enclosing */ u_int sctpPacketLength) /* ip packet */ { u_int sctpPacketLengthRemaining; const struct sctpHeader *sctpPktHdr; const struct ip *ip; const struct ip6_hdr *ip6; uint8_t chunkID; u_short sourcePort, destPort; u_int chunkCount; const struct sctpChunkDesc *chunkDescPtr; const char *sep; int isforces = 0; ndo->ndo_protocol = "sctp"; if (sctpPacketLength < sizeof(struct sctpHeader)) { ND_PRINT("truncated-sctp - %ld bytes missing!", (long)(sizeof(struct sctpHeader) - sctpPacketLength)); return; } sctpPktHdr = (const struct sctpHeader*) bp; ND_TCHECK_SIZE(sctpPktHdr); sctpPacketLengthRemaining = sctpPacketLength; sourcePort = EXTRACT_BE_U_2(sctpPktHdr->source); destPort = EXTRACT_BE_U_2(sctpPktHdr->destination); ip = (const struct ip *)bp2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; if (ip6) { ND_PRINT("%s.%u > %s.%u: sctp", ip6addr_string(ndo, ip6->ip6_src), sourcePort, ip6addr_string(ndo, ip6->ip6_dst), destPort); } else { ND_PRINT("%s.%u > %s.%u: sctp", ipaddr_string(ndo, ip->ip_src), sourcePort, ipaddr_string(ndo, ip->ip_dst), destPort); } if (isForCES_port(sourcePort)) { ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, sourcePort)); isforces = 1; } if (isForCES_port(destPort)) { ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, destPort)); isforces = 1; } bp += sizeof(struct sctpHeader); sctpPacketLengthRemaining -= sizeof(struct sctpHeader); if (ndo->ndo_vflag >= 2) sep = "\n\t"; else sep = " ("; /* cycle through all chunks, printing information on each one */ for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *)bp; sctpPacketLengthRemaining != 0; chunkCount++) { uint16_t chunkLength, chunkLengthRemaining; uint16_t align; chunkDescPtr = (const struct sctpChunkDesc *)bp; if (sctpPacketLengthRemaining < sizeof(*chunkDescPtr)) { ND_PRINT("%s%u) [chunk descriptor cut off at end of packet]", sep, chunkCount+1); break; } ND_TCHECK_SIZE(chunkDescPtr); chunkLength = EXTRACT_BE_U_2(chunkDescPtr->chunkLength); if (chunkLength < sizeof(*chunkDescPtr)) { ND_PRINT("%s%u) [Bad chunk length %u, < size of chunk descriptor]", sep, chunkCount+1, chunkLength); break; } chunkLengthRemaining = chunkLength; align = chunkLength % 4; if (align != 0) align = 4 - align; if (sctpPacketLengthRemaining < align) { ND_PRINT("%s%u) [Bad chunk length %u, > remaining data in packet]", sep, chunkCount+1, chunkLength); break; } ND_TCHECK_LEN(bp, chunkLength); bp += sizeof(*chunkDescPtr); sctpPacketLengthRemaining -= sizeof(*chunkDescPtr); chunkLengthRemaining -= sizeof(*chunkDescPtr); ND_PRINT("%s%u) ", sep, chunkCount+1); chunkID = EXTRACT_U_1(chunkDescPtr->chunkID); ND_PRINT("[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x", chunkID)); switch (chunkID) { case SCTP_DATA : { const struct sctpDataPart *dataHdrPtr; uint8_t chunkFlg; uint32_t ppid; u_int payload_size; chunkFlg = EXTRACT_U_1(chunkDescPtr->chunkFlg); if ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) ND_PRINT("(U)"); if ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) ND_PRINT("(B)"); if ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ND_PRINT("(E)"); if( ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) || ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) ND_PRINT(" "); if (chunkLengthRemaining < sizeof(*dataHdrPtr)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } dataHdrPtr=(const struct sctpDataPart*)bp; ppid = EXTRACT_BE_U_4(dataHdrPtr->payloadtype); ND_PRINT("[TSN: %u] ", EXTRACT_BE_U_4(dataHdrPtr->TSN)); ND_PRINT("[SID: %u] ", EXTRACT_BE_U_2(dataHdrPtr->streamId)); ND_PRINT("[SSEQ %u] ", EXTRACT_BE_U_2(dataHdrPtr->sequence)); ND_PRINT("[PPID %s] ", tok2str(PayloadProto_idents, "0x%x", ppid)); if (!isforces) { isforces = (ppid == SCTP_PPID_FORCES_HP) || (ppid == SCTP_PPID_FORCES_MP) || (ppid == SCTP_PPID_FORCES_LP); } bp += sizeof(*dataHdrPtr); sctpPacketLengthRemaining -= sizeof(*dataHdrPtr); chunkLengthRemaining -= sizeof(*dataHdrPtr); payload_size = chunkLengthRemaining; if (payload_size == 0) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } if (isforces) { forces_print(ndo, bp, payload_size); } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */ /* at the command line */ switch (ppid) { case SCTP_PPID_M3UA : m3ua_print(ndo, bp, payload_size); break; default: ND_PRINT("[Payload"); if (!ndo->ndo_suppress_default_print) { ND_PRINT(":"); ND_DEFAULTPRINT(bp, payload_size); } ND_PRINT("]"); break; } } bp += payload_size; sctpPacketLengthRemaining -= payload_size; chunkLengthRemaining -= payload_size; break; } case SCTP_INITIATION : { const struct sctpInitiation *init; if (chunkLengthRemaining < sizeof(*init)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } init=(const struct sctpInitiation*)bp; ND_PRINT("[init tag: %u] ", EXTRACT_BE_U_4(init->initTag)); ND_PRINT("[rwnd: %u] ", EXTRACT_BE_U_4(init->rcvWindowCredit)); ND_PRINT("[OS: %u] ", EXTRACT_BE_U_2(init->NumPreopenStreams)); ND_PRINT("[MIS: %u] ", EXTRACT_BE_U_2(init->MaxInboundStreams)); ND_PRINT("[init TSN: %u] ", EXTRACT_BE_U_4(init->initialTSN)); bp += sizeof(*init); sctpPacketLengthRemaining -= sizeof(*init); chunkLengthRemaining -= sizeof(*init); #if 0 /* ALC you can add code for optional params here */ if( chunkLengthRemaining != 0 ) ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; chunkLengthRemaining = 0; break; } case SCTP_INITIATION_ACK : { const struct sctpInitiation *init; if (chunkLengthRemaining < sizeof(*init)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } init=(const struct sctpInitiation*)bp; ND_PRINT("[init tag: %u] ", EXTRACT_BE_U_4(init->initTag)); ND_PRINT("[rwnd: %u] ", EXTRACT_BE_U_4(init->rcvWindowCredit)); ND_PRINT("[OS: %u] ", EXTRACT_BE_U_2(init->NumPreopenStreams)); ND_PRINT("[MIS: %u] ", EXTRACT_BE_U_2(init->MaxInboundStreams)); ND_PRINT("[init TSN: %u] ", EXTRACT_BE_U_4(init->initialTSN)); bp += sizeof(*init); sctpPacketLengthRemaining -= sizeof(*init); chunkLengthRemaining -= sizeof(*init); #if 0 /* ALC you can add code for optional params here */ if( chunkLengthRemaining != 0 ) ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; chunkLengthRemaining = 0; break; } case SCTP_SELECTIVE_ACK: { const struct sctpSelectiveAck *sack; const struct sctpSelectiveFrag *frag; u_int fragNo, tsnNo; const u_char *dupTSN; if (chunkLengthRemaining < sizeof(*sack)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } sack=(const struct sctpSelectiveAck*)bp; ND_PRINT("[cum ack %u] ", EXTRACT_BE_U_4(sack->highestConseqTSN)); ND_PRINT("[a_rwnd %u] ", EXTRACT_BE_U_4(sack->updatedRwnd)); ND_PRINT("[#gap acks %u] ", EXTRACT_BE_U_2(sack->numberOfdesc)); ND_PRINT("[#dup tsns %u] ", EXTRACT_BE_U_2(sack->numDupTsns)); bp += sizeof(*sack); sctpPacketLengthRemaining -= sizeof(*sack); chunkLengthRemaining -= sizeof(*sack); /* print gaps */ for (fragNo=0; chunkLengthRemaining != 0 && fragNo < EXTRACT_BE_U_2(sack->numberOfdesc); bp += sizeof(*frag), sctpPacketLengthRemaining -= sizeof(*frag), chunkLengthRemaining -= sizeof(*frag), fragNo++) { if (chunkLengthRemaining < sizeof(*frag)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } frag = (const struct sctpSelectiveFrag *)bp; ND_PRINT("\n\t\t[gap ack block #%u: start = %u, end = %u] ", fragNo+1, EXTRACT_BE_U_4(sack->highestConseqTSN) + EXTRACT_BE_U_2(frag->fragmentStart), EXTRACT_BE_U_4(sack->highestConseqTSN) + EXTRACT_BE_U_2(frag->fragmentEnd)); } /* print duplicate TSNs */ for (tsnNo=0; chunkLengthRemaining != 0 && tsnNo<EXTRACT_BE_U_2(sack->numDupTsns); bp += 4, sctpPacketLengthRemaining -= 4, chunkLengthRemaining -= 4, tsnNo++) { if (chunkLengthRemaining < 4) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } dupTSN = (const u_char *)bp; ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, EXTRACT_BE_U_4(dupTSN)); } break; } default : { bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; chunkLengthRemaining = 0; break; } } /* * Any extra stuff at the end of the chunk? * XXX - report this? */ bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; if (ndo->ndo_vflag < 2) sep = ", ("; if (align != 0) { /* * Fail if the alignment padding isn't in the captured data. * Otherwise, skip it. */ ND_TCHECK_LEN(bp, align); bp += align; sctpPacketLengthRemaining -= align; } } return; trunc: ND_PRINT("[|sctp]"); }