예제 #1
0
static int
print_report(netdissect_options *ndo,
             const u_char *bp, const u_char *ep,
             u_int len)
{
	uint32_t mask, origin;
	u_int metric, done;
	u_int i, width;

	while (len > 0) {
		if (len < 3) {
			ND_PRINT(" [|]");
			return (0);
		}
		ND_TCHECK_3(bp);
		mask = (uint32_t)0xff << 24 | GET_U_1(bp) << 16 |
			GET_U_1(bp + 1) << 8 | GET_U_1(bp + 2);
		width = 1;
		if (GET_U_1(bp))
			width = 2;
		if (GET_U_1(bp + 1))
			width = 3;
		if (GET_U_1(bp + 2))
			width = 4;

		ND_PRINT("\n\tMask %s", intoa(htonl(mask)));
		bp += 3;
		len -= 3;
		do {
			if (bp + width + 1 > ep) {
				ND_PRINT(" [|]");
				return (0);
			}
			if (len < width + 1) {
				ND_PRINT("\n\t  [Truncated Report]");
				return (0);
			}
			origin = 0;
			for (i = 0; i < width; ++i) {
				ND_TCHECK_1(bp);
				origin = origin << 8 | GET_U_1(bp);
				bp++;
			}
			for ( ; i < 4; ++i)
				origin <<= 8;

			ND_TCHECK_1(bp);
			metric = GET_U_1(bp);
			bp++;
			done = metric & 0x80;
			metric &= 0x7f;
			ND_PRINT("\n\t  %s metric %u", intoa(htonl(origin)),
				metric);
			len -= width + 1;
		} while (!done);
	}
	return (0);
trunc:
	return (-1);
}
예제 #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);
}
예제 #3
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);
}
예제 #4
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;
}
예제 #5
0
파일: print-hsrp.c 프로젝트: fenner/tcpdump
void
hsrp_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
	const struct hsrp *hp = (const struct hsrp *) bp;
	uint8_t version;

	ndo->ndo_protocol = "hsrp";
	ND_TCHECK_1(hp->hsrp_version);
	version = GET_U_1(hp->hsrp_version);
	ND_PRINT("HSRPv%u", version);
	if (version != 0)
		return;
	ND_TCHECK_1(hp->hsrp_op_code);
	ND_PRINT("-");
	ND_PRINT("%s ",
		 tok2strary(op_code_str, "unknown (%u)", GET_U_1(hp->hsrp_op_code)));
	ND_PRINT("%u: ", len);
	ND_TCHECK_1(hp->hsrp_state);
	ND_PRINT("state=%s ",
		 tok2str(states, "Unknown (%u)", GET_U_1(hp->hsrp_state)));
	ND_TCHECK_1(hp->hsrp_group);
	ND_PRINT("group=%u ", GET_U_1(hp->hsrp_group));
	ND_TCHECK_1(hp->hsrp_reserved);
	if (GET_U_1(hp->hsrp_reserved) != 0) {
		ND_PRINT("[reserved=%u!] ", GET_U_1(hp->hsrp_reserved));
	}
	ND_TCHECK_4(hp->hsrp_virtaddr);
	ND_PRINT("addr=%s", ipaddr_string(ndo, hp->hsrp_virtaddr));
	if (ndo->ndo_vflag) {
		ND_PRINT(" hellotime=");
		unsigned_relts_print(ndo, GET_U_1(hp->hsrp_hellotime));
		ND_PRINT(" holdtime=");
		unsigned_relts_print(ndo, GET_U_1(hp->hsrp_holdtime));
		ND_PRINT(" priority=%u", GET_U_1(hp->hsrp_priority));
		ND_PRINT(" auth=\"");
		if (nd_printn(ndo, hp->hsrp_authdata, sizeof(hp->hsrp_authdata),
			      ndo->ndo_snapend)) {
			ND_PRINT("\"");
			goto trunc;
		}
		ND_PRINT("\"");
	}
	return;
