Example #1
0
/*
 * Print EtherTalk/TokenTalk packets (or FDDITalk, or whatever it's called
 * when it runs over FDDI; yes, I've seen FDDI captures with AppleTalk
 * packets in them).
 */
void
atalk_print(netdissect_options *ndo,
            const u_char *bp, u_int length)
{
	const struct atDDP *dp;
	u_short snet;

	ndo->ndo_protocol = "atalk";
        if(!ndo->ndo_eflag)
            ND_PRINT("AT ");

	if (length < ddpSize) {
		ND_PRINT(" [|ddp %u]", length);
		return;
	}
	if (!ND_TTEST_LEN(bp, ddpSize)) {
		ND_PRINT(" [|ddp]");
		return;
	}
	dp = (const struct atDDP *)bp;
	snet = EXTRACT_BE_U_2(dp->srcNet);
	ND_PRINT("%s.%s", ataddr_string(ndo, snet, EXTRACT_U_1(dp->srcNode)),
	       ddpskt_string(ndo, EXTRACT_U_1(dp->srcSkt)));
	ND_PRINT(" > %s.%s: ",
	       ataddr_string(ndo, EXTRACT_BE_U_2(dp->dstNet), EXTRACT_U_1(dp->dstNode)),
	       ddpskt_string(ndo, EXTRACT_U_1(dp->dstSkt)));
	bp += ddpSize;
	length -= ddpSize;
	ddp_print(ndo, bp, length, EXTRACT_U_1(dp->type), snet, EXTRACT_U_1(dp->srcNode), EXTRACT_U_1(dp->srcSkt));
}
Example #2
0
/*
 * Print RRCP requests
 */
