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);
}
Exemple #3
0
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;
	}
}
Exemple #4
0
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;
}
Exemple #6
0
static int
ldp_tlv_print(netdissect_options *ndo,
              const u_char *tptr,
              u_short msg_tlen)
{
    struct ldp_tlv_header {
        nd_uint16_t type;
        nd_uint16_t length;
    };

    const struct ldp_tlv_header *ldp_tlv_header;
    u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
    u_char fec_type;
    u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
    char buf[100];
    int i;

    ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
    ND_TCHECK_SIZE(ldp_tlv_header);
    tlv_len=EXTRACT_BE_U_2(ldp_tlv_header->length);
    if (tlv_len + 4 > msg_tlen) {
        ND_PRINT("\n\t\t TLV contents go past end of message");
        return 0;
    }
    tlv_tlen=tlv_len;
    tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_BE_U_2(ldp_tlv_header->type));

    /* FIXME vendor private / experimental check */
    ND_PRINT("\n\t    %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
           tok2str(ldp_tlv_values,
                   "Unknown",
                   tlv_type),
           tlv_type,
           tlv_len,
           LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore",
           LDP_MASK_F_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't");

    tptr+=sizeof(struct ldp_tlv_header);

    switch(tlv_type) {

    case LDP_TLV_COMMON_HELLO:
        TLV_TCHECK(4);
        ND_PRINT("\n\t      Hold Time: %us, Flags: [%s Hello%s]",
               EXTRACT_BE_U_2(tptr),
               (EXTRACT_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link",
               (EXTRACT_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : "");
        break;

    case LDP_TLV_IPV4_TRANSPORT_ADDR:
        TLV_TCHECK(4);
        ND_PRINT("\n\t      IPv4 Transport Address: %s", ipaddr_string(ndo, tptr));
        break;
    case LDP_TLV_IPV6_TRANSPORT_ADDR:
        TLV_TCHECK(16);
        ND_PRINT("\n\t      IPv6 Transport Address: %s", ip6addr_string(ndo, tptr));
        break;
    case LDP_TLV_CONFIG_SEQ_NUMBER:
        TLV_TCHECK(4);
        ND_PRINT("\n\t      Sequence Number: %u", EXTRACT_BE_U_4(tptr));
        break;

    case LDP_TLV_ADDRESS_LIST:
        TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN);
	af = EXTRACT_BE_U_2(tptr);
	tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
        tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
	ND_PRINT("\n\t      Address Family: %s, addresses",
               tok2str(af_values, "Unknown (%u)", af));
        switch (af) {
        case AFNUM_INET:
	    while(tlv_tlen >= sizeof(struct in_addr)) {
		ND_TCHECK_LEN(tptr, sizeof(struct in_addr));
		ND_PRINT(" %s", ipaddr_string(ndo, tptr));
		tlv_tlen-=sizeof(struct in_addr);
		tptr+=sizeof(struct in_addr);
	    }
            break;
        case AFNUM_INET6:
	    while(tlv_tlen >= sizeof(struct in6_addr)) {
		ND_TCHECK_LEN(tptr, sizeof(struct in6_addr));
		ND_PRINT(" %s", ip6addr_string(ndo, tptr));
		tlv_tlen-=sizeof(struct in6_addr);
		tptr+=sizeof(struct in6_addr);
	    }
            break;
        default:
            /* unknown AF */
            break;
        }
	break;

    case LDP_TLV_COMMON_SESSION:
	TLV_TCHECK(8);
	ND_PRINT("\n\t      Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
	       EXTRACT_BE_U_2(tptr), EXTRACT_BE_U_2(tptr + 2),
	       (EXTRACT_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited",
	       (EXTRACT_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled"
	       );
	break;

    case LDP_TLV_FEC:
        TLV_TCHECK(1);
        fec_type = EXTRACT_U_1(tptr);
	ND_PRINT("\n\t      %s FEC (0x%02x)",
	       tok2str(ldp_fec_values, "Unknown", fec_type),
	       fec_type);

	tptr+=1;
	tlv_tlen-=1;
	switch(fec_type) {

	case LDP_FEC_WILDCARD:
	    break;
	case LDP_FEC_PREFIX:
	    TLV_TCHECK(2);
	    af = EXTRACT_BE_U_2(tptr);
	    tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
	    tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
	    if (af == AFNUM_INET) {
		i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf));
		if (i == -2)
		    goto trunc;
		if (i == -3)
		    ND_PRINT(": IPv4 prefix (goes past end of TLV)");
		else if (i == -1)
		    ND_PRINT(": IPv4 prefix (invalid length)");
		else
		    ND_PRINT(": IPv4 prefix %s", buf);
	    }
	    else if (af == AFNUM_INET6) {
		i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf));
		if (i == -2)
		    goto trunc;
		if (i == -3)
		    ND_PRINT(": IPv4 prefix (goes past end of TLV)");
		else if (i == -1)
		    ND_PRINT(": IPv6 prefix (invalid length)");
		else
		    ND_PRINT(": IPv6 prefix %s", buf);
	    }
	    else
		ND_PRINT(": Address family %u prefix", af);
	    break;
	case LDP_FEC_HOSTADDRESS:
	    break;
	case LDP_FEC_MARTINI_VC:
            /*
             * We assume the type was supposed to be one of the MPLS
             * Pseudowire Types.
             */
            TLV_TCHECK(7);
            vc_info_len = EXTRACT_U_1(tptr + 2);

            /*
	     * According to RFC 4908, the VC info Length field can be zero,
	     * in which case not only are there no interface parameters,
	     * there's no VC ID.
	     */
            if (vc_info_len == 0) {
                ND_PRINT(": %s, %scontrol word, group-ID %u, VC-info-length: %u",
                       tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff),
                       EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ",
                       EXTRACT_BE_U_4(tptr + 3),
                       vc_info_len);
                break;
            }

            /* Make sure we have the VC ID as well */
            TLV_TCHECK(11);
	    ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
		   tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff),
		   EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ",
		   EXTRACT_BE_U_4(tptr + 3),
		   EXTRACT_BE_U_4(tptr + 7),
		   vc_info_len);
            if (vc_info_len < 4) {
                /* minimum 4, for the VC ID */
                ND_PRINT(" (invalid, < 4");
                return(tlv_len+4); /* Type & Length fields not included */
	    }
            vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */

            /* Skip past the fixed information and the VC ID */
            tptr+=11;
            tlv_tlen-=11;
            TLV_TCHECK(vc_info_len);

            while (vc_info_len > 2) {
                vc_info_tlv_type = EXTRACT_U_1(tptr);
                vc_info_tlv_len = EXTRACT_U_1(tptr + 1);
                if (vc_info_tlv_len < 2)
                    break;
                if (vc_info_len < vc_info_tlv_len)
                    break;

                ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u",
                       tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
                       vc_info_tlv_type,
                       vc_info_tlv_len);

                switch(vc_info_tlv_type) {
                case LDP_FEC_MARTINI_IFPARM_MTU:
                    ND_PRINT(": %u", EXTRACT_BE_U_2(tptr + 2));
                    break;

                case LDP_FEC_MARTINI_IFPARM_DESC:
                    ND_PRINT(": ");
                    for (idx = 2; idx < vc_info_tlv_len; idx++)
                        safeputchar(ndo, EXTRACT_U_1(tptr + idx));
                    break;

                case LDP_FEC_MARTINI_IFPARM_VCCV:
                    ND_PRINT("\n\t\t  Control Channels (0x%02x) = [%s]",
                           EXTRACT_U_1((tptr + 2)),
                           bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", EXTRACT_U_1((tptr + 2))));
                    ND_PRINT("\n\t\t  CV Types (0x%02x) = [%s]",
                           EXTRACT_U_1((tptr + 3)),
                           bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", EXTRACT_U_1((tptr + 3))));
                    break;

                default:
                    print_unknown_data(ndo, tptr+2, "\n\t\t  ", vc_info_tlv_len-2);
                    break;
                }

                vc_info_len -= vc_info_tlv_len;
                tptr += vc_info_tlv_len;
            }
	    break;
	}

	break;

    case LDP_TLV_GENERIC_LABEL:
	TLV_TCHECK(4);
	ND_PRINT("\n\t      Label: %u", EXTRACT_BE_U_4(tptr) & 0xfffff);
	break;

    case LDP_TLV_STATUS:
	TLV_TCHECK(8);
	ui = EXTRACT_BE_U_4(tptr);
	tptr+=4;
	ND_PRINT("\n\t      Status: 0x%02x, Flags: [%s and %s forward]",
	       ui&0x3fffffff,
	       ui&0x80000000 ? "Fatal error" : "Advisory Notification",
	       ui&0x40000000 ? "do" : "don't");
	ui = EXTRACT_BE_U_4(tptr);
	tptr+=4;
	if (ui)
	    ND_PRINT(", causing Message ID: 0x%08x", ui);
	break;

    case LDP_TLV_FT_SESSION:
	TLV_TCHECK(8);
	ft_flags = EXTRACT_BE_U_2(tptr);
	ND_PRINT("\n\t      Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
	       ft_flags&0x8000 ? "" : "No ",
	       ft_flags&0x8 ? "" : "Don't ",
	       ft_flags&0x4 ? "" : "No ",
	       ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
	       ft_flags&0x1 ? "" : "Don't ");
	tptr+=4;
	ui = EXTRACT_BE_U_4(tptr);
	if (ui)
	    ND_PRINT(", Reconnect Timeout: %ums", ui);
	tptr+=4;
	ui = EXTRACT_BE_U_4(tptr);
	if (ui)
	    ND_PRINT(", Recovery Time: %ums", ui);
	break;

    case LDP_TLV_MTU:
	TLV_TCHECK(2);
	ND_PRINT("\n\t      MTU: %u", EXTRACT_BE_U_2(tptr));
	break;


    /*
     *  FIXME those are the defined TLVs that lack a decoder
     *  you are welcome to contribute code ;-)
     */

    case LDP_TLV_HOP_COUNT:
    case LDP_TLV_PATH_VECTOR:
    case LDP_TLV_ATM_LABEL:
    case LDP_TLV_FR_LABEL:
    case LDP_TLV_EXTD_STATUS:
    case LDP_TLV_RETURNED_PDU:
    case LDP_TLV_RETURNED_MSG:
    case LDP_TLV_ATM_SESSION_PARM:
    case LDP_TLV_FR_SESSION_PARM:
    case LDP_TLV_LABEL_REQUEST_MSG_ID:

    default:
        if (ndo->ndo_vflag <= 1)
            print_unknown_data(ndo, tptr, "\n\t      ", tlv_tlen);
        break;
    }
    return(tlv_len+4); /* Type & Length fields not included */

trunc:
    ND_PRINT("\n\t\t packet exceeded snapshot");
    return 0;

badtlv:
    ND_PRINT("\n\t\t TLV contents go past end of TLV");
    return(tlv_len+4); /* Type & Length fields not included */
}
Exemple #7
0
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
}
Exemple #8
0
/**
 * 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;
}
Exemple #9
0
/*
 * 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;
}
Exemple #11
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] "));
}
Exemple #12
0
/*
 * 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]");
}
Exemple #13
0
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]");
}
Exemple #14
0
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 {
Exemple #15
0
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]");
}
Exemple #16
0
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;
	}
}
Exemple #17
0
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("]");
        }
Exemple #18
0
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;
}
Exemple #19
0
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
}
Exemple #20
0
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)");
		}
	}
Exemple #21
0
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;
}
Exemple #22
0
/**
 * dccp_print - show dccp packet
 * @bp - beginning of dccp packet
 * @data2 - beginning of enclosing
 * @len - lenght of ip packet
 */
void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2,
		u_int len)
{
	const struct dccp_hdr *dh;
	const struct ip *ip;
	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;
}
Exemple #23
0
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] ");
}
Exemple #25
0
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] ");
}
Exemple #29
0
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('>');
}
Exemple #30
0
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]");
}