trunc:
	nd_print_trunc(ndo);
}
예제 #6
0
파일: print-ahcp.c 프로젝트: biot/tcpdump
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);
}
예제 #7
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);
}
예제 #8
0
파일: print-ahcp.c 프로젝트: biot/tcpdump
static void
ahcp1_options_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
{
	uint8_t option_no, option_len;

	while (cp < ep) {
		/* Option no */
		ND_TCHECK_1(cp);
		option_no = EXTRACT_U_1(cp);
		cp += 1;
		ND_PRINT("\n\t %s", tok2str(ahcp1_opt_str, "Unknown-%u", option_no));
		if (option_no == AHCP1_OPT_PAD || option_no == AHCP1_OPT_MANDATORY)
			continue;
		/* Length */
		if (cp + 1 > ep)
			goto invalid;
		ND_TCHECK_1(cp);
		option_len = EXTRACT_U_1(cp);
		cp += 1;
		if (cp + option_len > ep)
			goto invalid;
		/* Value */
		if (option_no <= AHCP1_OPT_MAX && data_decoders[option_no] != NULL) {
			if (data_decoders[option_no](ndo, cp, cp + option_len) < 0)
				break; /* truncated and already marked up */
		} else {
			ND_PRINT(" (Length %u)", option_len);
			ND_TCHECK_LEN(cp, option_len);
		}
		cp += option_len;
	}
	return;

invalid:
	ND_PRINT("%s", istr);
	ND_TCHECK_LEN(cp, ep - cp);
	return;
trunc:
	nd_print_trunc(ndo);
}
예제 #9
0
파일: print-stp.c 프로젝트: Wilm0r/tcpdump
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;
}
예제 #10
0
static void
ipnet_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
{
	const ipnet_hdr_t *hdr;

	if (caplen < sizeof(ipnet_hdr_t))
		goto trunc;

	if (ndo->ndo_eflag)
		ipnet_hdr_print(ndo, p, length);

	length -= sizeof(ipnet_hdr_t);
	caplen -= sizeof(ipnet_hdr_t);
	hdr = (const ipnet_hdr_t *)p;
	p += sizeof(ipnet_hdr_t);

	ND_TCHECK_1(hdr->iph_family);
	switch (EXTRACT_U_1(hdr->iph_family)) {

	case IPH_AF_INET:
	        ip_print(ndo, p, length);
		break;

	case IPH_AF_INET6:
		ip6_print(ndo, p, length);
		break;

	default:
		if (!ndo->ndo_eflag)
			ipnet_hdr_print(ndo, (const u_char *)hdr,
					length + sizeof(ipnet_hdr_t));

		if (!ndo->ndo_suppress_default_print)
			ND_DEFAULTPRINT(p, caplen);
		break;
	}
	return;
trunc:
	ND_PRINT(" %s", tstr);
}
예제 #11
0
/* LCP config options */
static u_int
print_lcp_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) {
		if (opt < NUM_LCPOPTS)
			ND_PRINT("\n\t  %s Option (0x%02x), length %u (length bogus, should be >= 2)",
			          lcpconfopts[opt], opt, len);
		else
			ND_PRINT("\n\tunknown LCP option 0x%02x", opt);
		return 0;
	}
	if (opt < NUM_LCPOPTS)
		ND_PRINT("\n\t  %s Option (0x%02x), length %u", lcpconfopts[opt], opt, len);
	else {
		ND_PRINT("\n\tunknown LCP option 0x%02x", opt);
		return len;
	}

	switch (opt) {
	case LCPOPT_VEXT:
		if (len < 6) {
			ND_PRINT(" (length bogus, should be >= 6)");
			return len;
		}
		ND_TCHECK_3(p + 2);
		ND_PRINT(": Vendor: %s (%u)",
			tok2str(oui_values,"Unknown",EXTRACT_BE_U_3(p + 2)),
			EXTRACT_BE_U_3(p + 2));
#if 0
		ND_TCHECK_1(p + 5);
		ND_PRINT(", kind: 0x%02x", EXTRACT_U_1(p + 5));
		ND_PRINT(", Value: 0x");
		for (i = 0; i < len - 6; i++) {
			ND_TCHECK_1(p + 6 + i);
			ND_PRINT("%02x", EXTRACT_U_1(p + 6 + i));
		}
#endif
		break;
	case LCPOPT_MRU:
		if (len != 4) {
			ND_PRINT(" (length bogus, should be = 4)");
			return len;
		}
		ND_TCHECK_2(p + 2);
		ND_PRINT(": %u", EXTRACT_BE_U_2(p + 2));
		break;
	case LCPOPT_ACCM:
		if (len != 6) {
			ND_PRINT(" (length bogus, should be = 6)");
			return len;
		}
		ND_TCHECK_4(p + 2);
		ND_PRINT(": 0x%08x", EXTRACT_BE_U_4(p + 2));
		break;
	case LCPOPT_AP:
		if (len < 4) {
			ND_PRINT(" (length bogus, should be >= 4)");
			return len;
		}
		ND_TCHECK_2(p + 2);
		ND_PRINT(": %s", tok2str(ppptype2str, "Unknown Auth Proto (0x04x)", EXTRACT_BE_U_2(p + 2)));

		switch (EXTRACT_BE_U_2(p + 2)) {
		case PPP_CHAP:
			ND_TCHECK_1(p + 4);
			ND_PRINT(", %s", tok2str(authalg_values, "Unknown Auth Alg %u", EXTRACT_U_1(p + 4)));
			break;
		case PPP_PAP: /* fall through */
		case PPP_EAP:
		case PPP_SPAP:
		case PPP_SPAP_OLD:
                        break;
		default:
			print_unknown_data(ndo, p, "\n\t", len);
		}
		break;
	case LCPOPT_QP:
		if (len < 4) {
			ND_PRINT(" (length bogus, should be >= 4)");
			return 0;
		}
		ND_TCHECK_2(p + 2);
		if (EXTRACT_BE_U_2(p + 2) == PPP_LQM)
			ND_PRINT(": LQR");
		else
			ND_PRINT(": unknown");
		break;
	case LCPOPT_MN:
		if (len != 6) {
			ND_PRINT(" (length bogus, should be = 6)");
			return 0;
		}
		ND_TCHECK_4(p + 2);
		ND_PRINT(": 0x%08x", EXTRACT_BE_U_4(p + 2));
		break;
	case LCPOPT_PFC:
		break;
	case LCPOPT_ACFC:
		break;
	case LCPOPT_LD:
		if (len != 4) {
			ND_PRINT(" (length bogus, should be = 4)");
			return 0;
		}
		ND_TCHECK_2(p + 2);
		ND_PRINT(": 0x%04x", EXTRACT_BE_U_2(p + 2));
		break;
	case LCPOPT_CBACK:
		if (len < 3) {
			ND_PRINT(" (length bogus, should be >= 3)");
			return 0;
		}
		ND_PRINT(": ");
		ND_TCHECK_1(p + 2);
		ND_PRINT(": Callback Operation %s (%u)",
                       tok2str(ppp_callback_values, "Unknown", EXTRACT_U_1(p + 2)),
                       EXTRACT_U_1(p + 2));
		break;
	case LCPOPT_MLMRRU:
		if (len != 4) {
			ND_PRINT(" (length bogus, should be = 4)");
			return 0;
		}
		ND_TCHECK_2(p + 2);
		ND_PRINT(": %u", EXTRACT_BE_U_2(p + 2));
		break;
	case LCPOPT_MLED:
		if (len < 3) {
			ND_PRINT(" (length bogus, should be >= 3)");
			return 0;
		}
		ND_TCHECK_1(p + 2);
		switch (EXTRACT_U_1(p + 2)) {		/* class */
		case MEDCLASS_NULL:
			ND_PRINT(": Null");
			break;
		case MEDCLASS_LOCAL:
			ND_PRINT(": Local"); /* XXX */
			break;
		case MEDCLASS_IPV4:
			if (len != 7) {
				ND_PRINT(" (length bogus, should be = 7)");
				return 0;
			}
			ND_TCHECK_4(p + 3);
			ND_PRINT(": IPv4 %s", ipaddr_string(ndo, p + 3));
			break;
		case MEDCLASS_MAC:
			if (len != 9) {
				ND_PRINT(" (length bogus, should be = 9)");
				return 0;
			}
			ND_TCHECK_6(p + 3);
			ND_PRINT(": MAC %s", etheraddr_string(ndo, p + 3));
			break;
		case MEDCLASS_MNB:
			ND_PRINT(": Magic-Num-Block"); /* XXX */
			break;
		case MEDCLASS_PSNDN:
			ND_PRINT(": PSNDN"); /* XXX */
			break;
		default:
			ND_PRINT(": Unknown class %u", EXTRACT_U_1(p + 2));
			break;
		}
		break;

/* XXX: to be supported */
#if 0
	case LCPOPT_DEP6:
	case LCPOPT_FCSALT:
	case LCPOPT_SDP:
	case LCPOPT_NUMMODE:
	case LCPOPT_DEP12:
	case LCPOPT_DEP14:
	case LCPOPT_DEP15:
	case LCPOPT_DEP16:
        case LCPOPT_MLSSNHF:
	case LCPOPT_PROP:
	case LCPOPT_DCEID:
	case LCPOPT_MPP:
	case LCPOPT_LCPAOPT:
	case LCPOPT_COBS:
	case LCPOPT_PE:
	case LCPOPT_MLHF:
	case LCPOPT_I18N:
	case LCPOPT_SDLOS:
	case LCPOPT_PPPMUX:
		break;
#endif
	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("[|lcp]");
	return 0;
}
예제 #12
0
/* PAP (see RFC 1334) */
static void
handle_pap(netdissect_options *ndo,
           const u_char *p, u_int length)
{
	u_int code, len;
	u_int peerid_len, passwd_len, msg_len;
	const u_char *p0;
	u_int i;

	p0 = p;
	if (length < 1) {
		ND_PRINT("[|pap]");
		return;
	} else if (length < 4) {
		ND_TCHECK_1(p);
		ND_PRINT("[|pap 0x%02x]", EXTRACT_U_1(p));
		return;
	}

	ND_TCHECK_1(p);
	code = EXTRACT_U_1(p);
	ND_PRINT("PAP, %s (0x%02x)",
	          tok2str(papcode_values, "unknown", code),
	          code);
	p++;

	ND_TCHECK_1(p);
	ND_PRINT(", id %u", EXTRACT_U_1(p));	/* ID */
	p++;

	ND_TCHECK_2(p);
	len = EXTRACT_BE_U_2(p);
	p += 2;

	if (len > length) {
		ND_PRINT(", length %u > packet size", len);
		return;
	}
	length = len;
	if (length < (size_t)(p - p0)) {
		ND_PRINT(", length %u < PAP header length", length);
		return;
	}

	switch (code) {
	case PAP_AREQ:
		/* A valid Authenticate-Request is 6 or more octets long. */
		if (len < 6)
			goto trunc;
		if (length - (p - p0) < 1)
			return;
		ND_TCHECK_1(p);
		peerid_len = EXTRACT_U_1(p);	/* Peer-ID Length */
		p++;
		if (length - (p - p0) < peerid_len)
			return;
		ND_PRINT(", Peer ");
		for (i = 0; i < peerid_len; i++) {
			ND_TCHECK_1(p);
			safeputchar(ndo, EXTRACT_U_1(p));
			p++;
		}

		if (length - (p - p0) < 1)
			return;
		ND_TCHECK_1(p);
		passwd_len = EXTRACT_U_1(p);	/* Password Length */
		p++;
		if (length - (p - p0) < passwd_len)
			return;
		ND_PRINT(", Name ");
		for (i = 0; i < passwd_len; i++) {
			ND_TCHECK_1(p);
			safeputchar(ndo, EXTRACT_U_1(p));
			p++;
		}
		break;
	case PAP_AACK:
	case PAP_ANAK:
		/* Although some implementations ignore truncation at
		 * this point and at least one generates a truncated
		 * packet, RFC 1334 section 2.2.2 clearly states that
		 * both AACK and ANAK are at least 5 bytes long.
		 */
		if (len < 5)
			goto trunc;
		if (length - (p - p0) < 1)
			return;
		ND_TCHECK_1(p);
		msg_len = EXTRACT_U_1(p);	/* Msg-Length */
		p++;
		if (length - (p - p0) < msg_len)
			return;
		ND_PRINT(", Msg ");
		for (i = 0; i< msg_len; i++) {
			ND_TCHECK_1(p);
			safeputchar(ndo, EXTRACT_U_1(p));
			p++;
		}
		break;
	}
	return;

trunc:
	ND_PRINT("[|pap]");
}
예제 #13
0
파일: print-dccp.c 프로젝트: fenner/tcpdump
static u_int
dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen)
{
	uint8_t optlen, i;

	ND_TCHECK_1(option);

	if (GET_U_1(option) >= 32) {
		ND_TCHECK_1(option + 1);
		optlen = GET_U_1(option + 1);
		if (optlen < 2) {
			if (GET_U_1(option) >= 128)
				ND_PRINT("CCID option %u optlen too short",
					 GET_U_1(option));
			else
				ND_PRINT("%s optlen too short",
					  tok2str(dccp_option_values, "Option %u", GET_U_1(option)));
			return 0;
		}
	} else
		optlen = 1;

	if (hlen < optlen) {
		if (GET_U_1(option) >= 128)
			ND_PRINT("CCID option %u optlen goes past header length",
				  GET_U_1(option));
		else
			ND_PRINT("%s optlen goes past header length",
				  tok2str(dccp_option_values, "Option %u", GET_U_1(option)));
		return 0;
	}
	ND_TCHECK_LEN(option, optlen);

	if (GET_U_1(option) >= 128) {
		ND_PRINT("CCID option %u", GET_U_1(option));
		switch (optlen) {
			case 4:
				ND_PRINT(" %u", GET_BE_U_2(option + 2));
				break;
			case 6:
				ND_PRINT(" %u", GET_BE_U_4(option + 2));
				break;
			default:
				break;
		}
	} else {
		ND_PRINT("%s",
			 tok2str(dccp_option_values, "Option %u", GET_U_1(option)));
		switch (GET_U_1(option)) {
		case 32:
		case 33:
		case 34:
		case 35:
			if (optlen < 3) {
				ND_PRINT(" optlen too short");
				return optlen;
			}
			if (GET_U_1(option + 2) < 10){
				ND_PRINT(" %s",
					 dccp_feature_nums[GET_U_1(option + 2)]);
				for (i = 0; i < optlen - 3; i++)
					ND_PRINT(" %u",
						 GET_U_1(option + 3 + i));
			}
			break;
		case 36:
			if (optlen > 2) {
				ND_PRINT(" 0x");
				for (i = 0; i < optlen - 2; i++)
					ND_PRINT("%02x",
						 GET_U_1(option + 2 + i));
			}
			break;
		case 37:
			for (i = 0; i < optlen - 2; i++)
				ND_PRINT(" %u", GET_U_1(option + 2 + i));
			break;
		case 38:
			if (optlen > 2) {
				ND_PRINT(" 0x");
				for (i = 0; i < optlen - 2; i++)
					ND_PRINT("%02x",
						 GET_U_1(option + 2 + i));
			}
			break;
		case 39:
			if (optlen > 2) {
				ND_PRINT(" 0x");
				for (i = 0; i < optlen - 2; i++)
					ND_PRINT("%02x",
						 GET_U_1(option + 2 + i));
			}
			break;
		case 40:
			if (optlen > 2) {
				ND_PRINT(" 0x");
				for (i = 0; i < optlen - 2; i++)
					ND_PRINT("%02x",
						 GET_U_1(option + 2 + i));
			}
			break;
		case 41:
		/*
		 * 13.1.  Timestamp Option
		 *
		 *  +--------+--------+--------+--------+--------+--------+
		 *  |00101001|00000110|          Timestamp Value          |
		 *  +--------+--------+--------+--------+--------+--------+
		 *   Type=41  Length=6
		 */
			if (optlen == 6)
				ND_PRINT(" %u", GET_BE_U_4(option + 2));
			else
				ND_PRINT(" [optlen != 6]");
			break;
		case 42:
		/*
		 * 13.3.  Timestamp Echo Option
		 *
		 *  +--------+--------+--------+--------+--------+--------+
		 *  |00101010|00000110|           Timestamp Echo          |
		 *  +--------+--------+--------+--------+--------+--------+
		 *   Type=42    Len=6
		 *
		 *  +--------+--------+------- ... -------+--------+--------+
		 *  |00101010|00001000|  Timestamp Echo   |   Elapsed Time  |
		 *  +--------+--------+------- ... -------+--------+--------+
		 *   Type=42    Len=8       (4 bytes)
		 *
		 *  +--------+--------+------- ... -------+------- ... -------+
		 *  |00101010|00001010|  Timestamp Echo   |    Elapsed Time   |
		 *  +--------+--------+------- ... -------+------- ... -------+
		 *   Type=42   Len=10       (4 bytes)           (4 bytes)
		 */
			switch (optlen) {
			case 6:
				ND_PRINT(" %u", GET_BE_U_4(option + 2));
				break;
			case 8:
				ND_PRINT(" %u", GET_BE_U_4(option + 2));
				ND_PRINT(" (elapsed time %u)",
					 GET_BE_U_2(option + 6));
				break;
			case 10:
				ND_PRINT(" %u", GET_BE_U_4(option + 2));
				ND_PRINT(" (elapsed time %u)",
					 GET_BE_U_4(option + 6));
				break;
			default:
				ND_PRINT(" [optlen != 6 or 8 or 10]");
				break;
			}
			break;
		case 43:
			if (optlen == 6)
				ND_PRINT(" %u", GET_BE_U_4(option + 2));
			else if (optlen == 4)
				ND_PRINT(" %u", GET_BE_U_2(option + 2));
			else
				ND_PRINT(" [optlen != 4 or 6]");
			break;
		case 44:
			if (optlen > 2) {
				ND_PRINT(" ");
				for (i = 0; i < optlen - 2; i++)
					ND_PRINT("%02x",
						 GET_U_1(option + 2 + i));
			}
			break;
		}
	}

	return optlen;
trunc:
	nd_print_trunc(ndo);
	return 0;
}
예제 #14
0
/* CCP config options */
static u_int
print_ccp_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(ccpconfopts_values, "Unknown", opt),
		          opt,
		          len);
		return 0;
	}

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

	switch (opt) {
	case CCPOPT_BSDCOMP:
		if (len < 3) {
			ND_PRINT(" (length bogus, should be >= 3)");
			return len;
		}
		ND_TCHECK_1(p + 2);
		ND_PRINT(": Version: %u, Dictionary Bits: %u",
			EXTRACT_U_1(p + 2) >> 5,
			EXTRACT_U_1(p + 2) & 0x1f);
		break;
	case CCPOPT_MVRCA:
		if (len < 4) {
			ND_PRINT(" (length bogus, should be >= 4)");
			return len;
		}
		ND_TCHECK_1(p + 3);
		ND_PRINT(": Features: %u, PxP: %s, History: %u, #CTX-ID: %u",
				(EXTRACT_U_1(p + 2) & 0xc0) >> 6,
				(EXTRACT_U_1(p + 2) & 0x20) ? "Enabled" : "Disabled",
				EXTRACT_U_1(p + 2) & 0x1f,
				EXTRACT_U_1(p + 3));
		break;
	case CCPOPT_DEFLATE:
		if (len < 4) {
			ND_PRINT(" (length bogus, should be >= 4)");
			return len;
		}
		ND_TCHECK_1(p + 3);
		ND_PRINT(": Window: %uK, Method: %s (0x%x), MBZ: %u, CHK: %u",
			(EXTRACT_U_1(p + 2) & 0xf0) >> 4,
			((EXTRACT_U_1(p + 2) & 0x0f) == 8) ? "zlib" : "unknown",
			EXTRACT_U_1(p + 2) & 0x0f,
			(EXTRACT_U_1(p + 3) & 0xfc) >> 2,
			EXTRACT_U_1(p + 3) & 0x03);
		break;

/* XXX: to be supported */
#if 0
	case CCPOPT_OUI:
	case CCPOPT_PRED1:
	case CCPOPT_PRED2:
	case CCPOPT_PJUMP:
	case CCPOPT_HPPPC:
	case CCPOPT_STACLZS:
	case CCPOPT_MPPC:
	case CCPOPT_GFZA:
	case CCPOPT_V42BIS:
	case CCPOPT_LZSDCP:
	case CCPOPT_DEC:
	case CCPOPT_RESV:
		break;
#endif
	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("[|ccp]");
	return 0;
}
예제 #15
0
파일: print-egp.c 프로젝트: Wilm0r/tcpdump
static void
egpnrprint(netdissect_options *ndo,
           const struct egp_packet *egp, u_int length)
{
	const uint8_t *cp;
	uint32_t addr;
	uint32_t net;
	u_int netlen;
	u_int gateways, distances, networks;
	u_int intgw, extgw, t_gateways;
	const char *comma;

	addr = EXTRACT_IPV4_TO_NETWORK_ORDER(egp->egp_sourcenet);
	if (IN_CLASSA(addr)) {
		net = addr & IN_CLASSA_NET;
		netlen = 1;
	} else if (IN_CLASSB(addr)) {
		net = addr & IN_CLASSB_NET;
		netlen = 2;
	} else if (IN_CLASSC(addr)) {
		net = addr & IN_CLASSC_NET;
		netlen = 3;
	} else {
		net = 0;
		netlen = 0;
	}
	cp = (const uint8_t *)(egp + 1);
	length -= sizeof(*egp);

	intgw = EXTRACT_U_1(egp->egp_intgw);
	extgw = EXTRACT_U_1(egp->egp_extgw);
	t_gateways = intgw + extgw;
	for (gateways = 0; gateways < t_gateways; ++gateways) {
		/* Pickup host part of gateway address */
		addr = 0;
		if (length < 4 - netlen)
			goto trunc;
		ND_TCHECK_LEN(cp, 4 - netlen);
		switch (netlen) {

		case 1:
			addr = EXTRACT_U_1(cp);
			cp++;
			/* fall through */
		case 2:
			addr = (addr << 8) | EXTRACT_U_1(cp);
			cp++;
			/* fall through */
		case 3:
			addr = (addr << 8) | EXTRACT_U_1(cp);
			cp++;
			break;
		}
		addr |= net;
		length -= 4 - netlen;
		if (length < 1)
			goto trunc;
		ND_TCHECK_1(cp);
		distances = EXTRACT_U_1(cp);
		cp++;
		length--;
		ND_PRINT(" %s %s ",
		       gateways < intgw ? "int" : "ext",
		       ipaddr_string(ndo, (const u_char *)&addr));

		comma = "";
		ND_PRINT("(");
		while (distances != 0) {
			if (length < 2)
				goto trunc;
			ND_TCHECK_2(cp);
			ND_PRINT("%sd%u:", comma, EXTRACT_U_1(cp));
			cp++;
			comma = ", ";
			networks = EXTRACT_U_1(cp);
			cp++;
			length -= 2;
			while (networks != 0) {
				/* Pickup network number */
				if (length < 1)
					goto trunc;
				ND_TCHECK_1(cp);
				addr = ((uint32_t) EXTRACT_U_1(cp)) << 24;
				cp++;
				length--;
				if (IN_CLASSB(addr)) {
					if (length < 1)
						goto trunc;
					ND_TCHECK_1(cp);
					addr |= ((uint32_t) EXTRACT_U_1(cp)) << 16;
					cp++;
					length--;
				} else if (!IN_CLASSA(addr)) {
					if (length < 2)
						goto trunc;
					ND_TCHECK_2(cp);
					addr |= ((uint32_t) EXTRACT_U_1(cp)) << 16;
					cp++;
					addr |= ((uint32_t) EXTRACT_U_1(cp)) << 8;
					cp++;
					length -= 2;
				}
				ND_PRINT(" %s", ipaddr_string(ndo, (const u_char *)&addr));
				networks--;
			}
			distances--;
		}
		ND_PRINT(")");
	}
	return;
trunc:
	ND_PRINT("[|]");
}
예제 #16
0
/* Standard PPP printer */
u_int
ppp_print(netdissect_options *ndo,
          const u_char *p, u_int length)
{
	u_int proto,ppp_header;
        u_int olen = length; /* _o_riginal length */
	u_int hdr_len = 0;

	/*
	 * Here, we assume that p points to the Address and Control
	 * field (if they present).
	 */
	if (length < 2)
		goto trunc;
	ND_TCHECK_2(p);
        ppp_header = EXTRACT_BE_U_2(p);

        switch(ppp_header) {
        case (PPP_WITHDIRECTION_IN  << 8 | PPP_CONTROL):
            if (ndo->ndo_eflag) ND_PRINT("In  ");
            p += 2;
            length -= 2;
            hdr_len += 2;
            break;
        case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL):
            if (ndo->ndo_eflag) ND_PRINT("Out ");
            p += 2;
            length -= 2;
            hdr_len += 2;
            break;
        case (PPP_ADDRESS << 8 | PPP_CONTROL):
            p += 2;			/* ACFC not used */
            length -= 2;
            hdr_len += 2;
            break;

        default:
            break;
        }

	if (length < 2)
		goto trunc;
	ND_TCHECK_1(p);
	if (EXTRACT_U_1(p) % 2) {
		proto = EXTRACT_U_1(p);	/* PFC is used */
		p++;
		length--;
		hdr_len++;
	} else {
		ND_TCHECK_2(p);
		proto = EXTRACT_BE_U_2(p);
		p += 2;
		length -= 2;
		hdr_len += 2;
	}

	if (ndo->ndo_eflag)
		ND_PRINT("%s (0x%04x), length %u: ",
		          tok2str(ppptype2str, "unknown", proto),
		          proto,
		          olen);

	handle_ppp(ndo, proto, p, length);
	return (hdr_len);