void
rrcp_print(netdissect_options *ndo,
	  const u_char *cp,
	  u_int length _U_,
	  const struct lladdr_info *src,
	  const struct lladdr_info *dst)
{
	uint8_t rrcp_proto;
	uint8_t rrcp_opcode;

	ndo->ndo_protocol = "rrcp";
	ND_TCHECK_1(cp + RRCP_PROTO_OFFSET);
	rrcp_proto = EXTRACT_U_1(cp + RRCP_PROTO_OFFSET);
	ND_TCHECK_1(cp + RRCP_OPCODE_ISREPLY_OFFSET);
	rrcp_opcode = EXTRACT_U_1((cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK;
	if (src != NULL && dst != NULL) {
		ND_PRINT("%s > %s, ",
			(src->addr_string)(ndo, src->addr),
			(dst->addr_string)(ndo, dst->addr));
	}
	ND_PRINT("%s %s",
		tok2str(proto_values,"RRCP-0x%02x",rrcp_proto),
		((EXTRACT_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query");
	if (rrcp_proto==1){
    	    ND_PRINT(": %s",
		     tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode));
	}
	if (rrcp_opcode==1 || rrcp_opcode==2){
	    ND_TCHECK_6(cp + RRCP_REG_ADDR_OFFSET);
    	    ND_PRINT(" addr=0x%04x, data=0x%08x",
		     EXTRACT_LE_U_2(cp + RRCP_REG_ADDR_OFFSET),
		     EXTRACT_LE_U_4(cp + RRCP_REG_DATA_OFFSET));
	}
	if (rrcp_proto==1){
	    ND_TCHECK_2(cp + RRCP_AUTHKEY_OFFSET);
    	    ND_PRINT(", auth=0x%04x",
		  EXTRACT_BE_U_2(cp + RRCP_AUTHKEY_OFFSET));
	}
	if (rrcp_proto==1 && rrcp_opcode==0 &&
	     ((EXTRACT_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){
	    ND_TCHECK_4(cp + RRCP_VENDOR_ID_OFFSET);
	    ND_PRINT(" downlink_port=%u, uplink_port=%u, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ",
		     EXTRACT_U_1(cp + RRCP_DOWNLINK_PORT_OFFSET),
		     EXTRACT_U_1(cp + RRCP_UPLINK_PORT_OFFSET),
		     etheraddr_string(ndo, cp + RRCP_UPLINK_MAC_OFFSET),
		     EXTRACT_BE_U_4(cp + RRCP_VENDOR_ID_OFFSET),
		     EXTRACT_BE_U_2(cp + RRCP_CHIP_ID_OFFSET));
	}else if (rrcp_opcode==1 || rrcp_opcode==2 || rrcp_proto==2){
	    ND_TCHECK_4(cp + RRCP_COOKIE2_OFFSET);
	    ND_PRINT(", cookie=0x%08x%08x ",
		    EXTRACT_BE_U_4(cp + RRCP_COOKIE2_OFFSET),
		    EXTRACT_BE_U_4(cp + RRCP_COOKIE1_OFFSET));
	}
	return;

trunc:
	nd_print_trunc(ndo);
}
Example #3
0
/* IP6CP config options */
static u_int
print_ip6cp_config_options(netdissect_options *ndo,
                           const u_char *p, u_int length)
{
	u_int opt, len;

	if (length < 2)
		return 0;
	ND_TCHECK_2(p);
	opt = EXTRACT_U_1(p);
	len = EXTRACT_U_1(p + 1);
	if (length < len)
		return 0;
	if (len < 2) {
		ND_PRINT("\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
		       tok2str(ip6cpopt_values,"unknown",opt),
		       opt,
		       len);
		return 0;
	}

	ND_PRINT("\n\t  %s Option (0x%02x), length %u",
	       tok2str(ip6cpopt_values,"unknown",opt),
	       opt,
	       len);

	switch (opt) {
	case IP6CP_IFID:
		if (len != 10) {
			ND_PRINT(" (length bogus, should be = 10)");
			return len;
		}
		ND_TCHECK_8(p + 2);
		ND_PRINT(": %04x:%04x:%04x:%04x",
		       EXTRACT_BE_U_2(p + 2),
		       EXTRACT_BE_U_2(p + 4),
		       EXTRACT_BE_U_2(p + 6),
		       EXTRACT_BE_U_2(p + 8));
		break;
	default:
		/*
		 * Unknown option; dump it as raw bytes now if we're
		 * not going to do so below.
		 */
		if (ndo->ndo_vflag < 2)
			print_unknown_data(ndo, p + 2, "\n\t    ", len - 2);
		break;
	}
	if (ndo->ndo_vflag > 1)
		print_unknown_data(ndo, p + 2, "\n\t    ", len - 2); /* exclude TLV header */

	return len;

trunc:
	ND_PRINT("[|ip6cp]");
	return 0;
}
Example #4
0
/*
 * Print NTP control message requests and responses
 */
static void
ntp_control_print(netdissect_options *ndo,
		  const struct ntp_control_data *cd, u_int length)
{
	uint8_t control, R, E, M, opcode;
	uint16_t sequence, status, assoc, offset, count;

	if (length < NTP_CTRLMSG_MINLEN)
		goto invalid;

	ND_TCHECK_1(cd->control);
	control = EXTRACT_U_1(cd->control);
	R = (control & 0x80) != 0;
	E = (control & 0x40) != 0;
	M = (control & 0x20) != 0;
	opcode = control & 0x1f;
	ND_PRINT(", %s, %s, %s, OpCode=%u\n",
		  R ? "Response" : "Request", E ? "Error" : "OK",
		  M ? "More" : "Last", opcode);

	ND_TCHECK_2(cd->sequence);
	sequence = EXTRACT_BE_U_2(cd->sequence);
	ND_PRINT("\tSequence=%hu", sequence);

	ND_TCHECK_2(cd->status);
	status = EXTRACT_BE_U_2(cd->status);
	ND_PRINT(", Status=%#hx", status);

	ND_TCHECK_2(cd->assoc);
	assoc = EXTRACT_BE_U_2(cd->assoc);
	ND_PRINT(", Assoc.=%hu", assoc);

	ND_TCHECK_2(cd->offset);
	offset = EXTRACT_BE_U_2(cd->offset);
	ND_PRINT(", Offset=%hu", offset);

	ND_TCHECK_2(cd->count);
	count = EXTRACT_BE_U_2(cd->count);
	ND_PRINT(", Count=%hu", count);

	if (NTP_CTRLMSG_MINLEN + count > length)
		goto invalid;
	if (count != 0) {
		ND_TCHECK_LEN(cd->data, count);
		ND_PRINT("\n\tTO-BE-DONE: data not interpreted");
	}
	return;

invalid:
	nd_print_invalid(ndo);
	ND_TCHECK_LEN(cd, length);
	return;

trunc:
	nd_print_trunc(ndo);
}
Example #5
0
void
igrp_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
	const struct igrphdr *hdr;
	const u_char *cp;
	u_int nint, nsys, next;

	hdr = (const struct igrphdr *)bp;
	cp = (const u_char *)(hdr + 1);
	ND_PRINT("igrp:");

	/* Header */
	ND_TCHECK_SIZE(hdr);
	nint = EXTRACT_BE_U_2(hdr->ig_ni);
	nsys = EXTRACT_BE_U_2(hdr->ig_ns);
	next = EXTRACT_BE_U_2(hdr->ig_nx);

	ND_PRINT(" %s V%u edit=%u AS=%u (%u/%u/%u)",
	    tok2str(op2str, "op-#%u", IGRP_OP(EXTRACT_U_1(hdr->ig_vop))),
	    IGRP_V(EXTRACT_U_1(hdr->ig_vop)),
	    EXTRACT_U_1(hdr->ig_ed),
	    EXTRACT_BE_U_2(hdr->ig_as),
	    nint,
	    nsys,
	    next);

	length -= sizeof(*hdr);
	while (length >= IGRP_RTE_SIZE) {
		if (nint > 0) {
			ND_TCHECK_LEN(cp, IGRP_RTE_SIZE);
			igrp_entry_print(ndo, (const struct igrprte *)cp, 1, 0);
			--nint;
		} else if (nsys > 0) {
			ND_TCHECK_LEN(cp, IGRP_RTE_SIZE);
			igrp_entry_print(ndo, (const struct igrprte *)cp, 0, 0);
			--nsys;
		} else if (next > 0) {
			ND_TCHECK_LEN(cp, IGRP_RTE_SIZE);
			igrp_entry_print(ndo, (const struct igrprte *)cp, 0, 1);
			--next;
		} else {
			ND_PRINT(" [extra bytes %u]", length);
			break;
		}
		cp += IGRP_RTE_SIZE;
		length -= IGRP_RTE_SIZE;
	}
	if (nint == 0 && nsys == 0 && next == 0)
		return;
trunc:
	ND_PRINT(" [|igrp]");
}
Example #6
0
void
gre_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
	u_int len = length, vers;

	ND_TCHECK_2(bp);
	if (len < 2)
		goto trunc;
	vers = EXTRACT_BE_U_2(bp) & GRE_VERS_MASK;
        ND_PRINT("GREv%u",vers);

        switch(vers) {
        case 0:
            gre_print_0(ndo, bp, len);
            break;
        case 1:
            gre_print_1(ndo, bp, len);
            break;
	default:
            ND_PRINT(" ERROR: unknown-version");
            break;
        }
        return;

trunc:
	ND_PRINT("%s", tstr);
	return;
}
Example #7
0
static int
gre_sre_asn_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
                  const u_char *bp, u_int len)
{
	const u_char *up = bp;

	if (sreoff & 1) {
		ND_PRINT(", badoffset=%u", sreoff);
		return (1);
	}
	if (srelen & 1) {
		ND_PRINT(", badlength=%u", srelen);
		return (1);
	}
	if (sreoff >= srelen) {
		ND_PRINT(", badoff/len=%u/%u", sreoff, srelen);
		return (1);
	}

	while (srelen != 0) {
		if (!ND_TTEST_2(bp))
			return (0);
		if (len < 2)
			return (0);

		ND_PRINT(" %s%x",
		    ((bp - up) == sreoff) ? "*" : "",
		    EXTRACT_BE_U_2(bp));

		bp += 2;
		len -= 2;
		srelen -= 2;
	}
	return (1);
}
Example #8
0
/*
 * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
 * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
 * with the CAN ID being in host byte order.
 *
 * When reading a DLT_LINUX_SLL capture file, we need to check for those
 * packets and convert the CAN ID from the byte order of the host that
 * wrote the file to this host's byte order.
 */
static void
swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
{
	u_int caplen = hdr->caplen;
	u_int length = hdr->len;
	struct sll_header *shdr = (struct sll_header *)buf;
	uint16_t protocol;
	pcap_can_socketcan_hdr *chdr;

	if (caplen < (u_int) sizeof(struct sll_header) ||
	    length < (u_int) sizeof(struct sll_header)) {
		/* Not enough data to have the protocol field */
		return;
	}

	protocol = EXTRACT_BE_U_2(&shdr->sll_protocol);
	if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
		return;

	/*
	 * SocketCAN packet; fix up the packet's header.
	 */
	chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
	if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
	    length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
		/* Not enough data to have the CAN ID */
		return;
	}
	chdr->can_id = SWAPLONG(chdr->can_id);
}
Example #9
0
static void
igrp_entry_print(netdissect_options *ndo, const struct igrprte *igr,
    int is_interior, int is_exterior)
{
	u_int delay, bandwidth;
	u_int metric, mtu;

	if (is_interior)
		ND_PRINT(" *.%u.%u.%u", igr->igr_net[0],
		    igr->igr_net[1], igr->igr_net[2]);
	else if (is_exterior)
		ND_PRINT(" X%u.%u.%u.0", igr->igr_net[0],
		    igr->igr_net[1], igr->igr_net[2]);
	else
		ND_PRINT(" %u.%u.%u.0", igr->igr_net[0],
		    igr->igr_net[1], igr->igr_net[2]);

	delay = EXTRACT_BE_U_3(igr->igr_dly);
	bandwidth = EXTRACT_BE_U_3(igr->igr_bw);
	metric = bandwidth + delay;
	if (metric > 0xffffff)
		metric = 0xffffff;
	mtu = EXTRACT_BE_U_2(igr->igr_mtu);

	ND_PRINT(" d=%u b=%u r=%u l=%u M=%u mtu=%u in %u hops",
	    10 * delay, bandwidth == 0 ? 0 : 10000000 / bandwidth,
	    EXTRACT_U_1(igr->igr_rel), EXTRACT_U_1(igr->igr_ld), metric,
	    mtu, EXTRACT_U_1(igr->igr_hct));
}
Example #10
0
static void
print_attr_string(netdissect_options *ndo,
                  const u_char *data, u_int length, u_short attr_code)
{
   u_int i;

   ND_TCHECK_LEN(data, length);

   switch(attr_code)
   {
      case TUNNEL_PASS:
           if (length < 3)
              goto trunc;
           if (EXTRACT_U_1(data) && (EXTRACT_U_1(data) <= 0x1F))
              ND_PRINT("Tag[%u] ", EXTRACT_U_1(data));
           else
              ND_PRINT("Tag[Unused] ");
           data++;
           length--;
           ND_PRINT("Salt %u ", EXTRACT_BE_U_2(data));
           data+=2;
           length-=2;
        break;
      case TUNNEL_CLIENT_END:
      case TUNNEL_SERVER_END:
      case TUNNEL_PRIV_GROUP:
      case TUNNEL_ASSIGN_ID:
      case TUNNEL_CLIENT_AUTH:
      case TUNNEL_SERVER_AUTH:
           if (EXTRACT_U_1(data) <= 0x1F)
           {
              if (length < 1)
                 goto trunc;
              if (EXTRACT_U_1(data))
                ND_PRINT("Tag[%u] ", EXTRACT_U_1(data));
              else
                ND_PRINT("Tag[Unused] ");
              data++;
              length--;
           }
        break;
      case EGRESS_VLAN_NAME:
           if (length < 1)
              goto trunc;
           ND_PRINT("%s (0x%02x) ",
                  tok2str(rfc4675_tagged,"Unknown tag",EXTRACT_U_1(data)),
                  EXTRACT_U_1(data));
           data++;
           length--;
        break;
   }

   for (i=0; i < length && EXTRACT_U_1(data); i++, data++)
       ND_PRINT("%c", ND_ISPRINT(EXTRACT_U_1(data)) ? EXTRACT_U_1(data) : '.');

   return;

   trunc:
      nd_print_trunc(ndo);
}
Example #11
0
void
timed_print(netdissect_options *ndo,
            const u_char *bp)
{
	const struct tsp *tsp = (const struct tsp *)bp;
	uint8_t tsp_type;
	int sec, usec;

	ndo->ndo_protocol = "timed";
	ND_TCHECK_1(tsp->tsp_type);
	tsp_type = EXTRACT_U_1(tsp->tsp_type);
	if (tsp_type < TSPTYPENUMBER)
		ND_PRINT("TSP_%s", tsptype[tsp_type]);
	else
		ND_PRINT("(tsp_type %#x)", tsp_type);

	ND_TCHECK_1(tsp->tsp_vers);
	ND_PRINT(" vers %u", EXTRACT_U_1(tsp->tsp_vers));

	ND_TCHECK_2(tsp->tsp_seq);
	ND_PRINT(" seq %u", EXTRACT_BE_U_2(tsp->tsp_seq));

	switch (tsp_type) {
	case TSP_LOOP:
		ND_TCHECK_1(tsp->tsp_hopcnt);
		ND_PRINT(" hopcnt %u", EXTRACT_U_1(tsp->tsp_hopcnt));
		break;
	case TSP_SETTIME:
	case TSP_ADJTIME:
	case TSP_SETDATE:
	case TSP_SETDATEREQ:
		ND_TCHECK_8(&tsp->tsp_time);
		sec = EXTRACT_BE_S_4(tsp->tsp_time.tv_sec);
		usec = EXTRACT_BE_S_4(tsp->tsp_time.tv_usec);
		/* XXX The comparison below is always false? */
		if (usec < 0)
			/* invalid, skip the rest of the packet */
			return;
		ND_PRINT(" time ");
		if (sec < 0 && usec != 0) {
			sec++;
			if (sec == 0)
				ND_PRINT("-");
			usec = 1000000 - usec;
		}
		ND_PRINT("%d.%06d", sec, usec);
		break;
	}
	ND_PRINT(" name ");
	if (nd_printzp(ndo, tsp->tsp_name, sizeof(tsp->tsp_name),
		       ndo->ndo_snapend))
		goto trunc;
	return;

trunc:
	nd_print_trunc(ndo);
}
Example #12
0
static int
stp_print_config_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu,
                      u_int length)
{
    uint8_t bpdu_flags;

    ND_TCHECK_1(stp_bpdu->flags);
    bpdu_flags = EXTRACT_U_1(stp_bpdu->flags);
    ND_PRINT(", Flags [%s]",
           bittok2str(stp_bpdu_flag_values, "none", bpdu_flags));

    ND_TCHECK_2(stp_bpdu->port_id);
    ND_PRINT(", bridge-id %s.%04x, length %u",
           stp_print_bridge_id((const u_char *)&stp_bpdu->bridge_id),
           EXTRACT_BE_U_2(stp_bpdu->port_id), length);

    /* in non-verbose mode just print the bridge-id */
    if (!ndo->ndo_vflag) {
        return 1;
    }

    ND_TCHECK_2(stp_bpdu->forward_delay);
    ND_PRINT("\n\tmessage-age %.2fs, max-age %.2fs"
           ", hello-time %.2fs, forwarding-delay %.2fs",
           (float) EXTRACT_BE_U_2(stp_bpdu->message_age) / STP_TIME_BASE,
           (float) EXTRACT_BE_U_2(stp_bpdu->max_age) / STP_TIME_BASE,
           (float) EXTRACT_BE_U_2(stp_bpdu->hello_time) / STP_TIME_BASE,
           (float) EXTRACT_BE_U_2(stp_bpdu->forward_delay) / STP_TIME_BASE);

    ND_PRINT("\n\troot-id %s, root-pathcost %u",
           stp_print_bridge_id((const u_char *)&stp_bpdu->root_id),
           EXTRACT_BE_U_4(stp_bpdu->root_path_cost));

    /* Port role is only valid for 802.1w */
    if (EXTRACT_U_1(stp_bpdu->protocol_version) == STP_PROTO_RAPID) {
        ND_PRINT(", port-role %s",
               tok2str(rstp_obj_port_role_values, "Unknown",
                       RSTP_EXTRACT_PORT_ROLE(bpdu_flags)));
    }
    return 1;

trunc:
    return 0;
}
Example #13
0
/* Print a single OpenFlow message. */
static const u_char *
of_header_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
{
	uint8_t version, type;
	uint16_t length;
	uint32_t xid;

	if (ep < cp + OF_HEADER_LEN)
		goto invalid;
	/* version */
	ND_TCHECK_1(cp);
	version = EXTRACT_U_1(cp);
	cp += 1;
	/* type */
	ND_TCHECK_1(cp);
	type = EXTRACT_U_1(cp);
	cp += 1;
	/* length */
	ND_TCHECK_2(cp);
	length = EXTRACT_BE_U_2(cp);
	cp += 2;
	/* xid */
	ND_TCHECK_4(cp);
	xid = EXTRACT_BE_U_4(cp);
	cp += 4;
	/* Message length includes the header length and a message always includes
	 * the basic header. A message length underrun fails decoding of the rest of
	 * the current packet. At the same time, try decoding as much of the current
	 * message as possible even when it does not end within the current TCP
	 * segment. */
	if (length < OF_HEADER_LEN) {
		of_header_print(ndo, version, type, length, xid);
		goto invalid;
	}
	/* Decode known protocol versions further without printing the header (the
	 * type decoding is version-specific. */
	switch (version) {
	case OF_VER_1_0:
		return of10_header_body_print(ndo, cp, ep, type, length, xid);
	default:
		of_header_print(ndo, version, type, length, xid);
		ND_TCHECK_LEN(cp, length - OF_HEADER_LEN);
		return cp + length - OF_HEADER_LEN; /* done with current message */
	}

invalid: /* fail current packet */
	ND_PRINT("%s", istr);
	ND_TCHECK_LEN(cp, ep - cp);
	return ep;
trunc:
	ND_PRINT("%s", tstr);
	return ep;
}
Example #14
0
void
radius_print(netdissect_options *ndo,
             const u_char *dat, u_int length)
{
   const struct radius_hdr *rad;
   u_int len, auth_idx;

   ndo->ndo_protocol = "radius";
   ND_TCHECK_LEN(dat, MIN_RADIUS_LEN);
   rad = (const struct radius_hdr *)dat;
   len = EXTRACT_BE_U_2(rad->len);

   if (len < MIN_RADIUS_LEN)
   {
	  nd_print_trunc(ndo);
	  return;
   }

   if (len > length)
	  len = length;

   if (ndo->ndo_vflag < 1) {
       ND_PRINT("RADIUS, %s (%u), id: 0x%02x length: %u",
              tok2str(radius_command_values,"Unknown Command",EXTRACT_U_1(rad->code)),
              EXTRACT_U_1(rad->code),
              EXTRACT_U_1(rad->id),
              len);
       return;
   }
   else {
       ND_PRINT("RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
              len,
              tok2str(radius_command_values,"Unknown Command",EXTRACT_U_1(rad->code)),
              EXTRACT_U_1(rad->code),
              EXTRACT_U_1(rad->id));

       for(auth_idx=0; auth_idx < 16; auth_idx++)
            ND_PRINT("%02x", rad->auth[auth_idx]);
   }

   if (len > MIN_RADIUS_LEN)
      radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
   return;

trunc:
   nd_print_trunc(ndo);
}
Example #15
0
static int
lwres_printnamelen(netdissect_options *ndo,
                   const u_char *p)
{
	uint16_t l;
	int advance;

	if (p + 2 > ndo->ndo_snapend)
		goto trunc;
	l = EXTRACT_BE_U_2(p);
	advance = lwres_printname(ndo, l, p + 2);
	if (advance < 0)
		goto trunc;
	return 2 + advance;

  trunc:
	return -1;
}
Example #16
0
static void
ahcp1_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
{
	uint8_t type, mbz;
	uint16_t body_len;

	if (cp + AHCP1_BODY_MIN_LEN > ep)
		goto invalid;
	/* Type */
	ND_TCHECK_1(cp);
	type = EXTRACT_U_1(cp);
	cp += 1;
	/* MBZ */
	ND_TCHECK_1(cp);
	mbz = EXTRACT_U_1(cp);
	cp += 1;
	/* Length */
	ND_TCHECK_2(cp);
	body_len = EXTRACT_BE_U_2(cp);
	cp += 2;

	if (ndo->ndo_vflag) {
		ND_PRINT("\n\t%s", tok2str(ahcp1_msg_str, "Unknown-%u", type));
		if (mbz != 0)
			ND_PRINT(", MBZ %u", mbz);
		ND_PRINT(", Length %u", body_len);
	}
	if (cp + body_len > ep)
		goto invalid;

	/* Options */
	if (ndo->ndo_vflag >= 2)
		ahcp1_options_print(ndo, cp, cp + body_len); /* not ep (ignore extra data) */
	else
		ND_TCHECK_LEN(cp, body_len);
	return;

invalid:
	ND_PRINT("%s", istr);
	ND_TCHECK_LEN(cp, ep - cp);
	return;
trunc:
	nd_print_trunc(ndo);
}
Example #17
0
static int
lwres_printaddr(netdissect_options *ndo,
                const u_char *p0)
{
	const u_char *p;
	const lwres_addr_t *ap;
	uint16_t l;
	int i;

	p = p0;
	ap = (const lwres_addr_t *)p;
	ND_TCHECK_2(ap->length);
	l = EXTRACT_BE_U_2(ap->length);
	p += LWRES_ADDR_LEN;
	ND_TCHECK_LEN(p, l);

	switch (EXTRACT_BE_U_4(ap->family)) {
	case 1:	/* IPv4 */
		if (l < 4)
			return -1;
		ND_PRINT(" %s", ipaddr_string(ndo, p));
		p += sizeof(nd_ipv4);
		break;
	case 2:	/* IPv6 */
		if (l < 16)
			return -1;
		ND_PRINT(" %s", ip6addr_string(ndo, p));
		p += sizeof(nd_ipv6);
		break;
	default:
		ND_PRINT(" %u/", EXTRACT_BE_U_4(ap->family));
		for (i = 0; i < l; i++) {
			ND_PRINT("%02x", EXTRACT_U_1(p));
			p++;
		}
	}

	return p - p0;

  trunc:
	return -1;
}
Example #18
0
static void
geneve_opts_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
    const char *sep = "";

    while (len > 0) {
        uint16_t opt_class;
        uint8_t opt_type;
        uint8_t opt_len;

        ND_PRINT("%s", sep);
        sep = ", ";

        opt_class = EXTRACT_BE_U_2(bp);
        opt_type = EXTRACT_U_1(bp + 2);
        opt_len = 4 + ((EXTRACT_U_1(bp + 3) & OPT_LEN_MASK) * 4);

        ND_PRINT("class %s (0x%x) type 0x%x%s len %u",
                  format_opt_class(opt_class), opt_class, opt_type,
                  opt_type & OPT_TYPE_CRITICAL ? "(C)" : "", opt_len);

        if (opt_len > len) {
            ND_PRINT(" [bad length]");
            return;
        }

        if (ndo->ndo_vflag > 1 && opt_len > 4) {
            const uint32_t *data = (const uint32_t *)(bp + 4);
            int i;

            ND_PRINT(" data");

            for (i = 4; i < opt_len; i += 4) {
                ND_PRINT(" %08x", EXTRACT_BE_U_4(data));
                data++;
            }
        }

        bp += opt_len;
        len -= opt_len;
    }
}
Example #19
0
static void
handle_mlppp(netdissect_options *ndo,
             const u_char *p, u_int length)
{
    if (!ndo->ndo_eflag)
        ND_PRINT("MLPPP, ");

    if (length < 2) {
        ND_PRINT("[|mlppp]");
        return;
    }
    if (!ND_TTEST_2(p)) {
        ND_PRINT("[|mlppp]");
        return;
    }

    ND_PRINT("seq 0x%03x, Flags [%s], length %u",
           (EXTRACT_BE_U_2(p))&0x0fff, /* only support 12-Bit sequence space for now */
           bittok2str(ppp_ml_flag_values, "none", EXTRACT_U_1(p) & 0xc0),
           length);
}
Example #20
0
static int
lwres_printbinlen(netdissect_options *ndo,
                  const u_char *p0)
{
	const u_char *p;
	uint16_t l;
	int i;

	p = p0;
	if (p + 2 > ndo->ndo_snapend)
		goto trunc;
	l = EXTRACT_BE_U_2(p);
	if (p + 2 + l > ndo->ndo_snapend)
		goto trunc;
	p += 2;
	for (i = 0; i < l; i++) {
		ND_PRINT("%02x", EXTRACT_U_1(p));
		p++;
	}
	return p - p0;

  trunc:
	return -1;
}
Example #21
0
/* XXX should probably pass in the snap header and do checks like arp_print() */
void
aarp_print(netdissect_options *ndo,
           const u_char *bp, u_int length)
{
	const struct aarp *ap;

#define AT(member) ataddr_string(ndo, (ap->member[1]<<8)|ap->member[2],ap->member[3])

	ndo->ndo_protocol = "aarp";
	ND_PRINT("aarp ");
	ap = (const struct aarp *)bp;
	if (!ND_TTEST_SIZE(ap)) {
		/* Just bail if we don't have the whole chunk. */
		nd_print_trunc(ndo);
		return;
	}
	if (length < sizeof(*ap)) {
		ND_PRINT(" [|aarp %u]", length);
		return;
	}
	if (EXTRACT_BE_U_2(ap->htype) == 1 &&
	    EXTRACT_BE_U_2(ap->ptype) == ETHERTYPE_ATALK &&
	    EXTRACT_U_1(ap->halen) == 6 && EXTRACT_U_1(ap->palen) == 4 )
		switch (EXTRACT_BE_U_2(ap->op)) {

		case 1:				/* request */
			ND_PRINT("who-has %s tell %s", AT(pdaddr), AT(psaddr));
			return;

		case 2:				/* response */
			ND_PRINT("reply %s is-at %s", AT(psaddr), etheraddr_string(ndo, ap->hsaddr));
			return;

		case 3:				/* probe (oy!) */
			ND_PRINT("probe %s tell %s", AT(pdaddr), AT(psaddr));
			return;
		}
	ND_PRINT("len %u op %u htype %u ptype %#x halen %u palen %u",
	    length, EXTRACT_BE_U_2(ap->op), EXTRACT_BE_U_2(ap->htype),
	    EXTRACT_BE_U_2(ap->ptype), EXTRACT_U_1(ap->halen), EXTRACT_U_1(ap->palen));
}
Example #22
0
void
msdp_print(netdissect_options *ndo, const u_char *sp, u_int length)
{
	unsigned int type, len;

	ndo->ndo_protocol = "msdp";
	ND_TCHECK_3(sp);
	/* See if we think we're at the beginning of a compound packet */
	type = EXTRACT_U_1(sp);
	len = EXTRACT_BE_U_2(sp + 1);
	if (len > 1500 || len < 3 || type == 0 || type > MSDP_TYPE_MAX)
		goto trunc;	/* not really truncated, but still not decodable */
	ND_PRINT(" msdp:");
	while (length != 0) {
		ND_TCHECK_3(sp);
		type = EXTRACT_U_1(sp);
		len = EXTRACT_BE_U_2(sp + 1);
		if (len > 1400 || ndo->ndo_vflag)
			ND_PRINT(" [len %u]", len);
		if (len < 3)
			goto trunc;
		if (length < len)
			goto trunc;
		sp += 3;
		length -= 3;
		switch (type) {
		case 1:	/* IPv4 Source-Active */
		case 3: /* IPv4 Source-Active Response */
			if (type == 1)
				ND_PRINT(" SA");
			else
				ND_PRINT(" SA-Response");
			ND_TCHECK_1(sp);
			ND_PRINT(" %u entries", EXTRACT_U_1(sp));
			if ((u_int)((EXTRACT_U_1(sp) * 12) + 8) < len) {
				ND_PRINT(" [w/data]");
				if (ndo->ndo_vflag > 1) {
					ND_PRINT(" ");
					ip_print(ndo, sp +
						 EXTRACT_U_1(sp) * 12 + 8 - 3,
					         len - (EXTRACT_U_1(sp) * 12 + 8));
				}
			}
			break;
		case 2:
			ND_PRINT(" SA-Request");
			ND_TCHECK_5(sp);
			ND_PRINT(" for %s", ipaddr_string(ndo, sp + 1));
			break;
		case 4:
			ND_PRINT(" Keepalive");
			if (len != 3)
				ND_PRINT("[len=%u] ", len);
			break;
		case 5:
			ND_PRINT(" Notification");
			break;
		default:
			ND_PRINT(" [type=%u len=%u]", type, len);
			break;
		}
		sp += (len - 3);
		length -= (len - 3);
	}
	return;
trunc:
	nd_print_trunc(ndo);
}
Example #23
0
void
egp_print(netdissect_options *ndo,
          const uint8_t *bp, u_int length)
{
	const struct egp_packet *egp;
	u_int version;
	u_int type;
	u_int code;
	u_int status;

	ndo->ndo_protocol = "egp";
	egp = (const struct egp_packet *)bp;
	if (length < sizeof(*egp) || !ND_TTEST_SIZE(egp)) {
		ND_PRINT("[|egp]");
		return;
	}

	version = EXTRACT_U_1(egp->egp_version);
        if (!ndo->ndo_vflag) {
            ND_PRINT("EGPv%u, AS %u, seq %u, length %u",
                   version,
                   EXTRACT_BE_U_2(egp->egp_as),
                   EXTRACT_BE_U_2(egp->egp_sequence),
                   length);
            return;
        } else
            ND_PRINT("EGPv%u, length %u",
                   version,
                   length);

	if (version != EGP_VERSION) {
		ND_PRINT("[version %u]", version);
		return;
	}

	type = EXTRACT_U_1(egp->egp_type);
	code = EXTRACT_U_1(egp->egp_code);
	status = EXTRACT_U_1(egp->egp_status);

	switch (type) {
	case EGPT_ACQUIRE:
		ND_PRINT(" acquire");
		switch (code) {
		case EGPC_REQUEST:
		case EGPC_CONFIRM:
			ND_PRINT(" %s", egp_acquire_codes[code]);
			switch (status) {
			case EGPS_UNSPEC:
			case EGPS_ACTIVE:
			case EGPS_PASSIVE:
				ND_PRINT(" %s", egp_acquire_status[status]);
				break;

			default:
				ND_PRINT(" [status %u]", status);
				break;
			}
			ND_PRINT(" hello:%u poll:%u",
			       EXTRACT_BE_U_2(egp->egp_hello),
			       EXTRACT_BE_U_2(egp->egp_poll));
			break;

		case EGPC_REFUSE:
		case EGPC_CEASE:
		case EGPC_CEASEACK:
			ND_PRINT(" %s", egp_acquire_codes[code]);
			switch (status ) {
			case EGPS_UNSPEC:
			case EGPS_NORES:
			case EGPS_ADMIN:
			case EGPS_GODOWN:
			case EGPS_PARAM:
			case EGPS_PROTO:
				ND_PRINT(" %s", egp_acquire_status[status]);
				break;

			default:
				ND_PRINT("[status %u]", status);
				break;
			}
			break;

		default:
			ND_PRINT("[code %u]", code);
			break;
		}
		break;

	case EGPT_REACH:
		switch (code) {

		case EGPC_HELLO:
		case EGPC_HEARDU:
			ND_PRINT(" %s", egp_reach_codes[code]);
			if (status <= EGPS_DOWN)
				ND_PRINT(" state:%s", egp_status_updown[status]);
			else
				ND_PRINT(" [status %u]", status);
			break;

		default:
			ND_PRINT("[reach code %u]", code);
			break;
		}
		break;

	case EGPT_POLL:
		ND_PRINT(" poll");
		if (status <= EGPS_DOWN)
			ND_PRINT(" state:%s", egp_status_updown[status]);
		else
			ND_PRINT(" [status %u]", status);
		ND_PRINT(" net:%s", ipaddr_string(ndo, egp->egp_sourcenet));
		break;

	case EGPT_UPDATE:
		ND_PRINT(" update");
		if (status & EGPS_UNSOL) {
			status &= ~EGPS_UNSOL;
			ND_PRINT(" unsolicited");
		}
		if (status <= EGPS_DOWN)
			ND_PRINT(" state:%s", egp_status_updown[status]);
		else
			ND_PRINT(" [status %u]", status);
		ND_PRINT(" %s int %u ext %u",
		       ipaddr_string(ndo, egp->egp_sourcenet),
		       EXTRACT_U_1(egp->egp_intgw),
		       EXTRACT_U_1(egp->egp_extgw));
		if (ndo->ndo_vflag)
			egpnrprint(ndo, egp, length);
		break;

	case EGPT_ERROR:
		ND_PRINT(" error");
		if (status <= EGPS_DOWN)
			ND_PRINT(" state:%s", egp_status_updown[status]);
		else
			ND_PRINT(" [status %u]", status);

		if (EXTRACT_BE_U_2(egp->egp_reason) <= EGPR_UVERSION)
			ND_PRINT(" %s", egp_reasons[EXTRACT_BE_U_2(egp->egp_reason)]);
		else
			ND_PRINT(" [reason %u]", EXTRACT_BE_U_2(egp->egp_reason));
		break;

	default:
		ND_PRINT("[type %u]", type);
		break;
	}
}
Example #24
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]");
}
Example #25
0
static int
stp_print_mstp_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu,
                    u_int length)
{
    const u_char *ptr;
    uint8_t	    bpdu_flags;
    uint16_t	    v3len;
    uint16_t	    len;
    uint16_t	    msti;
    u_int	    offset;

    ptr = (const u_char *)stp_bpdu;
    ND_TCHECK_1(stp_bpdu->flags);
    bpdu_flags = EXTRACT_U_1(stp_bpdu->flags);
    ND_PRINT(", CIST Flags [%s], length %u",
           bittok2str(stp_bpdu_flag_values, "none", bpdu_flags), length);

    /*
     * in non-verbose mode just print the flags.
     */
    if (!ndo->ndo_vflag) {
        return 1;
    }

    ND_PRINT("\n\tport-role %s, ",
           tok2str(rstp_obj_port_role_values, "Unknown",
                   RSTP_EXTRACT_PORT_ROLE(bpdu_flags)));

    ND_TCHECK_4(stp_bpdu->root_path_cost);
    ND_PRINT("CIST root-id %s, CIST ext-pathcost %u",
           stp_print_bridge_id((const u_char *)&stp_bpdu->root_id),
           EXTRACT_BE_U_4(stp_bpdu->root_path_cost));

    ND_TCHECK_SIZE(&stp_bpdu->bridge_id);
    ND_PRINT("\n\tCIST regional-root-id %s, ",
           stp_print_bridge_id((const u_char *)&stp_bpdu->bridge_id));

    ND_TCHECK_2(stp_bpdu->port_id);
    ND_PRINT("CIST port-id %04x,", EXTRACT_BE_U_2(stp_bpdu->port_id));

    ND_TCHECK_2(stp_bpdu->forward_delay);
    ND_PRINT("\n\tmessage-age %.2fs, max-age %.2fs"
           ", hello-time %.2fs, forwarding-delay %.2fs",
           (float) EXTRACT_BE_U_2(stp_bpdu->message_age) / STP_TIME_BASE,
           (float) EXTRACT_BE_U_2(stp_bpdu->max_age) / STP_TIME_BASE,
           (float) EXTRACT_BE_U_2(stp_bpdu->hello_time) / STP_TIME_BASE,
           (float) EXTRACT_BE_U_2(stp_bpdu->forward_delay) / STP_TIME_BASE);

    ND_TCHECK_2(ptr + MST_BPDU_VER3_LEN_OFFSET);
    ND_PRINT("\n\tv3len %u, ", EXTRACT_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET));
    ND_TCHECK_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 12);
    ND_PRINT("MCID Name ");
    if (fn_printzp(ndo, ptr + MST_BPDU_CONFIG_NAME_OFFSET, 32, ndo->ndo_snapend))
	goto trunc;
    ND_PRINT(", rev %u,"
            "\n\t\tdigest %08x%08x%08x%08x, ",
	          EXTRACT_BE_U_2(ptr + MST_BPDU_CONFIG_NAME_OFFSET + 32),
	          EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET),
	          EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 4),
	          EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 8),
	          EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 12));

    ND_TCHECK_4(ptr + MST_BPDU_CIST_INT_PATH_COST_OFFSET);
    ND_PRINT("CIST int-root-pathcost %u,",
            EXTRACT_BE_U_4(ptr + MST_BPDU_CIST_INT_PATH_COST_OFFSET));

    ND_TCHECK_BRIDGE_ID(ptr + MST_BPDU_CIST_BRIDGE_ID_OFFSET);
    ND_PRINT("\n\tCIST bridge-id %s, ",
           stp_print_bridge_id(ptr + MST_BPDU_CIST_BRIDGE_ID_OFFSET));

    ND_TCHECK_1(ptr + MST_BPDU_CIST_REMAIN_HOPS_OFFSET);
    ND_PRINT("CIST remaining-hops %u", EXTRACT_U_1(ptr + MST_BPDU_CIST_REMAIN_HOPS_OFFSET));

    /* Dump all MSTI's */
    ND_TCHECK_2(ptr + MST_BPDU_VER3_LEN_OFFSET);
    v3len = EXTRACT_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET);
    if (v3len > MST_BPDU_CONFIG_INFO_LENGTH) {
        len = v3len - MST_BPDU_CONFIG_INFO_LENGTH;
        offset = MST_BPDU_MSTI_OFFSET;
        while (len >= MST_BPDU_MSTI_LENGTH) {
            ND_TCHECK_LEN(ptr + offset, MST_BPDU_MSTI_LENGTH);

            msti = EXTRACT_BE_U_2(ptr + offset + MST_BPDU_MSTI_ROOT_PRIO_OFFSET);
            msti = msti & 0x0FFF;

            ND_PRINT("\n\tMSTI %u, Flags [%s], port-role %s",
                   msti, bittok2str(stp_bpdu_flag_values, "none", EXTRACT_U_1(ptr + offset)),
                   tok2str(rstp_obj_port_role_values, "Unknown",
                           RSTP_EXTRACT_PORT_ROLE(EXTRACT_U_1(ptr + offset))));
            ND_PRINT("\n\t\tMSTI regional-root-id %s, pathcost %u",
                   stp_print_bridge_id(ptr + offset +
                                       MST_BPDU_MSTI_ROOT_PRIO_OFFSET),
                   EXTRACT_BE_U_4(ptr + offset + MST_BPDU_MSTI_ROOT_PATH_COST_OFFSET));
            ND_PRINT("\n\t\tMSTI bridge-prio %u, port-prio %u, hops %u",
                   EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_BRIDGE_PRIO_OFFSET) >> 4,
                   EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_PORT_PRIO_OFFSET) >> 4,
                   EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_REMAIN_HOPS_OFFSET));

            len -= MST_BPDU_MSTI_LENGTH;
            offset += MST_BPDU_MSTI_LENGTH;
        }
    }
