Example #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);
}
Example #2
0
void
msdp_print(netdissect_options *ndo, const u_char *sp, u_int length)
{
	unsigned int type, len;

	ndo->ndo_protocol = "msdp";
	ND_TCHECK_3(sp);
	/* See if we think we're at the beginning of a compound packet */
	type = EXTRACT_U_1(sp);
	len = EXTRACT_BE_U_2(sp + 1);
	if (len > 1500 || len < 3 || type == 0 || type > MSDP_TYPE_MAX)
		goto trunc;	/* not really truncated, but still not decodable */
	ND_PRINT(" msdp:");
	while (length != 0) {
		ND_TCHECK_3(sp);
		type = EXTRACT_U_1(sp);
		len = EXTRACT_BE_U_2(sp + 1);
		if (len > 1400 || ndo->ndo_vflag)
			ND_PRINT(" [len %u]", len);
		if (len < 3)
			goto trunc;
		if (length < len)
			goto trunc;
		sp += 3;
		length -= 3;
		switch (type) {
		case 1:	/* IPv4 Source-Active */
		case 3: /* IPv4 Source-Active Response */
			if (type == 1)
				ND_PRINT(" SA");
			else
				ND_PRINT(" SA-Response");
			ND_TCHECK_1(sp);
			ND_PRINT(" %u entries", EXTRACT_U_1(sp));
			if ((u_int)((EXTRACT_U_1(sp) * 12) + 8) < len) {
				ND_PRINT(" [w/data]");
				if (ndo->ndo_vflag > 1) {
					ND_PRINT(" ");
					ip_print(ndo, sp +
						 EXTRACT_U_1(sp) * 12 + 8 - 3,
					         len - (EXTRACT_U_1(sp) * 12 + 8));
				}
			}
			break;
		case 2:
			ND_PRINT(" SA-Request");
			ND_TCHECK_5(sp);
			ND_PRINT(" for %s", ipaddr_string(ndo, sp + 1));
			break;
		case 4:
			ND_PRINT(" Keepalive");
			if (len != 3)
				ND_PRINT("[len=%u] ", len);
			break;
		case 5:
			ND_PRINT(" Notification");
			break;
		default:
			ND_PRINT(" [type=%u len=%u]", type, len);
			break;
		}
		sp += (len - 3);
		length -= (len - 3);
	}
	return;
trunc:
	nd_print_trunc(ndo);
}
Example #3
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;
}
Example #4
0
/* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
static void
handle_ctrl_proto(netdissect_options *ndo,
                  u_int proto, const u_char *pptr, u_int length)
{
	const char *typestr;
	u_int code, len;
	u_int (*pfunc)(netdissect_options *, const u_char *, u_int);
	u_int x, j;
        const u_char *tptr;

        tptr=pptr;

        typestr = tok2str(ppptype2str, "unknown ctrl-proto (0x%04x)", proto);
	ND_PRINT("%s, ", typestr);

	if (length < 4) /* FIXME weak boundary checking */
		goto trunc;
	ND_TCHECK_2(tptr);

	code = EXTRACT_U_1(tptr);
	tptr++;

	ND_PRINT("%s (0x%02x), id %u, length %u",
	          tok2str(cpcodes, "Unknown Opcode",code),
	          code,
	          EXTRACT_U_1(tptr), /* ID */
	          length + 2);
	tptr++;

	if (!ndo->ndo_vflag)
		return;

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

	if (len < 4) {
		ND_PRINT("\n\tencoded length %u (< 4))", len);
		return;
	}

	if (len > length) {
		ND_PRINT("\n\tencoded length %u (> packet length %u))", len, length);
		return;
	}
	length = len;

	ND_PRINT("\n\tencoded length %u (=Option(s) length %u)", len, len - 4);

	if (length == 4)
		return;    /* there may be a NULL confreq etc. */

	if (ndo->ndo_vflag > 1)
		print_unknown_data(ndo, pptr - 2, "\n\t", 6);


	switch (code) {
	case CPCODES_VEXT:
		if (length < 11)
			break;
		ND_TCHECK_4(tptr);
		ND_PRINT("\n\t  Magic-Num 0x%08x", EXTRACT_BE_U_4(tptr));
		tptr += 4;
		ND_TCHECK_3(tptr);
		ND_PRINT(" Vendor: %s (%u)",
                       tok2str(oui_values,"Unknown",EXTRACT_BE_U_3(tptr)),
                       EXTRACT_BE_U_3(tptr));
		/* XXX: need to decode Kind and Value(s)? */
		break;
	case CPCODES_CONF_REQ:
	case CPCODES_CONF_ACK:
	case CPCODES_CONF_NAK:
	case CPCODES_CONF_REJ:
		x = len - 4;	/* Code(1), Identifier(1) and Length(2) */
		do {
			switch (proto) {
			case PPP_LCP:
				pfunc = print_lcp_config_options;
				break;
			case PPP_IPCP:
				pfunc = print_ipcp_config_options;
				break;
			case PPP_IPV6CP:
				pfunc = print_ip6cp_config_options;
				break;
			case PPP_CCP:
				pfunc = print_ccp_config_options;
				break;
			case PPP_BACP:
				pfunc = print_bacp_config_options;
				break;
			default:
				/*
				 * No print routine for the options for
				 * this protocol.
				 */
				pfunc = NULL;
				break;
			}

			if (pfunc == NULL) /* catch the above null pointer if unknown CP */
				break;

			if ((j = (*pfunc)(ndo, tptr, len)) == 0)
				break;
			x -= j;
			tptr += j;
		} while (x != 0);
		break;

	case CPCODES_TERM_REQ:
	case CPCODES_TERM_ACK:
		/* XXX: need to decode Data? */
		break;
	case CPCODES_CODE_REJ:
		/* XXX: need to decode Rejected-Packet? */
		break;
	case CPCODES_PROT_REJ:
		if (length < 6)
			break;
		ND_TCHECK_2(tptr);
		ND_PRINT("\n\t  Rejected %s Protocol (0x%04x)",
		       tok2str(ppptype2str,"unknown", EXTRACT_BE_U_2(tptr)),
		       EXTRACT_BE_U_2(tptr));
		/* XXX: need to decode Rejected-Information? - hexdump for now */
		if (len > 6) {
			ND_PRINT("\n\t  Rejected Packet");
			print_unknown_data(ndo, tptr + 2, "\n\t    ", len - 2);
		}
		break;
	case CPCODES_ECHO_REQ:
	case CPCODES_ECHO_RPL:
	case CPCODES_DISC_REQ:
		if (length < 8)
			break;
		ND_TCHECK_4(tptr);
		ND_PRINT("\n\t  Magic-Num 0x%08x", EXTRACT_BE_U_4(tptr));
		/* XXX: need to decode Data? - hexdump for now */
		if (len > 8) {
			ND_PRINT("\n\t  -----trailing data-----");
			ND_TCHECK_LEN(tptr + 4, len - 8);
			print_unknown_data(ndo, tptr + 4, "\n\t  ", len - 8);
		}
		break;
	case CPCODES_ID:
		if (length < 8)
			break;
		ND_TCHECK_4(tptr);
		ND_PRINT("\n\t  Magic-Num 0x%08x", EXTRACT_BE_U_4(tptr));
		/* RFC 1661 says this is intended to be human readable */
		if (len > 8) {
			ND_PRINT("\n\t  Message\n\t    ");
			if (fn_printn(ndo, tptr + 4, len - 4, ndo->ndo_snapend))
				goto trunc;
		}
		break;
	case CPCODES_TIME_REM:
		if (length < 12)
			break;
		ND_TCHECK_4(tptr);
		ND_PRINT("\n\t  Magic-Num 0x%08x", EXTRACT_BE_U_4(tptr));
		ND_TCHECK_4(tptr + 4);
		ND_PRINT(", Seconds-Remaining %us", EXTRACT_BE_U_4(tptr + 4));
		/* XXX: need to decode Message? */
		break;
	default:
		/* XXX this is dirty but we do not get the
		 * original pointer passed to the begin
		 * the PPP packet */
		if (ndo->ndo_vflag <= 1)
			print_unknown_data(ndo, pptr - 2, "\n\t  ", length + 2);
		break;
	}
	return;

trunc:
	ND_PRINT("[|%s]", typestr);
}