trunc:
	ND_PRINT("[|ppp]");
	return (0);
}
예제 #17
0
/* CHAP */
static void
handle_chap(netdissect_options *ndo,
            const u_char *p, u_int length)
{
	u_int code, len;
	u_int val_size, name_size, msg_size;
	const u_char *p0;
	u_int i;

	p0 = p;
	if (length < 1) {
		ND_PRINT("[|chap]");
		return;
	} else if (length < 4) {
		ND_TCHECK_1(p);
		ND_PRINT("[|chap 0x%02x]", EXTRACT_U_1(p));
		return;
	}

	ND_TCHECK_1(p);
	code = EXTRACT_U_1(p);
	ND_PRINT("CHAP, %s (0x%02x)",
               tok2str(chapcode_values,"unknown",code),
               code);
	p++;

	ND_TCHECK_1(p);
	ND_PRINT(", id %u", EXTRACT_U_1(p));	/* ID */
	p++;

	ND_TCHECK_2(p);
	len = EXTRACT_BE_U_2(p);
	p += 2;

	/*
	 * Note that this is a generic CHAP decoding routine. Since we
	 * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
	 * MS-CHAPv2) is used at this point, we can't decode packet
	 * specifically to each algorithms. Instead, we simply decode
	 * the GCD (Gratest Common Denominator) for all algorithms.
	 */
	switch (code) {
	case CHAP_CHAL:
	case CHAP_RESP:
		if (length - (p - p0) < 1)
			return;
		ND_TCHECK_1(p);
		val_size = EXTRACT_U_1(p);	/* value size */
		p++;
		if (length - (p - p0) < val_size)
			return;
		ND_PRINT(", Value ");
		for (i = 0; i < val_size; i++) {
			ND_TCHECK_1(p);
			ND_PRINT("%02x", EXTRACT_U_1(p));
			p++;
		}
		name_size = len - (p - p0);
		ND_PRINT(", Name ");
		for (i = 0; i < name_size; i++) {
			ND_TCHECK_1(p);
			safeputchar(ndo, EXTRACT_U_1(p));
			p++;
		}
		break;
	case CHAP_SUCC:
	case CHAP_FAIL:
		msg_size = len - (p - p0);
		ND_PRINT(", Msg ");
		for (i = 0; i< msg_size; i++) {
			ND_TCHECK_1(p);
			safeputchar(ndo, EXTRACT_U_1(p));
			p++;
		}
		break;
	}
	return;

trunc:
	ND_PRINT("[|chap]");
}
예제 #18
0
/*
 * Print bootp requests
 */