Example #26
0
static int
ldp_pdu_print(netdissect_options *ndo,
              const u_char *pptr)
{
    const struct ldp_common_header *ldp_com_header;
    const struct ldp_msg_header *ldp_msg_header;
    const u_char *tptr,*msg_tptr;
    u_short tlen;
    u_short pdu_len,msg_len,msg_type,msg_tlen;
    int hexdump,processed;

    ldp_com_header = (const struct ldp_common_header *)pptr;
    ND_TCHECK_SIZE(ldp_com_header);

    /*
     * Sanity checking of the header.
     */
    if (EXTRACT_BE_U_2(ldp_com_header->version) != LDP_VERSION) {
	ND_PRINT("%sLDP version %u packet not supported",
               (ndo->ndo_vflag < 1) ? "" : "\n\t",
               EXTRACT_BE_U_2(ldp_com_header->version));
	return 0;
    }

    pdu_len = EXTRACT_BE_U_2(ldp_com_header->pdu_length);
    if (pdu_len < sizeof(struct ldp_common_header)-4) {
        /* length too short */
        ND_PRINT("%sLDP, pdu-length: %u (too short, < %u)",
               (ndo->ndo_vflag < 1) ? "" : "\n\t",
               pdu_len,
               (u_int)(sizeof(struct ldp_common_header)-4));
        return 0;
    }

    /* print the LSR-ID, label-space & length */
    ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
           (ndo->ndo_vflag < 1) ? "" : "\n\t",
           ipaddr_string(ndo, &ldp_com_header->lsr_id),
           EXTRACT_BE_U_2(ldp_com_header->label_space),
           pdu_len);

    /* bail out if non-verbose */
    if (ndo->ndo_vflag < 1)
        return 0;

    /* ok they seem to want to know everything - lets fully decode it */
    tptr = pptr + sizeof(struct ldp_common_header);
    tlen = pdu_len - (sizeof(struct ldp_common_header)-4);	/* Type & Length fields not included */

    while(tlen>0) {
        /* did we capture enough for fully decoding the msg header ? */
        ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header));

        ldp_msg_header = (const struct ldp_msg_header *)tptr;
        msg_len=EXTRACT_BE_U_2(ldp_msg_header->length);
        msg_type=LDP_MASK_MSG_TYPE(EXTRACT_BE_U_2(ldp_msg_header->type));

        if (msg_len < sizeof(struct ldp_msg_header)-4) {
            /* length too short */
            /* FIXME vendor private / experimental check */
            ND_PRINT("\n\t  %s Message (0x%04x), length: %u (too short, < %u)",
                   tok2str(ldp_msg_values,
                           "Unknown",
                           msg_type),
                   msg_type,
                   msg_len,
                   (u_int)(sizeof(struct ldp_msg_header)-4));
            return 0;
        }

        /* FIXME vendor private / experimental check */
        ND_PRINT("\n\t  %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
               tok2str(ldp_msg_values,
                       "Unknown",
                       msg_type),
               msg_type,
               msg_len,
               EXTRACT_BE_U_4(ldp_msg_header->id),
               LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore");

        msg_tptr=tptr+sizeof(struct ldp_msg_header);
        msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */

        /* did we capture enough for fully decoding the message ? */
        ND_TCHECK_LEN(tptr, msg_len);
        hexdump=FALSE;

        switch(msg_type) {

        case LDP_MSG_NOTIF:
        case LDP_MSG_HELLO:
        case LDP_MSG_INIT:
        case LDP_MSG_KEEPALIVE:
        case LDP_MSG_ADDRESS:
        case LDP_MSG_LABEL_MAPPING:
        case LDP_MSG_ADDRESS_WITHDRAW:
        case LDP_MSG_LABEL_WITHDRAW:
            while(msg_tlen >= 4) {
                processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen);
                if (processed == 0)
                    break;
                msg_tlen-=processed;
                msg_tptr+=processed;
            }
            break;

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

        case LDP_MSG_LABEL_REQUEST:
        case LDP_MSG_LABEL_RELEASE:
        case LDP_MSG_LABEL_ABORT_REQUEST:

        default:
            if (ndo->ndo_vflag <= 1)
                print_unknown_data(ndo, msg_tptr, "\n\t  ", msg_tlen);
            break;
        }
        /* do we want to see an additionally hexdump ? */
        if (ndo->ndo_vflag > 1 || hexdump==TRUE)
            print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t  ",
                               msg_len);

        tptr += msg_len+4;
        tlen -= msg_len+4;
    }
    return pdu_len+4;