void
bootp_print(netdissect_options *ndo,
	    const u_char *cp, u_int length)
{
	const struct bootp *bp;
	static const u_char vm_cmu[4] = VM_CMU;
	static const u_char vm_rfc1048[4] = VM_RFC1048;
	uint8_t bp_op, bp_htype, bp_hlen;

	ndo->ndo_protocol = "bootp";
	bp = (const struct bootp *)cp;
	ND_TCHECK_1(bp->bp_op);
	bp_op = EXTRACT_U_1(bp->bp_op);
	ND_PRINT("BOOTP/DHCP, %s",
		  tok2str(bootp_op_values, "unknown (0x%02x)", bp_op));

	ND_TCHECK_1(bp->bp_hlen);
	bp_htype = EXTRACT_U_1(bp->bp_htype);
	bp_hlen = EXTRACT_U_1(bp->bp_hlen);
	if (bp_htype == 1 && bp_hlen == 6 && bp_op == BOOTPREQUEST) {
		ND_TCHECK_6(bp->bp_chaddr);
		ND_PRINT(" from %s", etheraddr_string(ndo, bp->bp_chaddr));
	}

	ND_PRINT(", length %u", length);

	if (!ndo->ndo_vflag)
		return;

	ND_TCHECK_2(bp->bp_secs);

	/* The usual hardware address type is 1 (10Mb Ethernet) */
	if (bp_htype != 1)
		ND_PRINT(", htype %u", bp_htype);

	/* The usual length for 10Mb Ethernet address is 6 bytes */
	if (bp_htype != 1 || bp_hlen != 6)
		ND_PRINT(", hlen %u", bp_hlen);

	/* Only print interesting fields */
	if (EXTRACT_U_1(bp->bp_hops))
		ND_PRINT(", hops %u", EXTRACT_U_1(bp->bp_hops));
	if (EXTRACT_BE_U_4(bp->bp_xid))
		ND_PRINT(", xid 0x%x", EXTRACT_BE_U_4(bp->bp_xid));
	if (EXTRACT_BE_U_2(bp->bp_secs))
		ND_PRINT(", secs %u", EXTRACT_BE_U_2(bp->bp_secs));

	ND_TCHECK_2(bp->bp_flags);
	ND_PRINT(", Flags [%s]",
		  bittok2str(bootp_flag_values, "none", EXTRACT_BE_U_2(bp->bp_flags)));
	if (ndo->ndo_vflag > 1)
		ND_PRINT(" (0x%04x)", EXTRACT_BE_U_2(bp->bp_flags));

	/* Client's ip address */
	ND_TCHECK_4(bp->bp_ciaddr);
	if (EXTRACT_IPV4_TO_NETWORK_ORDER(bp->bp_ciaddr))
		ND_PRINT("\n\t  Client-IP %s", ipaddr_string(ndo, bp->bp_ciaddr));

	/* 'your' ip address (bootp client) */
	ND_TCHECK_4(bp->bp_yiaddr);
	if (EXTRACT_IPV4_TO_NETWORK_ORDER(bp->bp_yiaddr))
		ND_PRINT("\n\t  Your-IP %s", ipaddr_string(ndo, bp->bp_yiaddr));

	/* Server's ip address */
	ND_TCHECK_4(bp->bp_siaddr);
	if (EXTRACT_IPV4_TO_NETWORK_ORDER(bp->bp_siaddr))
		ND_PRINT("\n\t  Server-IP %s", ipaddr_string(ndo, bp->bp_siaddr));

	/* Gateway's ip address */
	ND_TCHECK_4(bp->bp_giaddr);
	if (EXTRACT_IPV4_TO_NETWORK_ORDER(bp->bp_giaddr))
		ND_PRINT("\n\t  Gateway-IP %s", ipaddr_string(ndo, bp->bp_giaddr));

	/* Client's Ethernet address */
	if (bp_htype == 1 && bp_hlen == 6) {
		ND_TCHECK_6(bp->bp_chaddr);
		ND_PRINT("\n\t  Client-Ethernet-Address %s", etheraddr_string(ndo, bp->bp_chaddr));
	}

	ND_TCHECK_1(bp->bp_sname);		/* check first char only */
	if (EXTRACT_U_1(bp->bp_sname)) {
		ND_PRINT("\n\t  sname \"");
		if (nd_printztn(ndo, bp->bp_sname, (u_int)sizeof(bp->bp_sname),
				ndo->ndo_snapend) == 0) {
			ND_PRINT("\"");
			nd_print_trunc(ndo);
			return;
		}
		ND_PRINT("\"");
	}
	ND_TCHECK_1(bp->bp_file);		/* check first char only */
	if (EXTRACT_U_1(bp->bp_file)) {
		ND_PRINT("\n\t  file \"");
		if (nd_printztn(ndo, bp->bp_file, (u_int)sizeof(bp->bp_file),
				ndo->ndo_snapend) == 0) {
			ND_PRINT("\"");
			nd_print_trunc(ndo);
			return;
		}
		ND_PRINT("\"");
	}

	/* Decode the vendor buffer */
	ND_TCHECK_4(bp->bp_vend);
	if (memcmp((const char *)bp->bp_vend, vm_rfc1048,
		    sizeof(uint32_t)) == 0)
		rfc1048_print(ndo, bp->bp_vend);
	else if (memcmp((const char *)bp->bp_vend, vm_cmu,
			sizeof(uint32_t)) == 0)
		cmu_print(ndo, bp->bp_vend);
	else {
		uint32_t ul;

		ul = EXTRACT_BE_U_4(bp->bp_vend);
		if (ul != 0)
			ND_PRINT("\n\t  Vendor-#0x%x", ul);
	}

	return;
trunc:
	nd_print_trunc(ndo);
}
예제 #19
0
void
vtp_print(netdissect_options *ndo,
          const u_char *pptr, u_int length)
{
    u_int type, len, name_len, tlv_len, tlv_value, mgmtd_len;
    const u_char *tptr;
    const struct vtp_vlan_ *vtp_vlan;

    ndo->ndo_protocol = "vtp";
    if (length < VTP_HEADER_LEN)
        goto trunc;

    tptr = pptr;

    ND_TCHECK_LEN(tptr, VTP_HEADER_LEN);

    type = EXTRACT_U_1(tptr + 1);
    ND_PRINT("VTPv%u, Message %s (0x%02x), length %u",
	   EXTRACT_U_1(tptr),
	   tok2str(vtp_message_type_values,"Unknown message type", type),
	   type,
	   length);

    /* In non-verbose mode, just print version and message type */
    if (ndo->ndo_vflag < 1) {
        return;
    }

    /* verbose mode print all fields */
    ND_PRINT("\n\tDomain name: ");
    mgmtd_len = EXTRACT_U_1(tptr + 3);
    if (mgmtd_len < 1 ||  mgmtd_len > 32) {
	ND_PRINT(" [invalid MgmtD Len %u]", mgmtd_len);
	return;
    }
    nd_printzp(ndo, tptr + 4, mgmtd_len, NULL);
    ND_PRINT(", %s: %u",
	   tok2str(vtp_header_values, "Unknown", type),
	   EXTRACT_U_1(tptr + 2));

    tptr += VTP_HEADER_LEN;

    switch (type) {

    case VTP_SUMMARY_ADV:

	/*
	 *  SUMMARY ADVERTISEMENT
	 *
	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |     Version   |     Code      |    Followers  |    MgmtD Len  |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |       Management Domain Name  (zero-padded to 32 bytes)       |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                    Configuration revision number              |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                  Updater Identity IP address                  |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                    Update Timestamp (12 bytes)                |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                        MD5 digest (16 bytes)                  |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *
	 */

	ND_TCHECK_8(tptr);
	ND_PRINT("\n\t  Config Rev %x, Updater %s",
	       EXTRACT_BE_U_4(tptr),
	       ipaddr_string(ndo, tptr+4));
	tptr += 8;
	ND_TCHECK_LEN(tptr, VTP_UPDATE_TIMESTAMP_LEN);
	ND_PRINT(", Timestamp 0x%08x 0x%08x 0x%08x",
	       EXTRACT_BE_U_4(tptr),
	       EXTRACT_BE_U_4(tptr + 4),
	       EXTRACT_BE_U_4(tptr + 8));
	tptr += VTP_UPDATE_TIMESTAMP_LEN;
	ND_TCHECK_LEN(tptr, VTP_MD5_DIGEST_LEN);
	ND_PRINT(", MD5 digest: %08x%08x%08x%08x",
	       EXTRACT_BE_U_4(tptr),
	       EXTRACT_BE_U_4(tptr + 4),
	       EXTRACT_BE_U_4(tptr + 8),
	       EXTRACT_BE_U_4(tptr + 12));
	tptr += VTP_MD5_DIGEST_LEN;
	break;

    case VTP_SUBSET_ADV:

	/*
	 *  SUBSET ADVERTISEMENT
	 *
	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |     Version   |     Code      |   Seq number  |    MgmtD Len  |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |       Management Domain Name  (zero-padded to 32 bytes)       |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                    Configuration revision number              |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                         VLAN info field 1                     |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                         ................                      |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                         VLAN info field N                     |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *
	 */

	ND_TCHECK_4(tptr);
	ND_PRINT(", Config Rev %x", EXTRACT_BE_U_4(tptr));

	/*
	 *  VLAN INFORMATION
	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  | V info len    |    Status     |  VLAN type    | VLAN name len |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |       ISL vlan id             |            MTU size           |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                     802.10 index (SAID)                       |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                         VLAN name                             |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *
	 */

	tptr += 4;
	while (tptr < (pptr+length)) {

	    ND_TCHECK_1(tptr);
	    len = EXTRACT_U_1(tptr);
	    if (len == 0)
		break;

	    ND_TCHECK_LEN(tptr, len);

	    vtp_vlan = (const struct vtp_vlan_*)tptr;
	    if (len < VTP_VLAN_INFO_FIXED_PART_LEN)
		goto trunc;
	    ND_TCHECK_SIZE(vtp_vlan);
	    ND_PRINT("\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name ",
		   tok2str(vtp_vlan_status,"Unknown",EXTRACT_U_1(vtp_vlan->status)),
		   tok2str(vtp_vlan_type_values,"Unknown",EXTRACT_U_1(vtp_vlan->type)),
		   EXTRACT_BE_U_2(vtp_vlan->vlanid),
		   EXTRACT_BE_U_2(vtp_vlan->mtu),
		   EXTRACT_BE_U_4(vtp_vlan->index));
	    len  -= VTP_VLAN_INFO_FIXED_PART_LEN;
	    tptr += VTP_VLAN_INFO_FIXED_PART_LEN;
	    name_len = EXTRACT_U_1(vtp_vlan->name_len);
	    if (len < 4*((name_len + 3)/4))
		goto trunc;
	    ND_TCHECK_LEN(tptr, name_len);
	    nd_printzp(ndo, tptr, name_len, NULL);

	    /*
	     * Vlan names are aligned to 32-bit boundaries.
	     */
	    len  -= 4*((name_len + 3)/4);
	    tptr += 4*((name_len + 3)/4);

            /* TLV information follows */

            while (len > 0) {

                /*
                 * Cisco specs say 2 bytes for type + 2 bytes for length;
                 * see http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm
                 * However, actual packets on the wire appear to use 1
                 * byte for the type and 1 byte for the length, so that's
                 * what we do.
                 */
                if (len < 2)
                    goto trunc;
                ND_TCHECK_2(tptr);
                type = EXTRACT_U_1(tptr);
                tlv_len = EXTRACT_U_1(tptr + 1);

                ND_PRINT("\n\t\t%s (0x%04x) TLV",
                       tok2str(vtp_vlan_tlv_values, "Unknown", type),
                       type);

                if (len < tlv_len * 2 + 2) {
                    ND_PRINT(" (TLV goes past the end of the packet)");
                    return;
                }
                ND_TCHECK_LEN(tptr, tlv_len * 2 + 2);

                /*
                 * We assume the value is a 2-byte integer; the length is
                 * in units of 16-bit words.
                 */
                if (tlv_len != 1) {
                    ND_PRINT(" (invalid TLV length %u != 1)", tlv_len);
                    return;
                } else {
                    tlv_value = EXTRACT_BE_U_2(tptr + 2);

                    switch (type) {
                    case VTP_VLAN_STE_HOP_COUNT:
                        ND_PRINT(", %u", tlv_value);
                        break;

                    case VTP_VLAN_PRUNING:
                        ND_PRINT(", %s (%u)",
                               tlv_value == 1 ? "Enabled" : "Disabled",
                               tlv_value);
                        break;

                    case VTP_VLAN_STP_TYPE:
                        ND_PRINT(", %s (%u)",
                               tok2str(vtp_stp_type_values, "Unknown", tlv_value),
                               tlv_value);
                        break;

                    case VTP_VLAN_BRIDGE_TYPE:
                        ND_PRINT(", %s (%u)",
                               tlv_value == 1 ? "SRB" : "SRT",
                               tlv_value);
                        break;

                    case VTP_VLAN_BACKUP_CRF_MODE:
                        ND_PRINT(", %s (%u)",
                               tlv_value == 1 ? "Backup" : "Not backup",
                               tlv_value);
                        break;

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

                    case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER:
                    case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER:
                    case VTP_VLAN_PARENT_VLAN:
                    case VTP_VLAN_TRANS_BRIDGED_VLAN:
                    case VTP_VLAN_ARP_HOP_COUNT:
                    default:
                        print_unknown_data(ndo, tptr, "\n\t\t  ", 2 + tlv_len*2);
                        break;
                    }
                }
                len -= 2 + tlv_len*2;
                tptr += 2 + tlv_len*2;
            }
	}
	break;

    case VTP_ADV_REQUEST:

	/*
	 *  ADVERTISEMENT REQUEST
	 *
	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |     Version   |     Code      |   Reserved    |    MgmtD Len  |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |       Management Domain Name  (zero-padded to 32 bytes)       |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *  |                          Start value                          |
	 *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 *
	 */

	ND_TCHECK_4(tptr);
	ND_PRINT("\n\tStart value: %u", EXTRACT_BE_U_4(tptr));
	break;

    case VTP_JOIN_MESSAGE:

	/* FIXME - Could not find message format */
	break;

    default:
	break;
    }

    return;

 trunc:
    nd_print_trunc(ndo);
}
예제 #20
0
static void
rfc1048_print(netdissect_options *ndo,
	      const u_char *bp)
{
	uint16_t tag;
	u_int len;
	const char *cp;
	char c;
	int first, idx;
	uint8_t subopt, suboptlen;

	ND_PRINT("\n\t  Vendor-rfc1048 Extensions");

	/* Step over magic cookie */
	ND_PRINT("\n\t    Magic Cookie 0x%08x", EXTRACT_BE_U_4(bp));
	bp += sizeof(int32_t);

	/* Loop while we there is a tag left in the buffer */
	while (ND_TTEST_1(bp)) {
		tag = EXTRACT_U_1(bp);
		bp++;
		if (tag == TAG_PAD && ndo->ndo_vflag < 3)
			continue;
		if (tag == TAG_END && ndo->ndo_vflag < 3)
			return;
		if (tag == TAG_EXTENDED_OPTION) {
			ND_TCHECK_2(bp + 1);
			tag = EXTRACT_BE_U_2(bp + 1);
			/* XXX we don't know yet if the IANA will
			 * preclude overlap of 1-byte and 2-byte spaces.
			 * If not, we need to offset tag after this step.
			 */
			cp = tok2str(xtag2str, "?xT%u", tag);
		} else
			cp = tok2str(tag2str, "?T%u", tag);
		c = *cp++;

		if (tag == TAG_PAD || tag == TAG_END)
			len = 0;
		else {
			/* Get the length; check for truncation */
			ND_TCHECK_1(bp);
			len = EXTRACT_U_1(bp);
			bp++;
		}

		ND_PRINT("\n\t    %s Option %u, length %u%s", cp, tag, len,
			  len > 0 ? ": " : "");

		if (tag == TAG_PAD && ndo->ndo_vflag > 2) {
			u_int ntag = 1;
			while (ND_TTEST_1(bp) &&
			       EXTRACT_U_1(bp) == TAG_PAD) {
				bp++;
				ntag++;
			}
			if (ntag > 1)
				ND_PRINT(", occurs %u", ntag);
		}

		ND_TCHECK_LEN(bp, len);

		if (tag == TAG_DHCP_MESSAGE && len == 1) {
			ND_PRINT("%s", tok2str(dhcp_msg_values, "Unknown (%u)", EXTRACT_U_1(bp)));
			bp++;
			continue;
		}

		if (tag == TAG_PARM_REQUEST) {
			idx = 0;
			while (len > 0) {
				cp = tok2str(tag2str, "?Option %u", EXTRACT_U_1(bp));
				bp++;
				len--;
				if (idx % 4 == 0)
					ND_PRINT("\n\t      ");
				else
					ND_PRINT(", ");
				ND_PRINT("%s", cp + 1);
				idx++;
			}
			continue;
		}

		if (tag == TAG_EXTENDED_REQUEST) {
			first = 1;
			while (len > 1) {
				cp = tok2str(xtag2str, "?xT%u", EXTRACT_BE_U_2(bp));
				bp += 2;
				len -= 2;
				if (!first)
					ND_PRINT("+");
				ND_PRINT("%s", cp + 1);
				first = 0;
			}
			continue;
		}

		/* Print data */
		if (c == '?') {
			/* Base default formats for unknown tags on data size */
			if (len & 1)
				c = 'b';
			else if (len & 2)
				c = 's';
			else
				c = 'l';
		}
		first = 1;
		switch (c) {

		case 'a':
			/* ASCII strings */
			ND_PRINT("\"");
			if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
				ND_PRINT("\"");
				goto trunc;
			}
			ND_PRINT("\"");
			bp += len;
			len = 0;
			break;

		case 'i':
		case 'l':
		case 'L':
			/* ip addresses/32-bit words */
			while (len >= 4) {
				if (!first)
					ND_PRINT(",");
				if (c == 'i')
					ND_PRINT("%s", ipaddr_string(ndo, bp));
				else if (c == 'L')
					ND_PRINT("%d", EXTRACT_BE_S_4(bp));
				else
					ND_PRINT("%u", EXTRACT_BE_U_4(bp));
				bp += 4;
				len -= 4;
				first = 0;
			}
			break;

		case 'p':
			/* IP address pairs */
			while (len >= 2*4) {
				if (!first)
					ND_PRINT(",");
				ND_PRINT("(%s:", ipaddr_string(ndo, bp));
				bp += 4;
				len -= 4;
				ND_PRINT("%s)", ipaddr_string(ndo, bp));
				bp += 4;
				len -= 4;
				first = 0;
			}
			break;

		case 's':
			/* shorts */
			while (len >= 2) {
				if (!first)
					ND_PRINT(",");
				ND_PRINT("%u", EXTRACT_BE_U_2(bp));
				bp += 2;
				len -= 2;
				first = 0;
			}
			break;

		case 'B':
			/* boolean */
			while (len > 0) {
				uint8_t bool_value;
				if (!first)
					ND_PRINT(",");
				bool_value = EXTRACT_U_1(bp);
				switch (bool_value) {
				case 0:
					ND_PRINT("N");
					break;
				case 1:
					ND_PRINT("Y");
					break;
				default:
					ND_PRINT("%u?", bool_value);
					break;
				}
				++bp;
				--len;
				first = 0;
			}
			break;

		case 'b':
		case 'x':
		default:
			/* Bytes */
			while (len > 0) {
				uint8_t byte_value;
				if (!first)
					ND_PRINT(c == 'x' ? ":" : ".");
				byte_value = EXTRACT_U_1(bp);
				if (c == 'x')
					ND_PRINT("%02x", byte_value);
				else
					ND_PRINT("%u", byte_value);
				++bp;
				--len;
				first = 0;
			}
			break;

		case '$':
			/* Guys we can't handle with one of the usual cases */
			switch (tag) {

			case TAG_NETBIOS_NODE:
				/* this option should be at least 1 byte long */
				if (len < 1) {
					ND_PRINT("ERROR: length < 1 bytes");
					break;
				}
				tag = EXTRACT_U_1(bp);
				++bp;
				--len;
				ND_PRINT("%s", tok2str(nbo2str, NULL, tag));
				break;

			case TAG_OPT_OVERLOAD:
				/* this option should be at least 1 byte long */
				if (len < 1) {
					ND_PRINT("ERROR: length < 1 bytes");
					break;
				}
				tag = EXTRACT_U_1(bp);
				++bp;
				--len;
				ND_PRINT("%s", tok2str(oo2str, NULL, tag));
				break;

			case TAG_CLIENT_FQDN:
				/* this option should be at least 3 bytes long */
				if (len < 3) {
					ND_PRINT("ERROR: length < 3 bytes");
					bp += len;
					len = 0;
					break;
				}
				if (EXTRACT_U_1(bp))
					ND_PRINT("[%s] ", client_fqdn_flags(EXTRACT_U_1(bp)));
				bp++;
				if (EXTRACT_U_1(bp) || EXTRACT_U_1(bp + 1))
					ND_PRINT("%u/%u ", EXTRACT_U_1(bp), EXTRACT_U_1(bp + 1));
				bp += 2;
				ND_PRINT("\"");
				if (nd_printn(ndo, bp, len - 3, ndo->ndo_snapend)) {
					ND_PRINT("\"");
					goto trunc;
				}
				ND_PRINT("\"");
				bp += len - 3;
				len = 0;
				break;

			case TAG_CLIENT_ID:
			    {
				int type;

				/* this option should be at least 1 byte long */
				if (len < 1) {
					ND_PRINT("ERROR: length < 1 bytes");
					break;
				}
				type = EXTRACT_U_1(bp);
				bp++;
				len--;
				if (type == 0) {
					ND_PRINT("\"");
					if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
						ND_PRINT("\"");
						goto trunc;
					}
					ND_PRINT("\"");
					bp += len;
					len = 0;
					break;
				} else {
					ND_PRINT("%s ", tok2str(arp2str, "hardware-type %u,", type));
					while (len > 0) {
						if (!first)
							ND_PRINT(":");
						ND_PRINT("%02x", EXTRACT_U_1(bp));
						++bp;
						--len;
						first = 0;
					}
				}
				break;
			    }

			case TAG_AGENT_CIRCUIT:
				while (len >= 2) {
					subopt = EXTRACT_U_1(bp);
					suboptlen = EXTRACT_U_1(bp + 1);
					bp += 2;
					len -= 2;
					if (suboptlen > len) {
						ND_PRINT("\n\t      %s SubOption %u, length %u: length goes past end of option",
							  tok2str(agent_suboption_values, "Unknown", subopt),
							  subopt,
							  suboptlen);
						bp += len;
						len = 0;
						break;
					}
					ND_PRINT("\n\t      %s SubOption %u, length %u: ",
						  tok2str(agent_suboption_values, "Unknown", subopt),
						  subopt,
						  suboptlen);
					switch (subopt) {

					case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */
					case AGENT_SUBOPTION_REMOTE_ID:
					case AGENT_SUBOPTION_SUBSCRIBER_ID:
						if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend))
							goto trunc;
						break;

					default:
						print_unknown_data(ndo, bp, "\n\t\t", suboptlen);
					}

					len -= suboptlen;
					bp += suboptlen;
				}
				break;

			case TAG_CLASSLESS_STATIC_RT:
			case TAG_CLASSLESS_STA_RT_MS:
			    {
				u_int mask_width, significant_octets, i;

				/* this option should be at least 5 bytes long */
				if (len < 5) {
					ND_PRINT("ERROR: length < 5 bytes");
					bp += len;
					len = 0;
					break;
				}
				while (len > 0) {
					if (!first)
						ND_PRINT(",");
					mask_width = EXTRACT_U_1(bp);
					bp++;
					len--;
					/* mask_width <= 32 */
					if (mask_width > 32) {
						ND_PRINT("[ERROR: Mask width (%u) > 32]", mask_width);
						bp += len;
						len = 0;
						break;
					}
					significant_octets = (mask_width + 7) / 8;
					/* significant octets + router(4) */
					if (len < significant_octets + 4) {
						ND_PRINT("[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4);
						bp += len;
						len = 0;
						break;
					}
					ND_PRINT("(");
					if (mask_width == 0)
						ND_PRINT("default");
					else {
						for (i = 0; i < significant_octets ; i++) {
							if (i > 0)
								ND_PRINT(".");
							ND_PRINT("%u", EXTRACT_U_1(bp));
							bp++;
						}
						for (i = significant_octets ; i < 4 ; i++)
							ND_PRINT(".0");
						ND_PRINT("/%u", mask_width);
					}
					ND_PRINT(":%s)", ipaddr_string(ndo, bp));
					bp += 4;
					len -= (significant_octets + 4);
					first = 0;
				}
				break;
			    }

			case TAG_USER_CLASS:
			    {
				u_int suboptnumber = 1;

				first = 1;
				if (len < 2) {
					ND_PRINT("ERROR: length < 2 bytes");
					bp += len;
					len = 0;
					break;
				}
				while (len > 0) {
					suboptlen = EXTRACT_U_1(bp);
					bp++;
					len--;
					ND_PRINT("\n\t      ");
					ND_PRINT("instance#%u: ", suboptnumber);
					if (suboptlen == 0) {
						ND_PRINT("ERROR: suboption length must be non-zero");
						bp += len;
						len = 0;
						break;
					}
					if (len < suboptlen) {
						ND_PRINT("ERROR: invalid option");
						bp += len;
						len = 0;
						break;
					}
					ND_PRINT("\"");
					if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) {
						ND_PRINT("\"");
						goto trunc;
					}
					ND_PRINT("\"");
					ND_PRINT(", length %u", suboptlen);
					suboptnumber++;
					len -= suboptlen;
					bp += suboptlen;
				}
				break;
			    }

			default:
				ND_PRINT("[unknown special tag %u, size %u]",
					  tag, len);
				bp += len;
				len = 0;
				break;
			}
			break;
		}
		/* Data left over? */
		if (len) {
			ND_PRINT("\n\t  trailing data length %u", len);
			bp += len;
		}
	}
	return;
trunc:
	nd_print_trunc(ndo);
}
예제 #21
0
파일: print-ahcp.c 프로젝트: biot/tcpdump
void
ahcp_print(netdissect_options *ndo, const u_char *cp, const u_int len)
{
	const u_char *ep = ndo->ndo_snapend;
	uint8_t version;

	ndo->ndo_protocol = "ahcp";
	ND_PRINT("AHCP");
	if (len < 2)
		goto invalid;
	/* Magic */
	ND_TCHECK_1(cp);
	if (EXTRACT_U_1(cp) != AHCP_MAGIC_NUMBER)
		goto invalid;
	cp += 1;
	/* Version */
	ND_TCHECK_1(cp);
	version = EXTRACT_U_1(cp);
	cp += 1;
	switch (version) {
		case AHCP_VERSION_1: {
			ND_PRINT(" Version 1");
			if (len < AHCP1_HEADER_FIX_LEN)
				goto invalid;
			if (!ndo->ndo_vflag) {
				ND_TCHECK_LEN(cp, AHCP1_HEADER_FIX_LEN - 2);
				cp += AHCP1_HEADER_FIX_LEN - 2;
			} else {
				/* Hopcount */
				ND_TCHECK_1(cp);
				ND_PRINT("\n\tHopcount %u", EXTRACT_U_1(cp));
				cp += 1;
				/* Original Hopcount */
				ND_TCHECK_1(cp);
				ND_PRINT(", Original Hopcount %u", EXTRACT_U_1(cp));
				cp += 1;
				/* Nonce */
				ND_TCHECK_4(cp);
				ND_PRINT(", Nonce 0x%08x", EXTRACT_BE_U_4(cp));
				cp += 4;
				/* Source Id */
				ND_TCHECK_8(cp);
				ND_PRINT(", Source Id %s", linkaddr_string(ndo, cp, 0, 8));
				cp += 8;
				/* Destination Id */
				ND_TCHECK_8(cp);
				ND_PRINT(", Destination Id %s", linkaddr_string(ndo, cp, 0, 8));
				cp += 8;
			}
			/* Body */
			ahcp1_body_print(ndo, cp, ep);
			break;
		}
		default:
			ND_PRINT(" Version %u (unknown)", version);
			break;
	}
	return;

invalid:
	ND_PRINT("%s", istr);
	ND_TCHECK_LEN(cp, ep - cp);
	return;
trunc:
	nd_print_trunc(ndo);
}
예제 #22
0
파일: print-slow.c 프로젝트: Wilm0r/tcpdump
void
slow_print(netdissect_options *ndo,
           const u_char *pptr, u_int len)
{
    int print_version;
    u_int subtype;

    ndo->ndo_protocol = "slow";
    if (len < 1)
        goto tooshort;
    ND_TCHECK_1(pptr);
    subtype = EXTRACT_U_1(pptr);

    /*
     * Sanity checking of the header.
     */
    switch (subtype) {
    case SLOW_PROTO_LACP:
        if (len < 2)
            goto tooshort;
        ND_TCHECK_1(pptr + 1);
        if (EXTRACT_U_1(pptr + 1) != LACP_VERSION) {
            ND_PRINT("LACP version %u packet not supported", EXTRACT_U_1(pptr + 1));
            return;
        }
        print_version = 1;
        break;

    case SLOW_PROTO_MARKER:
        if (len < 2)
            goto tooshort;
        ND_TCHECK_1(pptr + 1);
        if (EXTRACT_U_1(pptr + 1) != MARKER_VERSION) {
            ND_PRINT("MARKER version %u packet not supported", EXTRACT_U_1(pptr + 1));
            return;
        }
        print_version = 1;
        break;

    case SLOW_PROTO_OAM: /* fall through */
        print_version = 0;
        break;

    default:
        /* print basic information and exit */
        print_version = -1;
        break;
    }

    if (print_version == 1) {
        ND_PRINT("%sv%u, length %u",
               tok2str(slow_proto_values, "unknown (%u)", subtype),
               EXTRACT_U_1((pptr + 1)),
               len);
    } else {
        /* some slow protos don't have a version number in the header */
        ND_PRINT("%s, length %u",
               tok2str(slow_proto_values, "unknown (%u)", subtype),
               len);
    }

    /* unrecognized subtype */
    if (print_version == -1) {
        print_unknown_data(ndo, pptr, "\n\t", len);
        return;
    }

    if (!ndo->ndo_vflag)
        return;

    switch (subtype) {
    default: /* should not happen */
        break;

    case SLOW_PROTO_OAM:
        /* skip subtype */
        len -= 1;
        pptr += 1;
        slow_oam_print(ndo, pptr, len);
        break;

    case SLOW_PROTO_LACP:   /* LACP and MARKER share the same semantics */
    case SLOW_PROTO_MARKER:
        /* skip subtype and version */
        len -= 2;
        pptr += 2;
        slow_marker_lacp_print(ndo, pptr, len, subtype);
        break;
    }
    return;

tooshort:
    if (!ndo->ndo_vflag)
        ND_PRINT(" (packet is too short)");
    else
        ND_PRINT("\n\t\t packet is too short");
    return;

trunc:
    ND_PRINT("%s", tstr);
}
예제 #23
0
파일: print-tcp.c 프로젝트: fenner/tcpdump
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("]");
        }