trunc:
    ND_PRINT("\n\t\t packet exceeded snapshot");
    return 0;
}
Example #27
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 */
}
Example #28
0
u_int
chdlc_print(netdissect_options *ndo, const u_char *p, u_int length)
{
	u_int proto;
	const u_char *bp = p;

	if (length < CHDLC_HDRLEN)
		goto trunc;
	ND_TCHECK_LEN(p, CHDLC_HDRLEN);
	proto = EXTRACT_BE_U_2(p + 2);
	if (ndo->ndo_eflag) {
                ND_PRINT("%s, ethertype %s (0x%04x), length %u: ",
                       tok2str(chdlc_cast_values, "0x%02x", EXTRACT_U_1(p)),
                       tok2str(ethertype_values, "Unknown", proto),
                       proto,
                       length);
	}

	length -= CHDLC_HDRLEN;
	p += CHDLC_HDRLEN;

	switch (proto) {
	case ETHERTYPE_IP:
		ip_print(ndo, p, length);
		break;
	case ETHERTYPE_IPV6:
		ip6_print(ndo, p, length);
		break;
	case CHDLC_TYPE_SLARP:
		chdlc_slarp_print(ndo, p, length);
		break;
#if 0
	case CHDLC_TYPE_CDP:
		chdlc_cdp_print(p, length);
		break;
#endif
        case ETHERTYPE_MPLS:
        case ETHERTYPE_MPLS_MULTI:
                mpls_print(ndo, p, length);
		break;
        case ETHERTYPE_ISO:
                /* is the fudge byte set ? lets verify by spotting ISO headers */
                if (length < 2)
                    goto trunc;
                ND_TCHECK_2(p);
                if (EXTRACT_U_1(p + 1) == NLPID_CLNP ||
                    EXTRACT_U_1(p + 1) == NLPID_ESIS ||
                    EXTRACT_U_1(p + 1) == NLPID_ISIS)
                    isoclns_print(ndo, p + 1, length - 1);
                else
                    isoclns_print(ndo, p, length);
                break;
	default:
                if (!ndo->ndo_eflag)
                        ND_PRINT("unknown CHDLC protocol (0x%04x)", proto);
                break;
	}

	return (CHDLC_HDRLEN);

trunc:
	ND_PRINT("[|chdlc]");
	return ndo->ndo_snapend - bp;
}
Example #29
0
static void
chdlc_slarp_print(netdissect_options *ndo, const u_char *cp, u_int length)
{
	const struct cisco_slarp *slarp;
        u_int sec,min,hrs,days;

	ND_PRINT("SLARP (length: %u), ",length);
	if (length < SLARP_MIN_LEN)
		goto trunc;

	slarp = (const struct cisco_slarp *)cp;
	ND_TCHECK_LEN(slarp, SLARP_MIN_LEN);
	switch (EXTRACT_BE_U_4(slarp->code)) {
	case SLARP_REQUEST:
		ND_PRINT("request");
		/*
		 * At least according to William "Chops" Westfield's
		 * message in
		 *
		 *	http://www.nethelp.no/net/cisco-hdlc.txt
		 *
		 * the address and mask aren't used in requests -
		 * they're just zero.
		 */
		break;
	case SLARP_REPLY:
		ND_PRINT("reply %s/%s",
			ipaddr_string(ndo, slarp->un.addr.addr),
			ipaddr_string(ndo, slarp->un.addr.mask));
		break;
	case SLARP_KEEPALIVE:
		ND_PRINT("keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x",
                       EXTRACT_BE_U_4(slarp->un.keep.myseq),
                       EXTRACT_BE_U_4(slarp->un.keep.yourseq),
                       EXTRACT_BE_U_2(slarp->un.keep.rel));

                if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */
                        cp += SLARP_MIN_LEN;
                        ND_TCHECK_4(cp);
                        sec = EXTRACT_BE_U_4(cp) / 1000;
                        min = sec / 60; sec -= min * 60;
                        hrs = min / 60; min -= hrs * 60;
                        days = hrs / 24; hrs -= days * 24;
                        ND_PRINT(", link uptime=%ud%uh%um%us",days,hrs,min,sec);
                }
		break;
	default:
		ND_PRINT("0x%02x unknown", EXTRACT_BE_U_4(slarp->code));
                if (ndo->ndo_vflag <= 1)
                    print_unknown_data(ndo,cp+4,"\n\t",length-4);
		break;
	}

	if (SLARP_MAX_LEN < length && ndo->ndo_vflag)
		ND_PRINT(", (trailing junk: %u bytes)", length - SLARP_MAX_LEN);
        if (ndo->ndo_vflag > 1)
            print_unknown_data(ndo,cp+4,"\n\t",length-4);
	return;