예제 #24
0
파일: print-mpls.c 프로젝트: fenner/tcpdump
/*
 * RFC3032: MPLS label stack encoding
 */
void
mpls_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
	const u_char *p;
	uint32_t label_entry;
	uint16_t label_stack_depth = 0;
	enum mpls_packet_type pt = PT_UNKNOWN;

	ndo->ndo_protocol = "mpls";
	p = bp;
	ND_PRINT("MPLS");
	do {
		ND_TCHECK_LEN(p, sizeof(label_entry));
		if (length < sizeof(label_entry))
			goto trunc;
		label_entry = GET_BE_U_4(p);
		ND_PRINT("%s(label %u",
		       (label_stack_depth && ndo->ndo_vflag) ? "\n\t" : " ",
       		       MPLS_LABEL(label_entry));
		label_stack_depth++;
		if (ndo->ndo_vflag &&
		    MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
			ND_PRINT(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]);
		ND_PRINT(", exp %u", MPLS_EXP(label_entry));
		if (MPLS_STACK(label_entry))
			ND_PRINT(", [S]");
		ND_PRINT(", ttl %u)", MPLS_TTL(label_entry));

		p += sizeof(label_entry);
		length -= sizeof(label_entry);
	} while (!MPLS_STACK(label_entry));

	/*
	 * Try to figure out the packet type.
	 */
	switch (MPLS_LABEL(label_entry)) {

	case 0:	/* IPv4 explicit NULL label */
	case 3:	/* IPv4 implicit NULL label */
		pt = PT_IPV4;
		break;

	case 2:	/* IPv6 explicit NULL label */
		pt = PT_IPV6;
		break;

	default:
		/*
		 * Generally there's no indication of protocol in MPLS label
		 * encoding.
		 *
		 * However, draft-hsmit-isis-aal5mux-00.txt describes a
		 * technique for encapsulating IS-IS and IP traffic on the
		 * same ATM virtual circuit; you look at the first payload
		 * byte to determine the network layer protocol, based on
		 * the fact that
		 *
		 *	1) the first byte of an IP header is 0x45-0x4f
		 *	   for IPv4 and 0x60-0x6f for IPv6;
		 *
		 *	2) the first byte of an OSI CLNP packet is 0x81,
		 *	   the first byte of an OSI ES-IS packet is 0x82,
		 *	   and the first byte of an OSI IS-IS packet is
		 *	   0x83;
		 *
		 * so the network layer protocol can be inferred from the
		 * first byte of the packet, if the protocol is one of the
		 * ones listed above.
		 *
		 * Cisco sends control-plane traffic MPLS-encapsulated in
		 * this fashion.
		 */
		ND_TCHECK_1(p);
		if (length < 1) {
			/* nothing to print */
			return;
		}
		switch(GET_U_1(p)) {

		case 0x45:
		case 0x46:
		case 0x47:
		case 0x48:
		case 0x49:
		case 0x4a:
		case 0x4b:
		case 0x4c:
		case 0x4d:
		case 0x4e:
		case 0x4f:
			pt = PT_IPV4;
			break;

		case 0x60:
		case 0x61:
		case 0x62:
		case 0x63:
		case 0x64:
		case 0x65:
		case 0x66:
		case 0x67:
		case 0x68:
		case 0x69:
		case 0x6a:
		case 0x6b:
		case 0x6c:
		case 0x6d:
		case 0x6e:
		case 0x6f:
			pt = PT_IPV6;
			break;

		case 0x81:
		case 0x82:
		case 0x83:
			pt = PT_OSI;
			break;

		default:
			/* ok bail out - we did not figure out what it is*/
			break;
		}
	}

	/*
	 * Print the payload.
	 */
	if (pt == PT_UNKNOWN) {
		if (!ndo->ndo_suppress_default_print)
			ND_DEFAULTPRINT(p, length);
		return;
	}
	ND_PRINT(ndo->ndo_vflag ? "\n\t" : " ");
	switch (pt) {

	case PT_IPV4:
		ip_print(ndo, p, length);
		break;

	case PT_IPV6:
		ip6_print(ndo, p, length);
		break;

	case PT_OSI:
		isoclns_print(ndo, p, length);
		break;

	default:
		break;
	}
	return;

trunc:
	nd_print_trunc(ndo);
}
예제 #25
0
파일: print-stp.c 프로젝트: Wilm0r/tcpdump
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;
        }
    }
예제 #26
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;
}
예제 #27
0
void
dvmrp_print(netdissect_options *ndo,
            const u_char *bp, u_int len)
{
	const u_char *ep;
	u_char type;
	uint8_t major_version, minor_version;

	ndo->ndo_protocol = "dvmrp";
	ep = ndo->ndo_snapend;
	if (bp >= ep)
		return;

	ND_TCHECK_1(bp + 1);
	type = GET_U_1(bp + 1);

	/* Skip IGMP header */
	bp += 8;
	len -= 8;

	switch (type) {

	case DVMRP_PROBE:
		ND_PRINT(" Probe");
		if (ndo->ndo_vflag) {
			if (print_probe(ndo, bp, ep, len) < 0)
				goto trunc;
		}
		break;

	case DVMRP_REPORT:
		ND_PRINT(" Report");
		if (ndo->ndo_vflag > 1) {
			if (print_report(ndo, bp, ep, len) < 0)
				goto trunc;
		}
		break;

	case DVMRP_ASK_NEIGHBORS:
		ND_PRINT(" Ask-neighbors(old)");
		break;

	case DVMRP_NEIGHBORS:
		ND_PRINT(" Neighbors(old)");
		if (print_neighbors(ndo, bp, ep, len) < 0)
			goto trunc;
		break;

	case DVMRP_ASK_NEIGHBORS2:
		ND_PRINT(" Ask-neighbors2");
		break;

	case DVMRP_NEIGHBORS2:
		ND_PRINT(" Neighbors2");
		/*
		 * extract version from IGMP group address field
		 */
		bp -= 4;
		ND_TCHECK_4(bp);
		major_version = GET_U_1(bp + 3);
		minor_version = GET_U_1(bp + 2);
		bp += 4;
		if (print_neighbors2(ndo, bp, ep, len, major_version,
		    minor_version) < 0)
			goto trunc;
		break;

	case DVMRP_PRUNE:
		ND_PRINT(" Prune");
		if (print_prune(ndo, bp) < 0)
			goto trunc;
		break;

	case DVMRP_GRAFT:
		ND_PRINT(" Graft");
		if (print_graft(ndo, bp) < 0)
			goto trunc;
		break;

	case DVMRP_GRAFT_ACK:
		ND_PRINT(" Graft-ACK");
		if (print_graft_ack(ndo, bp) < 0)
			goto trunc;
		break;

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

trunc:
	nd_print_trunc(ndo);
	return;
}
예제 #28
0
/*
 * Print NTP time requests and responses
 */
static void
ntp_time_print(netdissect_options *ndo,
	       const struct ntp_time_data *bp, u_int length)
{
	uint8_t stratum;

	if (length < NTP_TIMEMSG_MINLEN)
		goto invalid;

	ND_TCHECK_1(bp->stratum);
	stratum = EXTRACT_U_1(bp->stratum);
	ND_PRINT(", Stratum %u (%s)",
		stratum,
		tok2str(ntp_stratum_values, (stratum >=2 && stratum<=15) ? "secondary reference" : "reserved", stratum));

	ND_TCHECK_1(bp->ppoll);
	ND_PRINT(", poll %d", EXTRACT_S_1(bp->ppoll));
	p_poll(ndo, EXTRACT_S_1(bp->ppoll));

	ND_TCHECK_1(bp->precision);
	ND_PRINT(", precision %d", EXTRACT_S_1(bp->precision));

	ND_TCHECK_SIZE(&bp->root_delay);
	ND_PRINT("\n\tRoot Delay: ");
	p_sfix(ndo, &bp->root_delay);

	ND_TCHECK_SIZE(&bp->root_dispersion);
	ND_PRINT(", Root dispersion: ");
	p_sfix(ndo, &bp->root_dispersion);

	ND_TCHECK_4(bp->refid);
	ND_PRINT(", Reference-ID: ");
	/* Interpretation depends on stratum */
	switch (stratum) {

	case UNSPECIFIED:
		ND_PRINT("(unspec)");
		break;

	case PRIM_REF:
		if (nd_printn(ndo, (const u_char *)&(bp->refid), 4, ndo->ndo_snapend))
			goto trunc;
		break;

	case INFO_QUERY:
		ND_PRINT("%s INFO_QUERY", ipaddr_string(ndo, bp->refid));
		/* this doesn't have more content */
		return;

	case INFO_REPLY:
		ND_PRINT("%s INFO_REPLY", ipaddr_string(ndo, bp->refid));
		/* this is too complex to be worth printing */
		return;

	default:
		/* In NTPv4 (RFC 5905) refid is an IPv4 address or first 32 bits of
		   MD5 sum of IPv6 address */
		ND_PRINT("0x%08x", EXTRACT_BE_U_4(bp->refid));
		break;
	}

	ND_TCHECK_SIZE(&bp->ref_timestamp);
	ND_PRINT("\n\t  Reference Timestamp:  ");
	p_ntp_time(ndo, &(bp->ref_timestamp));

	ND_TCHECK_SIZE(&bp->org_timestamp);
	ND_PRINT("\n\t  Originator Timestamp: ");
	p_ntp_time(ndo, &(bp->org_timestamp));

	ND_TCHECK_SIZE(&bp->rec_timestamp);
	ND_PRINT("\n\t  Receive Timestamp:    ");
	p_ntp_time(ndo, &(bp->rec_timestamp));

	ND_TCHECK_SIZE(&bp->xmt_timestamp);
	ND_PRINT("\n\t  Transmit Timestamp:   ");
	p_ntp_time(ndo, &(bp->xmt_timestamp));

	ND_PRINT("\n\t    Originator - Receive Timestamp:  ");
	p_ntp_delta(ndo, &(bp->org_timestamp), &(bp->rec_timestamp));

	ND_PRINT("\n\t    Originator - Transmit Timestamp: ");
	p_ntp_delta(ndo, &(bp->org_timestamp), &(bp->xmt_timestamp));

	/* FIXME: this code is not aware of any extension fields */
	if (length == NTP_TIMEMSG_MINLEN + 4) { 	/* Optional: key-id (crypto-NAK) */
		ND_TCHECK_4(bp->key_id);
		ND_PRINT("\n\tKey id: %u", EXTRACT_BE_U_4(bp->key_id));
	} else if (length == NTP_TIMEMSG_MINLEN + 4 + 16) { 	/* Optional: key-id + 128-bit digest */
		ND_TCHECK_4(bp->key_id);
		ND_PRINT("\n\tKey id: %u", EXTRACT_BE_U_4(bp->key_id));
		ND_TCHECK_LEN(bp->message_digest, 16);
		ND_PRINT("\n\tAuthentication: %08x%08x%08x%08x",
			 EXTRACT_BE_U_4(bp->message_digest),
			 EXTRACT_BE_U_4(bp->message_digest + 4),
			 EXTRACT_BE_U_4(bp->message_digest + 8),
			 EXTRACT_BE_U_4(bp->message_digest + 12));
	} else if (length == NTP_TIMEMSG_MINLEN + 4 + 20) { 	/* Optional: key-id + 160-bit digest */
		ND_TCHECK_4(bp->key_id);
		ND_PRINT("\n\tKey id: %u", EXTRACT_BE_U_4(bp->key_id));
		ND_TCHECK_LEN(bp->message_digest, 20);
		ND_PRINT("\n\tAuthentication: %08x%08x%08x%08x%08x",
			 EXTRACT_BE_U_4(bp->message_digest),
			 EXTRACT_BE_U_4(bp->message_digest + 4),
			 EXTRACT_BE_U_4(bp->message_digest + 8),
			 EXTRACT_BE_U_4(bp->message_digest + 12),
			 EXTRACT_BE_U_4(bp->message_digest + 16));
	} else if (length > NTP_TIMEMSG_MINLEN) {
		ND_PRINT("\n\t(%u more bytes after the header)", length - NTP_TIMEMSG_MINLEN);
	}
	return;

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

trunc:
	nd_print_trunc(ndo);
}
예제 #29
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);
}
예제 #30
0
파일: print-radius.c 프로젝트: biot/tcpdump
static void
print_attr_strange(netdissect_options *ndo,
                   const u_char *data, u_int length, u_short attr_code)
{
   u_short len_data;
   u_int error_cause_value;

   switch(attr_code)
   {
      case ARAP_PASS:
           if (length != 16)
           {
               ND_PRINT("ERROR: length %u != 16", length);
               return;
           }
           ND_PRINT("User_challenge (");
           ND_TCHECK_8(data);
           len_data = 8;
           PRINT_HEX(len_data, data);
           ND_PRINT(") User_resp(");
           ND_TCHECK_8(data);
           len_data = 8;
           PRINT_HEX(len_data, data);
           ND_PRINT(")");
        break;

      case ARAP_FEATURES:
           if (length != 14)
           {
               ND_PRINT("ERROR: length %u != 14", length);
               return;
           }
           ND_TCHECK_1(data);
           if (EXTRACT_U_1(data))
              ND_PRINT("User can change password");
           else
              ND_PRINT("User cannot change password");
           data++;
           ND_TCHECK_1(data);
           ND_PRINT(", Min password length: %u", EXTRACT_U_1(data));
           data++;
           ND_PRINT(", created at: ");
           ND_TCHECK_4(data);
           len_data = 4;
           PRINT_HEX(len_data, data);
           ND_PRINT(", expires in: ");
           ND_TCHECK_4(data);
           len_data = 4;
           PRINT_HEX(len_data, data);
           ND_PRINT(", Current Time: ");
           ND_TCHECK_4(data);
           len_data = 4;
           PRINT_HEX(len_data, data);
        break;

      case ARAP_CHALLENGE_RESP:
           if (length < 8)
           {
               ND_PRINT("ERROR: length %u != 8", length);
               return;
           }
           ND_TCHECK_8(data);
           len_data = 8;
           PRINT_HEX(len_data, data);
        break;

      case ERROR_CAUSE:
           if (length != 4)
           {
               ND_PRINT("Error: length %u != 4", length);
               return;
           }
           ND_TCHECK_4(data);

           error_cause_value = EXTRACT_BE_U_4(data);
           ND_PRINT("Error cause %u: %s", error_cause_value, tok2str(errorcausetype, "Error-Cause %u not known", error_cause_value));
        break;
   }
   return;

   trunc:
     nd_print_trunc(ndo);
}