trunc:
	ND_PRINT("[|slarp]");
}
Example #30
0
int
snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen,
	const struct lladdr_info *src, const struct lladdr_info *dst,
	u_int bridge_pad)
{
	uint32_t orgcode;
	u_short et;
	int ret;

	ND_TCHECK_5(p);
	if (caplen < 5 || length < 5)
		goto trunc;
	orgcode = EXTRACT_BE_U_3(p);
	et = EXTRACT_BE_U_2(p + 3);

	if (ndo->ndo_eflag) {
		/*
		 * Somebody's already printed the MAC addresses, if there
		 * are any, so just print the SNAP header, not the MAC
		 * addresses.
		 */
		ND_PRINT("oui %s (0x%06x), %s %s (0x%04x), length %u: ",
		     tok2str(oui_values, "Unknown", orgcode),
		     orgcode,
		     (orgcode == 0x000000 ? "ethertype" : "pid"),
		     tok2str(oui_to_struct_tok(orgcode), "Unknown", et),
		     et, length - 5);
	}
	p += 5;
	length -= 5;
	caplen -= 5;

	switch (orgcode) {
	case OUI_ENCAP_ETHER:
	case OUI_CISCO_90:
		/*
		 * This is an encapsulated Ethernet packet,
		 * or a packet bridged by some piece of
		 * Cisco hardware; the protocol ID is
		 * an Ethernet protocol type.
		 */
		ret = ethertype_print(ndo, et, p, length, caplen, src, dst);
		if (ret)
			return (ret);
		break;

	case OUI_APPLETALK:
		if (et == ETHERTYPE_ATALK) {
			/*
			 * No, I have no idea why Apple used one
			 * of their own OUIs, rather than
			 * 0x000000, and an Ethernet packet
			 * type, for Appletalk data packets,
			 * but used 0x000000 and an Ethernet
			 * packet type for AARP packets.
			 */
			ret = ethertype_print(ndo, et, p, length, caplen, src, dst);
			if (ret)
				return (ret);
		}
		break;

	case OUI_CISCO:
                switch (et) {
                case PID_CISCO_CDP:
                        cdp_print(ndo, p, length, caplen);
                        return (1);
                case PID_CISCO_DTP:
                        dtp_print(ndo, p, length);
                        return (1);
                case PID_CISCO_UDLD:
                        udld_print(ndo, p, length);
                        return (1);
                case PID_CISCO_VTP:
                        vtp_print(ndo, p, length);
                        return (1);
                case PID_CISCO_PVST:
                case PID_CISCO_VLANBRIDGE:
                        stp_print(ndo, p, length);
                        return (1);
                default:
                        break;
                }
		break;

	case OUI_RFC2684:
		switch (et) {

		case PID_RFC2684_ETH_FCS:
		case PID_RFC2684_ETH_NOFCS:
			/*
			 * XXX - remove the last two bytes for
			 * PID_RFC2684_ETH_FCS?
			 */
			/*
			 * Skip the padding.
			 */
			ND_TCHECK_LEN(p, bridge_pad);
			caplen -= bridge_pad;
			length -= bridge_pad;
			p += bridge_pad;

			/*
			 * What remains is an Ethernet packet.
			 */
			ether_print(ndo, p, length, caplen, NULL, NULL);
			return (1);

		case PID_RFC2684_802_5_FCS:
		case PID_RFC2684_802_5_NOFCS:
			/*
			 * XXX - remove the last two bytes for
			 * PID_RFC2684_ETH_FCS?
			 */
			/*
			 * Skip the padding, but not the Access
			 * Control field.
			 */
			ND_TCHECK_LEN(p, bridge_pad);
			caplen -= bridge_pad;
			length -= bridge_pad;
			p += bridge_pad;

			/*
			 * What remains is an 802.5 Token Ring
			 * packet.
			 */
			token_print(ndo, p, length, caplen);
			return (1);

		case PID_RFC2684_FDDI_FCS:
		case PID_RFC2684_FDDI_NOFCS:
			/*
			 * XXX - remove the last two bytes for
			 * PID_RFC2684_ETH_FCS?
			 */
			/*
			 * Skip the padding.
			 */
			ND_TCHECK_LEN(p, bridge_pad + 1);
			caplen -= bridge_pad + 1;
			length -= bridge_pad + 1;
			p += bridge_pad + 1;

			/*
			 * What remains is an FDDI packet.
			 */
			fddi_print(ndo, p, length, caplen);
			return (1);

		case PID_RFC2684_BPDU:
			stp_print(ndo, p, length);
			return (1);
		}
	}
	if (!ndo->ndo_eflag) {
		/*
		 * Nobody printed the link-layer addresses, so print them, if
		 * we have any.
		 */
		if (src != NULL && dst != NULL) {
			ND_PRINT("%s > %s ",
				(src->addr_string)(ndo, src->addr),
				(dst->addr_string)(ndo, dst->addr));
		}
		/*
		 * Print the SNAP header, but if the OUI is 000000, don't
		 * bother printing it, and report the PID as being an
		 * ethertype.
		 */
		if (orgcode == 0x000000) {
			ND_PRINT("SNAP, ethertype %s (0x%04x), length %u: ",
			     tok2str(ethertype_values, "Unknown", et),
			     et, length);
		} else {
			ND_PRINT("SNAP, oui %s (0x%06x), pid %s (0x%04x), length %u: ",
			     tok2str(oui_values, "Unknown", orgcode),
			     orgcode,
			     tok2str(oui_to_struct_tok(orgcode), "Unknown", et),
			     et, length);
		}
	}
	return (0);

trunc:
	ND_PRINT("[|snap]");
	return (1);
}