Esempio n. 1
0
static inline void
ipnet_hdr_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
	const ipnet_hdr_t *hdr;
	hdr = (const ipnet_hdr_t *)bp;

	ND_TCHECK_SIZE(hdr);
	ND_PRINT("%u > %u", EXTRACT_BE_U_4(hdr->iph_zsrc),
		  EXTRACT_BE_U_4(hdr->iph_zdst));

	if (!ndo->ndo_qflag) {
		ND_PRINT(", family %s (%u)",
                          tok2str(ipnet_values, "Unknown",
                                  EXTRACT_U_1(hdr->iph_family)),
                          EXTRACT_U_1(hdr->iph_family));
        } else {
		ND_PRINT(", %s",
                          tok2str(ipnet_values,
                                  "Unknown Ethertype (0x%04x)",
				  EXTRACT_U_1(hdr->iph_family)));
        }

	ND_PRINT(", length %u: ", length);
	return;
trunc:
	ND_PRINT(" %s", tstr);
}
Esempio n. 2
0
static int
parsepathconf(netdissect_options *ndo,
              const uint32_t *dp)
{
	u_int er;
	const struct nfsv3_pathconf *spp;

	if (!(dp = parsestatus(ndo, dp, &er)))
		return (0);
	if (ndo->ndo_vflag)
		ND_PRINT(" POST:");
	if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
		return (0);
	if (er)
		return (1);

	spp = (const struct nfsv3_pathconf *)dp;
	ND_TCHECK_SIZE(spp);

	ND_PRINT(" linkmax %u namemax %u %s %s %s %s",
	       EXTRACT_BE_U_4(&spp->pc_linkmax),
	       EXTRACT_BE_U_4(&spp->pc_namemax),
	       EXTRACT_BE_U_4(&spp->pc_notrunc) ? "notrunc" : "",
	       EXTRACT_BE_U_4(&spp->pc_chownrestricted) ? "chownres" : "",
	       EXTRACT_BE_U_4(&spp->pc_caseinsensitive) ? "igncase" : "",
	       EXTRACT_BE_U_4(&spp->pc_casepreserving) ? "keepcase" : "");
	return (1);
trunc:
	return (0);
}
Esempio n. 3
0
void
igrp_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
	const struct igrphdr *hdr;
	const u_char *cp;
	u_int nint, nsys, next;

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

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

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

	length -= sizeof(*hdr);
	while (length >= IGRP_RTE_SIZE) {
		if (nint > 0) {
			ND_TCHECK_LEN(cp, IGRP_RTE_SIZE);
			igrp_entry_print(ndo, (const struct igrprte *)cp, 1, 0);
			--nint;
		} else if (nsys > 0) {
			ND_TCHECK_LEN(cp, IGRP_RTE_SIZE);
			igrp_entry_print(ndo, (const struct igrprte *)cp, 0, 0);
			--nsys;
		} else if (next > 0) {
			ND_TCHECK_LEN(cp, IGRP_RTE_SIZE);
			igrp_entry_print(ndo, (const struct igrprte *)cp, 0, 1);
			--next;
		} else {
			ND_PRINT(" [extra bytes %u]", length);
			break;
		}
		cp += IGRP_RTE_SIZE;
		length -= IGRP_RTE_SIZE;
	}
	if (nint == 0 && nsys == 0 && next == 0)
		return;
trunc:
	ND_PRINT(" [|igrp]");
}
Esempio n. 4
0
void
msnlb_print(netdissect_options *ndo, const u_char *bp)
{
	const struct msnlb_heartbeat_pkt *hb;

	hb = (const struct msnlb_heartbeat_pkt *)bp;
	ND_TCHECK_SIZE(hb);

	ND_PRINT("MS NLB heartbeat, host priority: %u,",
		EXTRACT_LE_U_4((hb->host_prio)));
	ND_PRINT(" cluster IP: %s,", ipaddr_string(ndo, hb->virtual_ip));
	ND_PRINT(" host IP: %s", ipaddr_string(ndo, hb->host_ip));
	return;
trunc:
	ND_PRINT("[|MS NLB]");
}
Esempio n. 5
0
static int
parsefsinfo(netdissect_options *ndo,
            const uint32_t *dp)
{
	const struct nfsv3_fsinfo *sfp;
	u_int er;

	if (!(dp = parsestatus(ndo, dp, &er)))
		return (0);
	if (ndo->ndo_vflag)
		ND_PRINT(" POST:");
	if (!(dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag)))
		return (0);
	if (er)
		return (1);

	sfp = (const struct nfsv3_fsinfo *)dp;
	ND_TCHECK_SIZE(sfp);
	ND_PRINT(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u",
	       EXTRACT_BE_U_4(&sfp->fs_rtmax),
	       EXTRACT_BE_U_4(&sfp->fs_rtpref),
	       EXTRACT_BE_U_4(&sfp->fs_wtmax),
	       EXTRACT_BE_U_4(&sfp->fs_wtpref),
	       EXTRACT_BE_U_4(&sfp->fs_dtpref));
	if (ndo->ndo_vflag) {
		ND_PRINT(" rtmult %u wtmult %u maxfsz %" PRIu64,
		       EXTRACT_BE_U_4(&sfp->fs_rtmult),
		       EXTRACT_BE_U_4(&sfp->fs_wtmult),
		       EXTRACT_BE_U_8((const uint32_t *)&sfp->fs_maxfilesize));
		ND_PRINT(" delta %u.%06u ",
		       EXTRACT_BE_U_4(&sfp->fs_timedelta.nfsv3_sec),
		       EXTRACT_BE_U_4(&sfp->fs_timedelta.nfsv3_nsec));
	}
	return (1);
trunc:
	return (0);
}
Esempio n. 6
0
static void
slow_oam_print(netdissect_options *ndo,
               const u_char *tptr, u_int tlen)
{
    uint8_t code;
    uint8_t type, length;
    uint8_t state;
    uint8_t command;
    u_int hexdump;

    struct slow_oam_common_header_t {
        nd_uint16_t flags;
        nd_uint8_t code;
    };

    struct slow_oam_tlv_header_t {
        nd_uint8_t type;
        nd_uint8_t length;
    };

    union {
        const struct slow_oam_common_header_t *slow_oam_common_header;
        const struct slow_oam_tlv_header_t *slow_oam_tlv_header;
    } ptr;

    union {
	const struct slow_oam_info_t *slow_oam_info;
        const struct slow_oam_link_event_t *slow_oam_link_event;
        const struct slow_oam_variablerequest_t *slow_oam_variablerequest;
        const struct slow_oam_variableresponse_t *slow_oam_variableresponse;
        const struct slow_oam_loopbackctrl_t *slow_oam_loopbackctrl;
    } tlv;

    ptr.slow_oam_common_header = (const struct slow_oam_common_header_t *)tptr;
    if (tlen < sizeof(*ptr.slow_oam_common_header))
        goto tooshort;
    ND_TCHECK_SIZE(ptr.slow_oam_common_header);
    tptr += sizeof(struct slow_oam_common_header_t);
    tlen -= sizeof(struct slow_oam_common_header_t);

    code = EXTRACT_U_1(ptr.slow_oam_common_header->code);
    ND_PRINT("\n\tCode %s OAM PDU, Flags [%s]",
           tok2str(slow_oam_code_values, "Unknown (%u)", code),
           bittok2str(slow_oam_flag_values,
                      "none",
                      EXTRACT_BE_U_2(ptr.slow_oam_common_header->flags)));

    switch (code) {
    case SLOW_OAM_CODE_INFO:
        while (tlen > 0) {
            ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
            if (tlen < sizeof(*ptr.slow_oam_tlv_header))
                goto tooshort;
            ND_TCHECK_SIZE(ptr.slow_oam_tlv_header);
            type = EXTRACT_U_1(ptr.slow_oam_tlv_header->type);
            length = EXTRACT_U_1(ptr.slow_oam_tlv_header->length);
            ND_PRINT("\n\t  %s Information Type (%u), length %u",
                   tok2str(slow_oam_info_type_values, "Reserved", type),
                   type,
                   length);

            if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
                /*
                 * As IEEE Std 802.3-2015 says for the End of TLV Marker,
                 * "(the length and value of the Type 0x00 TLV can be ignored)".
                 */
                return;
            }

            /* length includes the type and length fields */
            if (length < sizeof(struct slow_oam_tlv_header_t)) {
                ND_PRINT("\n\t    ERROR: illegal length - should be >= %u",
                       (u_int)sizeof(struct slow_oam_tlv_header_t));
                return;
            }

            if (tlen < length)
                goto tooshort;
            ND_TCHECK_LEN(tptr, length);

            hexdump = FALSE;
            switch (type) {
            case SLOW_OAM_INFO_TYPE_LOCAL: /* identical format - fall through */
            case SLOW_OAM_INFO_TYPE_REMOTE:
                tlv.slow_oam_info = (const struct slow_oam_info_t *)tptr;

                if (EXTRACT_U_1(tlv.slow_oam_info->info_length) !=
                    sizeof(struct slow_oam_info_t)) {
                    ND_PRINT("\n\t    ERROR: illegal length - should be %lu",
                           (unsigned long) sizeof(struct slow_oam_info_t));
                    hexdump = TRUE;
                    goto badlength_code_info;
                }

                ND_PRINT("\n\t    OAM-Version %u, Revision %u",
                       EXTRACT_U_1(tlv.slow_oam_info->oam_version),
                       EXTRACT_BE_U_2(tlv.slow_oam_info->revision));

                state = EXTRACT_U_1(tlv.slow_oam_info->state);
                ND_PRINT("\n\t    State-Parser-Action %s, State-MUX-Action %s",
                       tok2str(slow_oam_info_type_state_parser_values, "Reserved",
                               state & OAM_INFO_TYPE_PARSER_MASK),
                       tok2str(slow_oam_info_type_state_mux_values, "Reserved",
                               state & OAM_INFO_TYPE_MUX_MASK));
                ND_PRINT("\n\t    OAM-Config Flags [%s], OAM-PDU-Config max-PDU size %u",
                       bittok2str(slow_oam_info_type_oam_config_values, "none",
                                  EXTRACT_U_1(tlv.slow_oam_info->oam_config)),
                       EXTRACT_BE_U_2(tlv.slow_oam_info->oam_pdu_config) &
                       OAM_INFO_TYPE_PDU_SIZE_MASK);
                ND_PRINT("\n\t    OUI %s (0x%06x), Vendor-Private 0x%08x",
                       tok2str(oui_values, "Unknown",
                               EXTRACT_BE_U_3(tlv.slow_oam_info->oui)),
                       EXTRACT_BE_U_3(tlv.slow_oam_info->oui),
                       EXTRACT_BE_U_4(tlv.slow_oam_info->vendor_private));
                break;

            case SLOW_OAM_INFO_TYPE_ORG_SPECIFIC:
                hexdump = TRUE;
                break;

            default:
                hexdump = TRUE;
                break;
            }

        badlength_code_info:
            /* do we also want to see a hex dump ? */
            if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
                print_unknown_data(ndo, tptr, "\n\t  ",
                                   length);
            }

            tlen -= length;
            tptr += length;
        }
        break;

    case SLOW_OAM_CODE_EVENT_NOTIF:
        /* Sequence number */
        if (tlen < 2)
            goto tooshort;
        ND_TCHECK_2(tptr);
        ND_PRINT("\n\t  Sequence Number %u", EXTRACT_BE_U_2(tptr));
        tlen -= 2;
        tptr += 2;

        /* TLVs */
        while (tlen > 0) {
            ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
            if (tlen < sizeof(*ptr.slow_oam_tlv_header))
                goto tooshort;
            ND_TCHECK_SIZE(ptr.slow_oam_tlv_header);
            type = EXTRACT_U_1(ptr.slow_oam_tlv_header->type);
            length = EXTRACT_U_1(ptr.slow_oam_tlv_header->length);
            ND_PRINT("\n\t  %s Link Event Type (%u), length %u",
                   tok2str(slow_oam_link_event_values, "Reserved",
                           type),
                   type,
                   length);

            if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
                /*
                 * As IEEE Std 802.3-2015 says for the End of TLV Marker,
                 * "(the length and value of the Type 0x00 TLV can be ignored)".
                 */
                return;
            }

            /* length includes the type and length fields */
            if (length < sizeof(struct slow_oam_tlv_header_t)) {
                ND_PRINT("\n\t    ERROR: illegal length - should be >= %u",
                       (u_int)sizeof(struct slow_oam_tlv_header_t));
                return;
            }

            if (tlen < length)
                goto tooshort;
            ND_TCHECK_LEN(tptr, length);

            hexdump = FALSE;
            switch (type) {
            case SLOW_OAM_LINK_EVENT_ERR_SYM_PER: /* identical format - fall through */
            case SLOW_OAM_LINK_EVENT_ERR_FRM:
            case SLOW_OAM_LINK_EVENT_ERR_FRM_PER:
            case SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM:
                tlv.slow_oam_link_event = (const struct slow_oam_link_event_t *)tptr;

                if (EXTRACT_U_1(tlv.slow_oam_link_event->event_length) !=
                    sizeof(struct slow_oam_link_event_t)) {
                    ND_PRINT("\n\t    ERROR: illegal length - should be %lu",
                           (unsigned long) sizeof(struct slow_oam_link_event_t));
                    hexdump = TRUE;
                    goto badlength_event_notif;
                }

                ND_PRINT("\n\t    Timestamp %u ms, Errored Window %" PRIu64
                       "\n\t    Errored Threshold %" PRIu64
                       "\n\t    Errors %" PRIu64
                       "\n\t    Error Running Total %" PRIu64
                       "\n\t    Event Running Total %u",
                       EXTRACT_BE_U_2(tlv.slow_oam_link_event->time_stamp)*100,
                       EXTRACT_BE_U_8(tlv.slow_oam_link_event->window),
                       EXTRACT_BE_U_8(tlv.slow_oam_link_event->threshold),
                       EXTRACT_BE_U_8(tlv.slow_oam_link_event->errors),
                       EXTRACT_BE_U_8(tlv.slow_oam_link_event->errors_running_total),
                       EXTRACT_BE_U_4(tlv.slow_oam_link_event->event_running_total));
                break;

            case SLOW_OAM_LINK_EVENT_ORG_SPECIFIC:
                hexdump = TRUE;
                break;

            default:
                hexdump = TRUE;
                break;
            }

        badlength_event_notif:
            /* do we also want to see a hex dump ? */
            if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
                print_unknown_data(ndo, tptr, "\n\t  ",
                                   length);
            }

            tlen -= length;
            tptr += length;
        }
        break;

    case SLOW_OAM_CODE_LOOPBACK_CTRL:
        tlv.slow_oam_loopbackctrl = (const struct slow_oam_loopbackctrl_t *)tptr;
        if (tlen < sizeof(*tlv.slow_oam_loopbackctrl))
            goto tooshort;
        ND_TCHECK_SIZE(tlv.slow_oam_loopbackctrl);
        command = EXTRACT_U_1(tlv.slow_oam_loopbackctrl->command);
        ND_PRINT("\n\t  Command %s (%u)",
               tok2str(slow_oam_loopbackctrl_cmd_values,
                       "Unknown",
                       command),
               command);
        tptr ++;
        tlen --;
        break;

        /*
         * FIXME those are the defined codes that lack a decoder
         * you are welcome to contribute code ;-)
         */
    case SLOW_OAM_CODE_VAR_REQUEST:
    case SLOW_OAM_CODE_VAR_RESPONSE:
    case SLOW_OAM_CODE_PRIVATE:
    default:
        if (ndo->ndo_vflag <= 1) {
            print_unknown_data(ndo, tptr, "\n\t  ", tlen);
        }
        break;
    }
    return;

tooshort:
    ND_PRINT("\n\t\t packet is too short");
    return;

trunc:
    ND_PRINT("%s", tstr);
}
Esempio n. 7
0
void
lwapp_data_print(netdissect_options *ndo,
                 const u_char *pptr, u_int len)
{
    const struct lwapp_transport_header *lwapp_trans_header;
    const u_char *tptr;
    u_int tlen;
    u_int version;

    tptr=pptr;

    /* check if enough bytes for AP identity */
    ND_TCHECK_6(tptr);
    lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
    ND_TCHECK_SIZE(lwapp_trans_header);
    version = EXTRACT_U_1(lwapp_trans_header->version);

    /*
     * Sanity checking of the header.
     */
    if (LWAPP_EXTRACT_VERSION(version) != LWAPP_VERSION) {
        ND_PRINT("LWAPP version %u packet not supported",
               LWAPP_EXTRACT_VERSION(version));
        return;
    }

    /* non-verbose */
    if (ndo->ndo_vflag < 1) {
        ND_PRINT("LWAPPv%u, %s frame, Flags [%s], length %u",
               LWAPP_EXTRACT_VERSION(version),
               LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
               bittok2str(lwapp_header_bits_values,"none",version&0x07),
               len);
        return;
    }

    /* ok they seem to want to know everything - lets fully decode it */
    tlen=EXTRACT_BE_U_2(lwapp_trans_header->length);
    if (tlen < sizeof(struct lwapp_transport_header)) {
        ND_PRINT("LWAPPv%u, %s frame, Radio-id  %u, Flags [%s], length %u < transport header length",
               LWAPP_EXTRACT_VERSION(version),
               LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
               LWAPP_EXTRACT_RID(version),
               bittok2str(lwapp_header_bits_values,"none",version&0x07),
               tlen);
        return;
    }

    ND_PRINT("LWAPPv%u, %s frame, Radio-id  %u, Flags [%s], Frag-id  %u, length %u",
           LWAPP_EXTRACT_VERSION(version),
           LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
           LWAPP_EXTRACT_RID(version),
           bittok2str(lwapp_header_bits_values,"none",version&0x07),
           EXTRACT_U_1(lwapp_trans_header->frag_id),
           tlen);

    tptr+=sizeof(struct lwapp_transport_header);
    tlen-=sizeof(struct lwapp_transport_header);

    /* FIX - An IEEE 802.11 frame follows - hexdump for now */
    print_unknown_data(ndo, tptr, "\n\t", tlen);

    return;

trunc:
    ND_PRINT("%s", data_tstr);
}
Esempio n. 8
0
void
lwapp_control_print(netdissect_options *ndo,
                    const u_char *pptr, u_int len, int has_ap_ident)
{
    const struct lwapp_transport_header *lwapp_trans_header;
    const struct lwapp_control_header *lwapp_control_header;
    const u_char *tptr;
    uint8_t version;
    u_int tlen;
    u_int msg_type, msg_tlen;

    tptr=pptr;

    if (has_ap_ident) {
        /* check if enough bytes for AP identity */
        ND_TCHECK_6(tptr);
        lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6);
    } else {
        lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
    }
    ND_TCHECK_SIZE(lwapp_trans_header);
    version = EXTRACT_U_1(lwapp_trans_header->version);

    /*
     * Sanity checking of the header.
     */
    if (LWAPP_EXTRACT_VERSION(version) != LWAPP_VERSION) {
	ND_PRINT("LWAPP version %u packet not supported",
               LWAPP_EXTRACT_VERSION(version));
	return;
    }

    /* non-verbose */
    if (ndo->ndo_vflag < 1) {
        ND_PRINT("LWAPPv%u, %s frame, Flags [%s], length %u",
               LWAPP_EXTRACT_VERSION(version),
               LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
               bittok2str(lwapp_header_bits_values,"none",version&0x07),
               len);
        return;
    }

    /* ok they seem to want to know everything - lets fully decode it */
    tlen=EXTRACT_BE_U_2(lwapp_trans_header->length);

    ND_PRINT("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u",
           LWAPP_EXTRACT_VERSION(version),
           LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
           LWAPP_EXTRACT_RID(version),
           bittok2str(lwapp_header_bits_values,"none",version&0x07),
	   EXTRACT_U_1(lwapp_trans_header->frag_id),
	   tlen);

    if (has_ap_ident) {
        ND_PRINT("\n\tAP identity: %s", etheraddr_string(ndo, tptr));
        tptr+=sizeof(struct lwapp_transport_header)+6;
    } else {
        tptr+=sizeof(struct lwapp_transport_header);
    }

    while(tlen!=0) {

        /* did we capture enough for fully decoding the object header ? */
        ND_TCHECK_LEN(tptr, sizeof(struct lwapp_control_header));
        if (tlen < sizeof(struct lwapp_control_header)) {
            ND_PRINT("\n\t  Msg goes past end of PDU");
            break;
        }

        lwapp_control_header = (const struct lwapp_control_header *)tptr;
	msg_tlen = EXTRACT_BE_U_2(lwapp_control_header->len);
        if (tlen < sizeof(struct lwapp_control_header) + msg_tlen) {
            ND_PRINT("\n\t  Msg goes past end of PDU");
            break;
        }

	/* print message header */
	msg_type = EXTRACT_U_1(lwapp_control_header->msg_type);
        ND_PRINT("\n\t  Msg type: %s (%u), Seqnum: %u, Msg len: %u, Session: 0x%08x",
               tok2str(lwapp_msg_type_values,"Unknown",msg_type),
               msg_type,
               EXTRACT_U_1(lwapp_control_header->seq_num),
               msg_tlen,
               EXTRACT_BE_U_4(lwapp_control_header->session_id));

        /* did we capture enough for fully decoding the message */
        ND_TCHECK_LEN(tptr, msg_tlen);

	/* XXX - Decode sub messages for each message */
        switch(msg_type) {
        case LWAPP_MSGTYPE_DISCOVERY_REQUEST:
        case LWAPP_MSGTYPE_DISCOVERY_RESPONSE:
        case LWAPP_MSGTYPE_JOIN_REQUEST:
        case LWAPP_MSGTYPE_JOIN_RESPONSE:
        case LWAPP_MSGTYPE_JOIN_ACK:
        case LWAPP_MSGTYPE_JOIN_CONFIRM:
        case LWAPP_MSGTYPE_CONFIGURE_REQUEST:
        case LWAPP_MSGTYPE_CONFIGURE_RESPONSE:
        case LWAPP_MSGTYPE_CONF_UPDATE_REQUEST:
        case LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE:
        case LWAPP_MSGTYPE_WTP_EVENT_REQUEST:
        case LWAPP_MSGTYPE_WTP_EVENT_RESPONSE:
        case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST:
        case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE:
        case LWAPP_MSGTYPE_ECHO_REQUEST:
        case LWAPP_MSGTYPE_ECHO_RESPONSE:
        case LWAPP_MSGTYPE_IMAGE_DATA_REQUEST:
        case LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE:
        case LWAPP_MSGTYPE_RESET_REQUEST:
        case LWAPP_MSGTYPE_RESET_RESPONSE:
        case LWAPP_MSGTYPE_KEY_UPDATE_REQUEST:
        case LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE:
        case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST:
        case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE:
        case LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST:
        case LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE:
        case LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION:
        case LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST:
        case LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE:
        case LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST:
        case LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE:
        default:
            break;
        }

        tptr += sizeof(struct lwapp_control_header) + msg_tlen;
        tlen -= sizeof(struct lwapp_control_header) + msg_tlen;
    }
    return;

trunc:
    ND_PRINT("%s", control_tstr);
}
Esempio n. 9
0
/**
 * dccp_print - show dccp packet
 * @bp - beginning of dccp packet
 * @data2 - beginning of enclosing
 * @len - length of ip packet
 */
void
dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2,
	   u_int len)
{
	const struct dccp_hdr *dh;
	const struct ip *ip;
	const struct ip6_hdr *ip6;
	const u_char *cp;
	u_short sport, dport;
	u_int hlen;
	u_int fixed_hdrlen;
	uint8_t	dccph_type;

	ndo->ndo_protocol = "dccp";
	dh = (const struct dccp_hdr *)bp;

	ip = (const struct ip *)data2;
	if (IP_V(ip) == 6)
		ip6 = (const struct ip6_hdr *)data2;
	else
		ip6 = NULL;

	/* make sure we have enough data to look at the X bit */
	cp = (const u_char *)(dh + 1);
	if (cp > ndo->ndo_snapend)
		goto trunc;
	if (len < sizeof(struct dccp_hdr)) {
		ND_PRINT("truncated-dccp - %u bytes missing!",
			 (u_int)sizeof(struct dccp_hdr) - len);
		return;
	}

	/* get the length of the generic header */
	fixed_hdrlen = dccp_basic_hdr_len(ndo, dh);
	if (len < fixed_hdrlen) {
		ND_PRINT("truncated-dccp - %u bytes missing!",
			  fixed_hdrlen - len);
		return;
	}
	ND_TCHECK_LEN(dh, fixed_hdrlen);

	sport = GET_BE_U_2(dh->dccph_sport);
	dport = GET_BE_U_2(dh->dccph_dport);
	hlen = GET_U_1(dh->dccph_doff) * 4;

	if (ip6) {
		ND_PRINT("%s.%u > %s.%u: ",
			  ip6addr_string(ndo, ip6->ip6_src), sport,
			  ip6addr_string(ndo, ip6->ip6_dst), dport);
	} else {
		ND_PRINT("%s.%u > %s.%u: ",
			  ipaddr_string(ndo, ip->ip_src), sport,
			  ipaddr_string(ndo, ip->ip_dst), dport);
	}

	ND_PRINT("DCCP");

	if (ndo->ndo_qflag) {
		ND_PRINT(" %u", len - hlen);
		if (hlen > len) {
			ND_PRINT(" [bad hdr length %u - too long, > %u]",
				  hlen, len);
		}
		return;
	}

	/* other variables in generic header */
	if (ndo->ndo_vflag) {
		ND_PRINT(" (CCVal %u, CsCov %u, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh));
	}

	/* checksum calculation */
	if (ndo->ndo_vflag && ND_TTEST_LEN(bp, len)) {
		uint16_t sum = 0, dccp_sum;

		dccp_sum = GET_BE_U_2(dh->dccph_checksum);
		ND_PRINT("cksum 0x%04x ", dccp_sum);
		if (IP_V(ip) == 4)
			sum = dccp_cksum(ndo, ip, dh, len);
		else if (IP_V(ip) == 6)
			sum = dccp6_cksum(ndo, ip6, dh, len);
		if (sum != 0)
			ND_PRINT("(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum));
		else
			ND_PRINT("(correct)");
	}

	if (ndo->ndo_vflag)
		ND_PRINT(")");
	ND_PRINT(" ");

	dccph_type = DCCPH_TYPE(dh);
	switch (dccph_type) {
	case DCCP_PKT_REQUEST: {
		const struct dccp_hdr_request *dhr =
			(const struct dccp_hdr_request *)(bp + fixed_hdrlen);
		fixed_hdrlen += 4;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_TCHECK_SIZE(dhr);
		ND_PRINT("%s (service=%u) ",
			  tok2str(dccp_pkt_type_str, "", dccph_type),
			  GET_BE_U_4(dhr->dccph_req_service));
		break;
	}
	case DCCP_PKT_RESPONSE: {
		const struct dccp_hdr_response *dhr =
			(const struct dccp_hdr_response *)(bp + fixed_hdrlen);
		fixed_hdrlen += 12;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_TCHECK_SIZE(dhr);
		ND_PRINT("%s (service=%u) ",
			  tok2str(dccp_pkt_type_str, "", dccph_type),
			  GET_BE_U_4(dhr->dccph_resp_service));
		break;
	}
	case DCCP_PKT_DATA:
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_ACK: {
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	}
	case DCCP_PKT_DATAACK: {
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	}
	case DCCP_PKT_CLOSEREQ:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_CLOSE:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_RESET: {
		const struct dccp_hdr_reset *dhr =
			(const struct dccp_hdr_reset *)(bp + fixed_hdrlen);
		fixed_hdrlen += 12;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_TCHECK_SIZE(dhr);
		ND_PRINT("%s (code=%s) ",
			  tok2str(dccp_pkt_type_str, "", dccph_type),
			  dccp_reset_code(GET_U_1(dhr->dccph_reset_code)));
		break;
	}
	case DCCP_PKT_SYNC:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	case DCCP_PKT_SYNCACK:
		fixed_hdrlen += 8;
		if (len < fixed_hdrlen) {
			ND_PRINT("truncated-%s - %u bytes missing!",
				  tok2str(dccp_pkt_type_str, "", dccph_type),
				  fixed_hdrlen - len);
			return;
		}
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
		break;
	default:
		ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type));
		break;
	}

	if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) &&
			(DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
		dccp_print_ack_no(ndo, bp);

	if (ndo->ndo_vflag < 2)
		return;

	ND_PRINT("seq %" PRIu64, dccp_seqno(ndo, bp));

	/* process options */
	if (hlen > fixed_hdrlen){
		u_int optlen;
		cp = bp + fixed_hdrlen;
		ND_PRINT(" <");

		hlen -= fixed_hdrlen;
		while(1){
			optlen = dccp_print_option(ndo, cp, hlen);
			if (!optlen)
				break;
			if (hlen <= optlen)
				break;
			hlen -= optlen;
			cp += optlen;
			ND_PRINT(", ");
		}
		ND_PRINT(">");
	}
	return;
trunc:
	nd_print_trunc(ndo);
	return;
}
Esempio n. 10
0
u_int
nflog_if_print(netdissect_options *ndo,
			   const struct pcap_pkthdr *h, const u_char *p)
{
	const nflog_hdr_t *hdr = (const nflog_hdr_t *)p;
	uint16_t size;
	uint16_t h_size = sizeof(nflog_hdr_t);
	u_int caplen = h->caplen;
	u_int length = h->len;

	if (caplen < sizeof(nflog_hdr_t) || length < sizeof(nflog_hdr_t))
		goto trunc;

	ND_TCHECK_SIZE(hdr);
	if (hdr->nflog_version != 0) {
		ND_PRINT("version %u (unknown)", hdr->nflog_version);
		return h_size;
	}

	if (ndo->ndo_eflag)
		nflog_hdr_print(ndo, hdr, length);

	p += sizeof(nflog_hdr_t);
	length -= sizeof(nflog_hdr_t);
	caplen -= sizeof(nflog_hdr_t);

	while (length > 0) {
		const nflog_tlv_t *tlv;

		/* We have some data.  Do we have enough for the TLV header? */
		if (caplen < sizeof(nflog_tlv_t) || length < sizeof(nflog_tlv_t))
			goto trunc;	/* No. */

		tlv = (const nflog_tlv_t *) p;
		ND_TCHECK_SIZE(tlv);
		size = tlv->tlv_length;
		if (size % 4 != 0)
			size += 4 - size % 4;

		/* Is the TLV's length less than the minimum? */
		if (size < sizeof(nflog_tlv_t))
			goto trunc;	/* Yes. Give up now. */

		/* Do we have enough data for the full TLV? */
		if (caplen < size || length < size)
			goto trunc;	/* No. */

		if (tlv->tlv_type == NFULA_PAYLOAD) {
			/*
			 * This TLV's data is the packet payload.
			 * Skip past the TLV header, and break out
			 * of the loop so we print the packet data.
			 */
			p += sizeof(nflog_tlv_t);
			h_size += sizeof(nflog_tlv_t);
			length -= sizeof(nflog_tlv_t);
			caplen -= sizeof(nflog_tlv_t);
			break;
		}

		p += size;
		h_size += size;
		length -= size;
		caplen -= size;
	}

	switch (hdr->nflog_family) {

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

#ifdef AF_INET6
	case AF_INET6:
		ip6_print(ndo, p, length);
		break;
#endif /* AF_INET6 */

	default:
		if (!ndo->ndo_eflag)
			nflog_hdr_print(ndo, hdr,
				length + sizeof(nflog_hdr_t));

		if (!ndo->ndo_suppress_default_print)
			ND_DEFAULTPRINT(p, caplen);
		break;
	}

	return h_size;
trunc:
	ND_PRINT("%s", tstr);
	return h_size;
}
Esempio n. 11
0
void
tcp_print(netdissect_options *ndo,
          const u_char *bp, u_int length,
          const u_char *bp2, int fragmented)
{
        const struct tcphdr *tp;
        const struct ip *ip;
        u_char flags;
        u_int hlen;
        char ch;
        uint16_t sport, dport, win, urp;
        uint32_t seq, ack, thseq, thack;
        u_int utoval;
        uint16_t magic;
        int rev;
        const struct ip6_hdr *ip6;

        ndo->ndo_protocol = "tcp";
        tp = (const struct tcphdr *)bp;
        ip = (const struct ip *)bp2;
        if (IP_V(ip) == 6)
                ip6 = (const struct ip6_hdr *)bp2;
        else
                ip6 = NULL;
        ch = '\0';
        if (!ND_TTEST_2(tp->th_dport)) {
                if (ip6) {
                        ND_PRINT("%s > %s:",
                                 ip6addr_string(ndo, ip6->ip6_src),
                                 ip6addr_string(ndo, ip6->ip6_dst));
                } else {
                        ND_PRINT("%s > %s:",
                                 ipaddr_string(ndo, ip->ip_src),
                                 ipaddr_string(ndo, ip->ip_dst));
                }
                nd_print_trunc(ndo);
                return;
        }

        sport = GET_BE_U_2(tp->th_sport);
        dport = GET_BE_U_2(tp->th_dport);

        if (ip6) {
                if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) {
                        ND_PRINT("%s.%s > %s.%s: ",
                                 ip6addr_string(ndo, ip6->ip6_src),
                                 tcpport_string(ndo, sport),
                                 ip6addr_string(ndo, ip6->ip6_dst),
                                 tcpport_string(ndo, dport));
                } else {
                        ND_PRINT("%s > %s: ",
                                 tcpport_string(ndo, sport), tcpport_string(ndo, dport));
                }
        } else {
                if (GET_U_1(ip->ip_p) == IPPROTO_TCP) {
                        ND_PRINT("%s.%s > %s.%s: ",
                                 ipaddr_string(ndo, ip->ip_src),
                                 tcpport_string(ndo, sport),
                                 ipaddr_string(ndo, ip->ip_dst),
                                 tcpport_string(ndo, dport));
                } else {
                        ND_PRINT("%s > %s: ",
                                 tcpport_string(ndo, sport), tcpport_string(ndo, dport));
                }
        }

        ND_TCHECK_SIZE(tp);

        hlen = TH_OFF(tp) * 4;

        if (hlen < sizeof(*tp)) {
                ND_PRINT(" tcp %u [bad hdr length %u - too short, < %lu]",
                         length - hlen, hlen, (unsigned long)sizeof(*tp));
                return;
        }

        seq = GET_BE_U_4(tp->th_seq);
        ack = GET_BE_U_4(tp->th_ack);
        win = GET_BE_U_2(tp->th_win);
        urp = GET_BE_U_2(tp->th_urp);

        if (ndo->ndo_qflag) {
                ND_PRINT("tcp %u", length - hlen);
                if (hlen > length) {
                        ND_PRINT(" [bad hdr length %u - too long, > %u]",
                                 hlen, length);
                }
                return;
        }

        flags = GET_U_1(tp->th_flags);
        ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));

        if (!ndo->ndo_Sflag && (flags & TH_ACK)) {
                /*
                 * Find (or record) the initial sequence numbers for
                 * this conversation.  (we pick an arbitrary
                 * collating order so there's only one entry for
                 * both directions).
                 */
                rev = 0;
                if (ip6) {
                        struct tcp_seq_hash6 *th;
                        struct tcp_seq_hash6 *tcp_seq_hash;
                        const void *src, *dst;
                        struct tha6 tha;

                        tcp_seq_hash = tcp_seq_hash6;
                        src = (const void *)ip6->ip6_src;
                        dst = (const void *)ip6->ip6_dst;
                        if (sport > dport)
                                rev = 1;
                        else if (sport == dport) {
                                if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0)
                                        rev = 1;
                        }
                        if (rev) {
                                UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst));
                                UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src));
                                tha.port = ((u_int)dport) << 16 | sport;
                        } else {
                                UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst));
                                UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src));
                                tha.port = ((u_int)sport) << 16 | dport;
                        }

                        for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
                             th->nxt; th = th->nxt)
                                if (memcmp((char *)&tha, (char *)&th->addr,
                                           sizeof(th->addr)) == 0)
                                        break;

                        if (!th->nxt || (flags & TH_SYN)) {
                                /* didn't find it or new conversation */
                                /* calloc() return used by the 'tcp_seq_hash6'
                                   hash table: do not free() */
                                if (th->nxt == NULL) {
                                        th->nxt = (struct tcp_seq_hash6 *)
                                                calloc(1, sizeof(*th));
                                        if (th->nxt == NULL)
                                                (*ndo->ndo_error)(ndo,
                                                        S_ERR_ND_MEM_ALLOC,
                                                        "tcp_print: calloc");
                                }
                                th->addr = tha;
                                if (rev)
                                        th->ack = seq, th->seq = ack - 1;
                                else
                                        th->seq = seq, th->ack = ack - 1;
                        } else {
                                if (rev)
                                        seq -= th->ack, ack -= th->seq;
                                else
                                        seq -= th->seq, ack -= th->ack;
                        }

                        thseq = th->seq;
                        thack = th->ack;
                } else {
                        struct tcp_seq_hash *th;
                        struct tcp_seq_hash *tcp_seq_hash;
                        struct tha tha;

                        tcp_seq_hash = tcp_seq_hash4;
                        if (sport > dport)
                                rev = 1;
                        else if (sport == dport) {
                                if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0)
                                        rev = 1;
                        }
                        if (rev) {
                                UNALIGNED_MEMCPY(&tha.src, ip->ip_dst,
                                                 sizeof(ip->ip_dst));
                                UNALIGNED_MEMCPY(&tha.dst, ip->ip_src,
                                                 sizeof(ip->ip_src));
                                tha.port = ((u_int)dport) << 16 | sport;
                        } else {
                                UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst,
                                                 sizeof(ip->ip_dst));
                                UNALIGNED_MEMCPY(&tha.src, ip->ip_src,
                                                 sizeof(ip->ip_src));
                                tha.port = ((u_int)sport) << 16 | dport;
                        }

                        for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
                             th->nxt; th = th->nxt)
                                if (memcmp((char *)&tha, (char *)&th->addr,
                                           sizeof(th->addr)) == 0)
                                        break;

                        if (!th->nxt || (flags & TH_SYN)) {
                                /* didn't find it or new conversation */
                                /* calloc() return used by the 'tcp_seq_hash4'
                                   hash table: do not free() */
                                if (th->nxt == NULL) {
                                        th->nxt = (struct tcp_seq_hash *)
                                                calloc(1, sizeof(*th));
                                        if (th->nxt == NULL)
                                                (*ndo->ndo_error)(ndo,
                                                        S_ERR_ND_MEM_ALLOC,
                                                        "tcp_print: calloc");
                                }
                                th->addr = tha;
                                if (rev)
                                        th->ack = seq, th->seq = ack - 1;
                                else
                                        th->seq = seq, th->ack = ack - 1;
                        } else {
                                if (rev)
                                        seq -= th->ack, ack -= th->seq;
                                else
                                        seq -= th->seq, ack -= th->ack;
                        }

                        thseq = th->seq;
                        thack = th->ack;
                }
        } else {
                /*fool gcc*/
                thseq = thack = rev = 0;
        }
        if (hlen > length) {
                ND_PRINT(" [bad hdr length %u - too long, > %u]",
                         hlen, length);
                return;
        }

        if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) {
                /* Check the checksum, if possible. */
                uint16_t sum, tcp_sum;

                if (IP_V(ip) == 4) {
                        if (ND_TTEST_LEN(tp->th_sport, length)) {
                                sum = tcp_cksum(ndo, ip, tp, length);
                                tcp_sum = GET_BE_U_2(tp->th_sum);

                                ND_PRINT(", cksum 0x%04x", tcp_sum);
                                if (sum != 0)
                                        ND_PRINT(" (incorrect -> 0x%04x)",
                                            in_cksum_shouldbe(tcp_sum, sum));
                                else
                                        ND_PRINT(" (correct)");
                        }
                } else if (IP_V(ip) == 6 && ip6->ip6_plen) {
                        if (ND_TTEST_LEN(tp->th_sport, length)) {
                                sum = tcp6_cksum(ndo, ip6, tp, length);
                                tcp_sum = GET_BE_U_2(tp->th_sum);

                                ND_PRINT(", cksum 0x%04x", tcp_sum);
                                if (sum != 0)
                                        ND_PRINT(" (incorrect -> 0x%04x)",
                                            in_cksum_shouldbe(tcp_sum, sum));
                                else
                                        ND_PRINT(" (correct)");

                        }
                }
        }

        length -= hlen;
        if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) {
                ND_PRINT(", seq %u", seq);

                if (length > 0) {
                        ND_PRINT(":%u", seq + length);
                }
        }

        if (flags & TH_ACK) {
                ND_PRINT(", ack %u", ack);
        }

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

        if (flags & TH_URG)
                ND_PRINT(", urg %u", urp);
        /*
         * Handle any options.
         */
        if (hlen > sizeof(*tp)) {
                const u_char *cp;
                u_int i, opt, datalen;
                u_int len;

                hlen -= sizeof(*tp);
                cp = (const u_char *)tp + sizeof(*tp);
                ND_PRINT(", options [");
                while (hlen > 0) {
                        if (ch != '\0')
                                ND_PRINT("%c", ch);
                        ND_TCHECK_1(cp);
                        opt = GET_U_1(cp);
                        cp++;
                        if (ZEROLENOPT(opt))
                                len = 1;
                        else {
                                ND_TCHECK_1(cp);
                                len = GET_U_1(cp);
                                cp++;	/* total including type, len */
                                if (len < 2 || len > hlen)
                                        goto bad;
                                --hlen;		/* account for length byte */
                        }
                        --hlen;			/* account for type byte */
                        datalen = 0;

/* Bail if "l" bytes of data are not left or were not captured  */
#define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); }


                        ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt));

                        switch (opt) {

                        case TCPOPT_MAXSEG:
                                datalen = 2;
                                LENCHECK(datalen);
                                ND_PRINT(" %u", GET_BE_U_2(cp));
                                break;

                        case TCPOPT_WSCALE:
                                datalen = 1;
                                LENCHECK(datalen);
                                ND_PRINT(" %u", GET_U_1(cp));
                                break;

                        case TCPOPT_SACK:
                                datalen = len - 2;
                                if (datalen % 8 != 0) {
                                        ND_PRINT(" invalid sack");
                                } else {
                                        uint32_t s, e;

                                        ND_PRINT(" %u ", datalen / 8);
                                        for (i = 0; i < datalen; i += 8) {
                                                LENCHECK(i + 4);
                                                s = GET_BE_U_4(cp + i);
                                                LENCHECK(i + 8);
                                                e = GET_BE_U_4(cp + i + 4);
                                                if (rev) {
                                                        s -= thseq;
                                                        e -= thseq;
                                                } else {
                                                        s -= thack;
                                                        e -= thack;
                                                }
                                                ND_PRINT("{%u:%u}", s, e);
                                        }
                                }
                                break;

                        case TCPOPT_CC:
                        case TCPOPT_CCNEW:
                        case TCPOPT_CCECHO:
                        case TCPOPT_ECHO:
                        case TCPOPT_ECHOREPLY:

                                /*
                                 * those options share their semantics.
                                 * fall through
                                 */
                                datalen = 4;
                                LENCHECK(datalen);
                                ND_PRINT(" %u", GET_BE_U_4(cp));
                                break;

                        case TCPOPT_TIMESTAMP:
                                datalen = 8;
                                LENCHECK(datalen);
                                ND_PRINT(" val %u ecr %u",
                                             GET_BE_U_4(cp),
                                             GET_BE_U_4(cp + 4));
                                break;

                        case TCPOPT_SIGNATURE:
                                datalen = TCP_SIGLEN;
                                LENCHECK(datalen);
                                ND_PRINT(" ");
#ifdef HAVE_LIBCRYPTO
                                switch (tcp_verify_signature(ndo, ip, tp,
                                                             bp + TH_OFF(tp) * 4, length, cp)) {

                                case SIGNATURE_VALID:
                                        ND_PRINT("valid");
                                        break;

                                case SIGNATURE_INVALID:
                                        nd_print_invalid(ndo);
                                        break;

                                case CANT_CHECK_SIGNATURE:
                                        ND_PRINT("can't check - ");
                                        for (i = 0; i < TCP_SIGLEN; ++i)
                                                ND_PRINT("%02x",
                                                         GET_U_1(cp + i));
                                        break;
                                }
#else
                                for (i = 0; i < TCP_SIGLEN; ++i)
                                        ND_PRINT("%02x", GET_U_1(cp + i));
#endif
                                break;

                        case TCPOPT_SCPS:
                                datalen = 2;
                                LENCHECK(datalen);
                                ND_PRINT(" cap %02x id %u", GET_U_1(cp),
                                         GET_U_1(cp + 1));
                                break;

                        case TCPOPT_TCPAO:
                                datalen = len - 2;
                                /* RFC 5925 Section 2.2:
                                 * "The Length value MUST be greater than or equal to 4."
                                 * (This includes the Kind and Length fields already processed
                                 * at this point.)
                                 */
                                if (datalen < 2) {
                                        nd_print_invalid(ndo);
                                } else {
                                        LENCHECK(1);
                                        ND_PRINT(" keyid %u", GET_U_1(cp));
                                        LENCHECK(2);
                                        ND_PRINT(" rnextkeyid %u",
                                                 GET_U_1(cp + 1));
                                        if (datalen > 2) {
                                                ND_PRINT(" mac 0x");
                                                for (i = 2; i < datalen; i++) {
                                                        LENCHECK(i + 1);
                                                        ND_PRINT("%02x",
                                                                 GET_U_1(cp + i));
                                                }
                                        }
                                }
                                break;

                        case TCPOPT_EOL:
                        case TCPOPT_NOP:
                        case TCPOPT_SACKOK:
                                /*
                                 * Nothing interesting.
                                 * fall through
                                 */
                                break;

                        case TCPOPT_UTO:
                                datalen = 2;
                                LENCHECK(datalen);
                                utoval = GET_BE_U_2(cp);
                                ND_PRINT(" 0x%x", utoval);
                                if (utoval & 0x0001)
                                        utoval = (utoval >> 1) * 60;
                                else
                                        utoval >>= 1;
                                ND_PRINT(" %u", utoval);
                                break;

                        case TCPOPT_MPTCP:
                                datalen = len - 2;
                                LENCHECK(datalen);
                                if (!mptcp_print(ndo, cp-2, len, flags))
                                        goto bad;
                                break;

                        case TCPOPT_FASTOPEN:
                                datalen = len - 2;
                                LENCHECK(datalen);
                                ND_PRINT(" ");
                                print_tcp_fastopen_option(ndo, cp, datalen, FALSE);
                                break;

                        case TCPOPT_EXPERIMENT2:
                                datalen = len - 2;
                                LENCHECK(datalen);
                                if (datalen < 2)
                                        goto bad;
                                /* RFC6994 */
                                magic = GET_BE_U_2(cp);
                                ND_PRINT("-");

                                switch(magic) {

                                case 0xf989: /* TCP Fast Open RFC 7413 */
                                        print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE);
                                        break;

                                default:
                                        /* Unknown magic number */
                                        ND_PRINT("%04x", magic);
                                        break;
                                }
                                break;

                        default:
                                datalen = len - 2;
                                if (datalen)
                                        ND_PRINT(" 0x");
                                for (i = 0; i < datalen; ++i) {
                                        LENCHECK(i + 1);
                                        ND_PRINT("%02x", GET_U_1(cp + i));
                                }
                                break;
                        }

                        /* Account for data printed */
                        cp += datalen;
                        hlen -= datalen;

                        /* Check specification against observed length */
                        ++datalen;		/* option octet */
                        if (!ZEROLENOPT(opt))
                                ++datalen;	/* size octet */
                        if (datalen != len)
                                ND_PRINT("[len %u]", len);
                        ch = ',';
                        if (opt == TCPOPT_EOL)
                                break;
                }
                ND_PRINT("]");
        }
Esempio n. 12
0
static int
ldp_pdu_print(netdissect_options *ndo,
              const u_char *pptr)
{
    const struct ldp_common_header *ldp_com_header;
    const struct ldp_msg_header *ldp_msg_header;
    const u_char *tptr,*msg_tptr;
    u_short tlen;
    u_short pdu_len,msg_len,msg_type,msg_tlen;
    int hexdump,processed;

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

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

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

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

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

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

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

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

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

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

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

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

        switch(msg_type) {

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

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

        case LDP_MSG_LABEL_REQUEST:
        case LDP_MSG_LABEL_RELEASE:
        case LDP_MSG_LABEL_ABORT_REQUEST:

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

        tptr += msg_len+4;
        tlen -= msg_len+4;
    }
    return pdu_len+4;
trunc:
    ND_PRINT("\n\t\t packet exceeded snapshot");
    return 0;
}
Esempio n. 13
0
void
bfd_print(netdissect_options *ndo, const u_char *pptr,
          u_int len, u_int port)
{
	ndo->ndo_protocol = "bfd";
        if (port == BFD_CONTROL_PORT ||
            port == BFD_MULTIHOP_PORT ||
            port == BFD_LAG_PORT) {
            /*
             * Control packet.
             */
            const struct bfd_header_t *bfd_header;
            uint8_t version_diag;
            uint8_t version = 0;
            uint8_t flags;

            bfd_header = (const struct bfd_header_t *)pptr;
            ND_TCHECK_SIZE(bfd_header);
            version_diag = GET_U_1(bfd_header->version_diag);
            version = BFD_EXTRACT_VERSION(version_diag);
            flags = GET_U_1(bfd_header->flags);

            switch (version) {

                /* BFDv0 */
            case 0:
                if (ndo->ndo_vflag < 1)
                {
                    ND_PRINT("BFDv0, Control, Flags: [%s], length: %u",
                           bittok2str(bfd_v0_flag_values, "none", flags),
                           len);
                    return;
                }

                ND_PRINT("BFDv0, length: %u\n\tControl, Flags: [%s], Diagnostic: %s (0x%02x)",
                       len,
                       bittok2str(bfd_v0_flag_values, "none", flags),
                       tok2str(bfd_diag_values,"unknown",BFD_EXTRACT_DIAG(version_diag)),
                       BFD_EXTRACT_DIAG(version_diag));

                ND_PRINT("\n\tDetection Timer Multiplier: %u (%u ms Detection time), BFD Length: %u",
                       GET_U_1(bfd_header->detect_time_multiplier),
                       GET_U_1(bfd_header->detect_time_multiplier) * GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000,
                       GET_U_1(bfd_header->length));


                ND_PRINT("\n\tMy Discriminator: 0x%08x",
                         GET_BE_U_4(bfd_header->my_discriminator));
                ND_PRINT(", Your Discriminator: 0x%08x",
                         GET_BE_U_4(bfd_header->your_discriminator));
                ND_PRINT("\n\t  Desired min Tx Interval:    %4u ms",
                         GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000);
                ND_PRINT("\n\t  Required min Rx Interval:   %4u ms",
                         GET_BE_U_4(bfd_header->required_min_rx_interval)/1000);
                ND_PRINT("\n\t  Required min Echo Interval: %4u ms",
                         GET_BE_U_4(bfd_header->required_min_echo_interval)/1000);

                if (flags & BFD_FLAG_AUTH) {
                    if (auth_print(ndo, pptr))
                        goto trunc;
                }
                break;

                /* BFDv1 */
            case 1:
                if (ndo->ndo_vflag < 1)
                {
                    ND_PRINT("BFDv1, %s, State %s, Flags: [%s], length: %u",
                           tok2str(bfd_port_values, "unknown (%u)", port),
                           tok2str(bfd_v1_state_values, "unknown (%u)", (flags & 0xc0) >> 6),
                           bittok2str(bfd_v1_flag_values, "none", flags & 0x3f),
                           len);
                    return;
                }

                ND_PRINT("BFDv1, length: %u\n\t%s, State %s, Flags: [%s], Diagnostic: %s (0x%02x)",
                       len,
                       tok2str(bfd_port_values, "unknown (%u)", port),
                       tok2str(bfd_v1_state_values, "unknown (%u)", (flags & 0xc0) >> 6),
                       bittok2str(bfd_v1_flag_values, "none", flags & 0x3f),
                       tok2str(bfd_diag_values,"unknown",BFD_EXTRACT_DIAG(version_diag)),
                       BFD_EXTRACT_DIAG(version_diag));

                ND_PRINT("\n\tDetection Timer Multiplier: %u (%u ms Detection time), BFD Length: %u",
                       GET_U_1(bfd_header->detect_time_multiplier),
                       GET_U_1(bfd_header->detect_time_multiplier) * GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000,
                       GET_U_1(bfd_header->length));


                ND_PRINT("\n\tMy Discriminator: 0x%08x",
                         GET_BE_U_4(bfd_header->my_discriminator));
                ND_PRINT(", Your Discriminator: 0x%08x",
                         GET_BE_U_4(bfd_header->your_discriminator));
                ND_PRINT("\n\t  Desired min Tx Interval:    %4u ms",
                         GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000);
                ND_PRINT("\n\t  Required min Rx Interval:   %4u ms",
                         GET_BE_U_4(bfd_header->required_min_rx_interval)/1000);
                ND_PRINT("\n\t  Required min Echo Interval: %4u ms",
                         GET_BE_U_4(bfd_header->required_min_echo_interval)/1000);

                if (flags & BFD_FLAG_AUTH) {
                    if (auth_print(ndo, pptr))
                        goto trunc;
                }
                break;

            default:
                ND_PRINT("BFDv%u, Control, length: %u",
                       version,
                       len);
                if (ndo->ndo_vflag >= 1) {
                    if(!print_unknown_data(ndo, pptr,"\n\t",len))
                        return;
                }
                break;
            }
        } else if (port == BFD_ECHO_PORT) {
Esempio n. 14
0
static int
auth_print(netdissect_options *ndo, const u_char *pptr)
{
        const struct bfd_auth_header_t *bfd_auth_header;
        uint8_t auth_type, auth_len;
        int i;

        pptr += sizeof (struct bfd_header_t);
        bfd_auth_header = (const struct bfd_auth_header_t *)pptr;
        ND_TCHECK_SIZE(bfd_auth_header);
        auth_type = GET_U_1(bfd_auth_header->auth_type);
        auth_len = GET_U_1(bfd_auth_header->auth_len);
        ND_PRINT("\n\tAuthentication: %s (%u), length: %u",
                 tok2str(bfd_v1_authentication_values,"Unknown",auth_type),
                 auth_type, auth_len);
                pptr += 2;
                ND_PRINT("\n\t  Auth Key ID: %u", GET_U_1(pptr));

        switch(auth_type) {
            case AUTH_PASSWORD:
/*
 *    Simple Password Authentication Section Format
 *
 *     0                   1                   2                   3
 *     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
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |   Auth Type   |   Auth Len    |  Auth Key ID  |  Password...  |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                              ...                              |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
                if (auth_len < AUTH_PASSWORD_FIELD_MIN_LEN ||
                    auth_len > AUTH_PASSWORD_FIELD_MAX_LEN) {
                    ND_PRINT("[invalid length %u]",
                             auth_len);
                    break;
                }
                pptr++;
                ND_PRINT(", Password: "******"[invalid length %u]",
                             auth_len);
                    break;
                }
                pptr += 2;
                ND_TCHECK_4(pptr);
                ND_PRINT(", Sequence Number: 0x%08x", GET_BE_U_4(pptr));
                pptr += 4;
                ND_TCHECK_LEN(pptr, AUTH_MD5_HASH_LEN);
                ND_PRINT("\n\t  Digest: ");
                for(i = 0; i < AUTH_MD5_HASH_LEN; i++)
                    ND_PRINT("%02x", GET_U_1(pptr + i));
                break;
            case AUTH_SHA1:
            case AUTH_MET_SHA1:
/*
 *    Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section Format
 *
 *     0                   1                   2                   3
 *     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
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |   Auth Type   |   Auth Len    |  Auth Key ID  |   Reserved    |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                        Sequence Number                        |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                       Auth Key/Hash...                        |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                              ...                              |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
                if (auth_len != AUTH_SHA1_FIELD_LEN) {
                    ND_PRINT("[invalid length %u]",
                             auth_len);
                    break;
                }
                pptr += 2;
                ND_TCHECK_4(pptr);
                ND_PRINT(", Sequence Number: 0x%08x", GET_BE_U_4(pptr));
                pptr += 4;
                ND_TCHECK_LEN(pptr, AUTH_SHA1_HASH_LEN);
                ND_PRINT("\n\t  Hash: ");
                for(i = 0; i < AUTH_SHA1_HASH_LEN; i++)
                    ND_PRINT("%02x", GET_U_1(pptr + i));
                break;
        }
        return 0;

trunc:
        return 1;
}
Esempio n. 15
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);
}
Esempio n. 16
0
static void
radius_attrs_print(netdissect_options *ndo,
                   const u_char *attr, u_int length)
{
   const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
   const char *attr_string;
   uint8_t type, len;

   while (length > 0)
   {
     if (length < 2)
        goto trunc;
     ND_TCHECK_SIZE(rad_attr);

     type = EXTRACT_U_1(rad_attr->type);
     len = EXTRACT_U_1(rad_attr->len);
     if (type != 0 && type < TAM_SIZE(attr_type))
	attr_string = attr_type[type].name;
     else
	attr_string = "Unknown";
     if (len < 2)
     {
	ND_PRINT("\n\t  %s Attribute (%u), length: %u (bogus, must be >= 2)",
               attr_string,
               type,
               len);
	return;
     }
     if (len > length)
     {
	ND_PRINT("\n\t  %s Attribute (%u), length: %u (bogus, goes past end of packet)",
               attr_string,
               type,
               len);
        return;
     }
     ND_PRINT("\n\t  %s Attribute (%u), length: %u, Value: ",
            attr_string,
            type,
            len);

     if (type < TAM_SIZE(attr_type))
     {
         if (len > 2)
         {
             if ( attr_type[type].print_func )
                 (*attr_type[type].print_func)(
                     ndo, ((const u_char *)(rad_attr+1)),
                     len - 2, type);
         }
     }
     /* do we also want to see a hex dump ? */
     if (ndo->ndo_vflag> 1)
         print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t    ", (len)-2);

     length-=(len);
     rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+len);
   }
   return;

trunc:
   nd_print_trunc(ndo);
}
Esempio n. 17
0
u_int
pflog_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
               const u_char *p)
{
	u_int length = h->len;
	u_int hdrlen;
	u_int caplen = h->caplen;
	const struct pfloghdr *hdr;
	uint8_t af;

	ndo->ndo_protocol = "pflog_if";
	/* check length */
	if (caplen < sizeof(uint8_t)) {
		ND_PRINT("%s", tstr);
		return (caplen);
	}

#define MIN_PFLOG_HDRLEN	45
	hdr = (const struct pfloghdr *)p;
	if (hdr->length < MIN_PFLOG_HDRLEN) {
		ND_PRINT("[pflog: invalid header length!]");
		return (hdr->length);	/* XXX: not really */
	}
	hdrlen = BPF_WORDALIGN(hdr->length);

	if (caplen < hdrlen) {
		ND_PRINT("%s", tstr);
		return (hdrlen);	/* XXX: true? */
	}

	/* print what we know */
	ND_TCHECK_SIZE(hdr);
	if (ndo->ndo_eflag)
		pflog_print(ndo, hdr);

	/* skip to the real packet */
	af = EXTRACT_U_1(&hdr->af);
	length -= hdrlen;
	caplen -= hdrlen;
	p += hdrlen;
	switch (af) {

		case AF_INET:
#if OPENBSD_AF_INET != AF_INET
		case OPENBSD_AF_INET:		/* XXX: read pcap files */
#endif
		        ip_print(ndo, p, length);
			break;

#if defined(AF_INET6) || defined(OPENBSD_AF_INET6)
#ifdef AF_INET6
		case AF_INET6:
#endif /* AF_INET6 */
#if !defined(AF_INET6) || OPENBSD_AF_INET6 != AF_INET6
		case OPENBSD_AF_INET6:		/* XXX: read pcap files */
#endif /* !defined(AF_INET6) || OPENBSD_AF_INET6 != AF_INET6 */
			ip6_print(ndo, p, length);
			break;
#endif /* defined(AF_INET6) || defined(OPENBSD_AF_INET6) */

	default:
		/* address family not handled, print raw packet */
		if (!ndo->ndo_eflag)
			pflog_print(ndo, hdr);
		if (!ndo->ndo_suppress_default_print)
			ND_DEFAULTPRINT(p, caplen);
	}

	return (hdrlen);
trunc:
	ND_PRINT("%s", tstr);
	return (hdrlen);
}
Esempio n. 18
0
static int
ldp_tlv_print(netdissect_options *ndo,
              const u_char *tptr,
              u_short msg_tlen)
{
    struct ldp_tlv_header {
        nd_uint16_t type;
        nd_uint16_t length;
    };

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

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

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

    tptr+=sizeof(struct ldp_tlv_header);

    switch(tlv_type) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	break;

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

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

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

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


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

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

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

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

badtlv:
    ND_PRINT("\n\t\t TLV contents go past end of TLV");
    return(tlv_len+4); /* Type & Length fields not included */
}
Esempio n. 19
0
void
lmp_print(netdissect_options *ndo,
          const u_char *pptr, u_int len)
{
    const struct lmp_common_header *lmp_com_header;
    const struct lmp_object_header *lmp_obj_header;
    const u_char *tptr,*obj_tptr;
    u_int version_res, tlen, lmp_obj_len, lmp_obj_ctype, obj_tlen;
    int hexdump;
    u_int offset;
    u_int link_type;

    union { /* int to float conversion buffer */
        float f;
        uint32_t i;
    } bw;

    ndo->ndo_protocol = "lmp";
    tptr=pptr;
    lmp_com_header = (const struct lmp_common_header *)pptr;
    ND_TCHECK_SIZE(lmp_com_header);

    version_res = EXTRACT_BE_U_2(lmp_com_header->version_res);

    /*
     * Sanity checking of the header.
     */
    if (LMP_EXTRACT_VERSION(version_res) != LMP_VERSION) {
	ND_PRINT("LMP version %u packet not supported",
               LMP_EXTRACT_VERSION(version_res));
	return;
    }

    /* in non-verbose mode just lets print the basic Message Type*/
    if (ndo->ndo_vflag < 1) {
        ND_PRINT("LMPv%u %s Message, length: %u",
               LMP_EXTRACT_VERSION(version_res),
               tok2str(lmp_msg_type_values, "unknown (%u)",EXTRACT_U_1(lmp_com_header->msg_type)),
               len);
        return;
    }

    /* ok they seem to want to know everything - lets fully decode it */

    tlen=EXTRACT_BE_U_2(lmp_com_header->length);

    ND_PRINT("\n\tLMPv%u, msg-type: %s, Flags: [%s], length: %u",
           LMP_EXTRACT_VERSION(version_res),
           tok2str(lmp_msg_type_values, "unknown, type: %u",EXTRACT_U_1(lmp_com_header->msg_type)),
           bittok2str(lmp_header_flag_values,"none",EXTRACT_U_1(lmp_com_header->flags)),
           tlen);
    if (tlen < sizeof(struct lmp_common_header)) {
        ND_PRINT(" (too short)");
        return;
    }
    if (tlen > len) {
        ND_PRINT(" (too long)");
        tlen = len;
    }

    tptr+=sizeof(struct lmp_common_header);
    tlen-=sizeof(struct lmp_common_header);

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

        lmp_obj_header = (const struct lmp_object_header *)tptr;
        lmp_obj_len=EXTRACT_BE_U_2(lmp_obj_header->length);
        lmp_obj_ctype=EXTRACT_U_1(lmp_obj_header->ctype)&0x7f;

        ND_PRINT("\n\t  %s Object (%u), Class-Type: %s (%u) Flags: [%snegotiable], length: %u",
               tok2str(lmp_obj_values,
                       "Unknown",
                       EXTRACT_U_1(lmp_obj_header->class_num)),
               EXTRACT_U_1(lmp_obj_header->class_num),
               tok2str(lmp_ctype_values,
                       "Unknown",
                       (EXTRACT_U_1(lmp_obj_header->class_num)<<8)+lmp_obj_ctype),
               lmp_obj_ctype,
               EXTRACT_U_1(lmp_obj_header->ctype)&0x80 ? "" : "non-",
               lmp_obj_len);

        if (lmp_obj_len < 4) {
            ND_PRINT(" (too short)");
            return;
        }
        if ((lmp_obj_len % 4) != 0) {
            ND_PRINT(" (not a multiple of 4)");
            return;
        }

        obj_tptr=tptr+sizeof(struct lmp_object_header);
        obj_tlen=lmp_obj_len-sizeof(struct lmp_object_header);

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

        switch(EXTRACT_U_1(lmp_obj_header->class_num)) {

        case LMP_OBJ_CC_ID:
            switch(lmp_obj_ctype) {
            case LMP_CTYPE_LOC:
            case LMP_CTYPE_RMT:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Control Channel ID: %u (0x%08x)",
                       EXTRACT_BE_U_4(obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr));
                break;

            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_LINK_ID:
        case LMP_OBJ_INTERFACE_ID:
            switch(lmp_obj_ctype) {
            case LMP_CTYPE_IPV4_LOC:
            case LMP_CTYPE_IPV4_RMT:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    IPv4 Link ID: %s (0x%08x)",
                       ipaddr_string(ndo, obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr));
                break;
            case LMP_CTYPE_IPV6_LOC:
            case LMP_CTYPE_IPV6_RMT:
                if (obj_tlen != 16) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    IPv6 Link ID: %s (0x%08x)",
                       ip6addr_string(ndo, obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr));
                break;
            case LMP_CTYPE_UNMD_LOC:
            case LMP_CTYPE_UNMD_RMT:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Link ID: %u (0x%08x)",
                       EXTRACT_BE_U_4(obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr));
                break;
            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_MESSAGE_ID:
            switch(lmp_obj_ctype) {
            case LMP_CTYPE_1:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Message ID: %u (0x%08x)",
                       EXTRACT_BE_U_4(obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr));
                break;
            case LMP_CTYPE_2:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Message ID Ack: %u (0x%08x)",
                       EXTRACT_BE_U_4(obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr));
                break;
            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_NODE_ID:
            switch(lmp_obj_ctype) {
            case LMP_CTYPE_LOC:
            case LMP_CTYPE_RMT:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Node ID: %s (0x%08x)",
                       ipaddr_string(ndo, obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr));
                break;

            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_CONFIG:
            switch(lmp_obj_ctype) {
            case LMP_CTYPE_HELLO_CONFIG:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Hello Interval: %u\n\t    Hello Dead Interval: %u",
                       EXTRACT_BE_U_2(obj_tptr),
                       EXTRACT_BE_U_2(obj_tptr + 2));
                break;

            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_HELLO:
            switch(lmp_obj_ctype) {
	    case LMP_CTYPE_HELLO:
                if (obj_tlen != 8) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Tx Seq: %u, Rx Seq: %u",
                       EXTRACT_BE_U_4(obj_tptr),
                       EXTRACT_BE_U_4(obj_tptr + 4));
                break;

            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_TE_LINK:
	    switch(lmp_obj_ctype) {
	    case LMP_CTYPE_IPV4:
                if (obj_tlen != 12) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
		ND_PRINT("\n\t    Flags: [%s]",
		    bittok2str(lmp_obj_te_link_flag_values,
			"none",
			EXTRACT_U_1(obj_tptr)));

		ND_PRINT("\n\t    Local Link-ID: %s (0x%08x)"
		       "\n\t    Remote Link-ID: %s (0x%08x)",
                       ipaddr_string(ndo, obj_tptr+4),
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       ipaddr_string(ndo, obj_tptr+8),
                       EXTRACT_BE_U_4(obj_tptr + 8));
		break;

	    case LMP_CTYPE_IPV6:
                if (obj_tlen != 36) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
		ND_PRINT("\n\t    Flags: [%s]",
		    bittok2str(lmp_obj_te_link_flag_values,
			"none",
			EXTRACT_U_1(obj_tptr)));

		ND_PRINT("\n\t    Local Link-ID: %s (0x%08x)"
		       "\n\t    Remote Link-ID: %s (0x%08x)",
                       ip6addr_string(ndo, obj_tptr+4),
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       ip6addr_string(ndo, obj_tptr+20),
                       EXTRACT_BE_U_4(obj_tptr + 20));
                break;

	    case LMP_CTYPE_UNMD:
                if (obj_tlen != 12) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
		ND_PRINT("\n\t    Flags: [%s]",
		    bittok2str(lmp_obj_te_link_flag_values,
			"none",
			EXTRACT_U_1(obj_tptr)));

		ND_PRINT("\n\t    Local Link-ID: %u (0x%08x)"
		       "\n\t    Remote Link-ID: %u (0x%08x)",
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       EXTRACT_BE_U_4(obj_tptr + 8),
                       EXTRACT_BE_U_4(obj_tptr + 8));
		break;

            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_DATA_LINK:
	    switch(lmp_obj_ctype) {
	    case LMP_CTYPE_IPV4:
                if (obj_tlen < 12) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
	        ND_PRINT("\n\t    Flags: [%s]",
		    bittok2str(lmp_obj_data_link_flag_values,
			"none",
			EXTRACT_U_1(obj_tptr)));
                ND_PRINT("\n\t    Local Interface ID: %s (0x%08x)"
                       "\n\t    Remote Interface ID: %s (0x%08x)",
                       ipaddr_string(ndo, obj_tptr+4),
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       ipaddr_string(ndo, obj_tptr+8),
                       EXTRACT_BE_U_4(obj_tptr + 8));

		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
		    hexdump=TRUE;
		break;

	    case LMP_CTYPE_IPV6:
                if (obj_tlen < 36) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
	        ND_PRINT("\n\t    Flags: [%s]",
		    bittok2str(lmp_obj_data_link_flag_values,
			"none",
			EXTRACT_U_1(obj_tptr)));
                ND_PRINT("\n\t    Local Interface ID: %s (0x%08x)"
                       "\n\t    Remote Interface ID: %s (0x%08x)",
                       ip6addr_string(ndo, obj_tptr+4),
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       ip6addr_string(ndo, obj_tptr+20),
                       EXTRACT_BE_U_4(obj_tptr + 20));

		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 36, 36))
		    hexdump=TRUE;
		break;

	    case LMP_CTYPE_UNMD:
                if (obj_tlen < 12) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
	        ND_PRINT("\n\t    Flags: [%s]",
		    bittok2str(lmp_obj_data_link_flag_values,
			"none",
			EXTRACT_U_1(obj_tptr)));
                ND_PRINT("\n\t    Local Interface ID: %u (0x%08x)"
                       "\n\t    Remote Interface ID: %u (0x%08x)",
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       EXTRACT_BE_U_4(obj_tptr + 4),
                       EXTRACT_BE_U_4(obj_tptr + 8),
                       EXTRACT_BE_U_4(obj_tptr + 8));

		if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
		    hexdump=TRUE;
		break;

            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_VERIFY_BEGIN:
	    switch(lmp_obj_ctype) {
            case LMP_CTYPE_1:
                if (obj_tlen != 20) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
		ND_PRINT("\n\t    Flags: %s",
		bittok2str(lmp_obj_begin_verify_flag_values,
			"none",
			EXTRACT_BE_U_2(obj_tptr)));
		ND_PRINT("\n\t    Verify Interval: %u",
			EXTRACT_BE_U_2(obj_tptr + 2));
		ND_PRINT("\n\t    Data links: %u",
			EXTRACT_BE_U_4(obj_tptr + 4));
                ND_PRINT("\n\t    Encoding type: %s",
			tok2str(gmpls_encoding_values, "Unknown", EXTRACT_U_1((obj_tptr + 8))));
                ND_PRINT("\n\t    Verify Transport Mechanism: %u (0x%x)%s",
			EXTRACT_BE_U_2(obj_tptr + 10),
			EXTRACT_BE_U_2(obj_tptr + 10),
			EXTRACT_BE_U_2(obj_tptr + 10)&8000 ? " (Payload test messages capable)" : "");
                bw.i = EXTRACT_BE_U_4(obj_tptr + 12);
		ND_PRINT("\n\t    Transmission Rate: %.3f Mbps",bw.f*8/1000000);
		ND_PRINT("\n\t    Wavelength: %u",
			EXTRACT_BE_U_4(obj_tptr + 16));
		break;

            default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_VERIFY_BEGIN_ACK:
	    switch(lmp_obj_ctype) {
            case LMP_CTYPE_1:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Verify Dead Interval: %u"
                       "\n\t    Verify Transport Response: %u",
                       EXTRACT_BE_U_2(obj_tptr),
                       EXTRACT_BE_U_2(obj_tptr + 2));
                break;

            default:
                hexdump=TRUE;
            }
            break;

	case LMP_OBJ_VERIFY_ID:
	    switch(lmp_obj_ctype) {
            case LMP_CTYPE_1:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
                ND_PRINT("\n\t    Verify ID: %u",
                       EXTRACT_BE_U_4(obj_tptr));
                break;

            default:
                hexdump=TRUE;
            }
            break;

	case LMP_OBJ_CHANNEL_STATUS:
            switch(lmp_obj_ctype) {
	    case LMP_CTYPE_IPV4:
		offset = 0;
		/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
		while (offset+8 <= obj_tlen) {
			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
			ipaddr_string(ndo, obj_tptr+offset),
			EXTRACT_BE_U_4(obj_tptr + offset));

			ND_PRINT("\n\t\t    Active: %s (%u)",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>31) ?
				"Allocated" : "Non-allocated",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>31));

			ND_PRINT("\n\t\t    Direction: %s (%u)",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ?
				"Transmit" : "Receive",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>30)&0x1);

			ND_PRINT("\n\t\t    Channel Status: %s (%u)",
					tok2str(lmp_obj_channel_status_values,
			 		"Unknown",
					EXTRACT_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF),
					EXTRACT_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF);
			offset+=8;
		}
                break;

	    case LMP_CTYPE_IPV6:
		offset = 0;
		/* Decode pairs: <Interface_ID (16 bytes), Channel_status (4 bytes)> */
		while (offset+20 <= obj_tlen) {
			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
			ip6addr_string(ndo, obj_tptr+offset),
			EXTRACT_BE_U_4(obj_tptr + offset));

			ND_PRINT("\n\t\t    Active: %s (%u)",
				(EXTRACT_BE_U_4(obj_tptr + offset + 16)>>31) ?
				"Allocated" : "Non-allocated",
				(EXTRACT_BE_U_4(obj_tptr + offset + 16)>>31));

			ND_PRINT("\n\t\t    Direction: %s (%u)",
				(EXTRACT_BE_U_4(obj_tptr + offset + 16)>>30)&0x1 ?
				"Transmit" : "Receive",
				(EXTRACT_BE_U_4(obj_tptr + offset + 16)>>30)&0x1);

			ND_PRINT("\n\t\t    Channel Status: %s (%u)",
					tok2str(lmp_obj_channel_status_values,
					"Unknown",
					EXTRACT_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF),
					EXTRACT_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF);
			offset+=20;
		}
                break;

	    case LMP_CTYPE_UNMD:
		offset = 0;
		/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
		while (offset+8 <= obj_tlen) {
			ND_PRINT("\n\t    Interface ID: %u (0x%08x)",
			EXTRACT_BE_U_4(obj_tptr + offset),
			EXTRACT_BE_U_4(obj_tptr + offset));

			ND_PRINT("\n\t\t    Active: %s (%u)",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>31) ?
				"Allocated" : "Non-allocated",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>31));

			ND_PRINT("\n\t\t    Direction: %s (%u)",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ?
				"Transmit" : "Receive",
				(EXTRACT_BE_U_4(obj_tptr + offset + 4)>>30)&0x1);

			ND_PRINT("\n\t\t    Channel Status: %s (%u)",
					tok2str(lmp_obj_channel_status_values,
					"Unknown",
					EXTRACT_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF),
					EXTRACT_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF);
			offset+=8;
		}
                break;

            default:
                hexdump=TRUE;
            }
            break;

	case LMP_OBJ_CHANNEL_STATUS_REQ:
            switch(lmp_obj_ctype) {
	    case LMP_CTYPE_IPV4:
		offset = 0;
		while (offset+4 <= obj_tlen) {
			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
			ipaddr_string(ndo, obj_tptr+offset),
			EXTRACT_BE_U_4(obj_tptr + offset));
			offset+=4;
		}
                break;

	    case LMP_CTYPE_IPV6:
		offset = 0;
		while (offset+16 <= obj_tlen) {
			ND_PRINT("\n\t    Interface ID: %s (0x%08x)",
			ip6addr_string(ndo, obj_tptr+offset),
			EXTRACT_BE_U_4(obj_tptr + offset));
			offset+=16;
		}
                break;

	    case LMP_CTYPE_UNMD:
		offset = 0;
		while (offset+4 <= obj_tlen) {
			ND_PRINT("\n\t    Interface ID: %u (0x%08x)",
			EXTRACT_BE_U_4(obj_tptr + offset),
			EXTRACT_BE_U_4(obj_tptr + offset));
			offset+=4;
		}
                break;

	    default:
                hexdump=TRUE;
            }
            break;

        case LMP_OBJ_ERROR_CODE:
	    switch(lmp_obj_ctype) {
            case LMP_CTYPE_BEGIN_VERIFY_ERROR:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
		ND_PRINT("\n\t    Error Code: %s",
		bittok2str(lmp_obj_begin_verify_error_values,
			"none",
			EXTRACT_BE_U_4(obj_tptr)));
                break;

            case LMP_CTYPE_LINK_SUMMARY_ERROR:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
		ND_PRINT("\n\t    Error Code: %s",
		bittok2str(lmp_obj_link_summary_error_values,
			"none",
			EXTRACT_BE_U_4(obj_tptr)));
                break;
            default:
                hexdump=TRUE;
            }
            break;

	case LMP_OBJ_SERVICE_CONFIG:
	    switch (lmp_obj_ctype) {
	    case LMP_CTYPE_SERVICE_CONFIG_SP:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }
		ND_PRINT("\n\t Flags: %s",
		       bittok2str(lmp_obj_service_config_sp_flag_values,
				  "none",
				  EXTRACT_U_1(obj_tptr)));

		ND_PRINT("\n\t  UNI Version: %u",
		       EXTRACT_U_1(obj_tptr + 1));

		break;

            case LMP_CTYPE_SERVICE_CONFIG_CPSA:
                if (obj_tlen != 16) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }

		link_type = EXTRACT_U_1(obj_tptr);

		ND_PRINT("\n\t Link Type: %s (%u)",
		       tok2str(lmp_sd_service_config_cpsa_link_type_values,
			       "Unknown", link_type),
		       link_type);

		switch (link_type) {
		case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH:
		    ND_PRINT("\n\t Signal Type: %s (%u)",
			   tok2str(lmp_sd_service_config_cpsa_signal_type_sdh_values,
				   "Unknown",
				   EXTRACT_U_1(obj_tptr + 1)),
			   EXTRACT_U_1(obj_tptr + 1));
		    break;

		case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET:
		    ND_PRINT("\n\t Signal Type: %s (%u)",
			   tok2str(lmp_sd_service_config_cpsa_signal_type_sonet_values,
				   "Unknown",
				   EXTRACT_U_1(obj_tptr + 1)),
			   EXTRACT_U_1(obj_tptr + 1));
		    break;
		}

		ND_PRINT("\n\t Transparency: %s",
		       bittok2str(lmp_obj_service_config_cpsa_tp_flag_values,
				  "none",
				  EXTRACT_U_1(obj_tptr + 2)));

		ND_PRINT("\n\t Contiguous Concatenation Types: %s",
		       bittok2str(lmp_obj_service_config_cpsa_cct_flag_values,
				  "none",
				  EXTRACT_U_1(obj_tptr + 3)));

		ND_PRINT("\n\t Minimum NCC: %u",
		       EXTRACT_BE_U_2(obj_tptr + 4));

		ND_PRINT("\n\t Maximum NCC: %u",
		       EXTRACT_BE_U_2(obj_tptr + 6));

		ND_PRINT("\n\t Minimum NVC:%u",
		       EXTRACT_BE_U_2(obj_tptr + 8));

		ND_PRINT("\n\t Maximum NVC:%u",
		       EXTRACT_BE_U_2(obj_tptr + 10));

		ND_PRINT("\n\t    Local Interface ID: %s (0x%08x)",
		       ipaddr_string(ndo, obj_tptr+12),
		       EXTRACT_BE_U_4(obj_tptr + 12));

		break;

	    case LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM:
                if (obj_tlen != 8) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }

		ND_PRINT("\n\t Transparency Flags: %s",
		       bittok2str(
			   lmp_obj_service_config_nsa_transparency_flag_values,
			   "none",
			   EXTRACT_BE_U_4(obj_tptr)));

		ND_PRINT("\n\t TCM Monitoring Flags: %s",
		       bittok2str(
			   lmp_obj_service_config_nsa_tcm_flag_values,
			   "none",
			   EXTRACT_U_1(obj_tptr + 7)));

		break;

	    case LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY:
                if (obj_tlen != 4) {
                    ND_PRINT(" (not correct for object)");
                    break;
                }

		ND_PRINT("\n\t Diversity: Flags: %s",
		       bittok2str(
			   lmp_obj_service_config_nsa_network_diversity_flag_values,
			   "none",
			   EXTRACT_U_1(obj_tptr + 3)));
		break;

	    default:
		hexdump = TRUE;
	    }

	break;

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

        tptr+=lmp_obj_len;
        tlen-=lmp_obj_len;
    }
    return;
trunc:
    nd_print_trunc(ndo);
}
Esempio n. 20
0
static int
stp_print_mstp_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu,
                    u_int length)
{
    const u_char *ptr;
    uint8_t	    bpdu_flags;
    uint16_t	    v3len;
    uint16_t	    len;
    uint16_t	    msti;
    u_int	    offset;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            len -= MST_BPDU_MSTI_LENGTH;
            offset += MST_BPDU_MSTI_LENGTH;
        }
    }
Esempio n. 21
0
void
sctp_print(netdissect_options *ndo,
           const u_char *bp,        /* beginning of sctp packet */
           const u_char *bp2,       /* beginning of enclosing */
           u_int sctpPacketLength)  /* ip packet */
{
  u_int sctpPacketLengthRemaining;
  const struct sctpHeader *sctpPktHdr;
  const struct ip *ip;
  const struct ip6_hdr *ip6;
  uint8_t chunkID;
  u_short sourcePort, destPort;
  u_int chunkCount;
  const struct sctpChunkDesc *chunkDescPtr;
  const char *sep;
  int isforces = 0;

  ndo->ndo_protocol = "sctp";
  if (sctpPacketLength < sizeof(struct sctpHeader))
    {
      ND_PRINT("truncated-sctp - %ld bytes missing!",
		   (long)(sizeof(struct sctpHeader) - sctpPacketLength));
      return;
    }
  sctpPktHdr = (const struct sctpHeader*) bp;
  ND_TCHECK_SIZE(sctpPktHdr);
  sctpPacketLengthRemaining = sctpPacketLength;

  sourcePort = EXTRACT_BE_U_2(sctpPktHdr->source);
  destPort = EXTRACT_BE_U_2(sctpPktHdr->destination);

  ip = (const struct ip *)bp2;
  if (IP_V(ip) == 6)
    ip6 = (const struct ip6_hdr *)bp2;
  else
    ip6 = NULL;

  if (ip6) {
    ND_PRINT("%s.%u > %s.%u: sctp",
      ip6addr_string(ndo, ip6->ip6_src),
      sourcePort,
      ip6addr_string(ndo, ip6->ip6_dst),
      destPort);
  } else
  {
    ND_PRINT("%s.%u > %s.%u: sctp",
      ipaddr_string(ndo, ip->ip_src),
      sourcePort,
      ipaddr_string(ndo, ip->ip_dst),
      destPort);
  }

  if (isForCES_port(sourcePort)) {
         ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, sourcePort));
         isforces = 1;
  }
  if (isForCES_port(destPort)) {
         ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, destPort));
         isforces = 1;
  }

  bp += sizeof(struct sctpHeader);
  sctpPacketLengthRemaining -= sizeof(struct sctpHeader);

  if (ndo->ndo_vflag >= 2)
    sep = "\n\t";
  else
    sep = " (";
  /* cycle through all chunks, printing information on each one */
  for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *)bp;
      sctpPacketLengthRemaining != 0;
      chunkCount++)
    {
      uint16_t chunkLength, chunkLengthRemaining;
      uint16_t align;

      chunkDescPtr = (const struct sctpChunkDesc *)bp;
      if (sctpPacketLengthRemaining < sizeof(*chunkDescPtr)) {
        ND_PRINT("%s%u) [chunk descriptor cut off at end of packet]", sep, chunkCount+1);
        break;
      }
      ND_TCHECK_SIZE(chunkDescPtr);
      chunkLength = EXTRACT_BE_U_2(chunkDescPtr->chunkLength);
      if (chunkLength < sizeof(*chunkDescPtr)) {
        ND_PRINT("%s%u) [Bad chunk length %u, < size of chunk descriptor]", sep, chunkCount+1, chunkLength);
        break;
      }
      chunkLengthRemaining = chunkLength;

      align = chunkLength % 4;
      if (align != 0)
	align = 4 - align;

      if (sctpPacketLengthRemaining < align) {
        ND_PRINT("%s%u) [Bad chunk length %u, > remaining data in packet]", sep, chunkCount+1, chunkLength);
        break;
      }

      ND_TCHECK_LEN(bp, chunkLength);

      bp += sizeof(*chunkDescPtr);
      sctpPacketLengthRemaining -= sizeof(*chunkDescPtr);
      chunkLengthRemaining -= sizeof(*chunkDescPtr);

      ND_PRINT("%s%u) ", sep, chunkCount+1);
      chunkID = EXTRACT_U_1(chunkDescPtr->chunkID);
      ND_PRINT("[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x",
                                      chunkID));
      switch (chunkID)
	{
	case SCTP_DATA :
	  {
	    const struct sctpDataPart *dataHdrPtr;
	    uint8_t chunkFlg;
	    uint32_t ppid;
	    u_int payload_size;

	    chunkFlg = EXTRACT_U_1(chunkDescPtr->chunkFlg);
	    if ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)
	      ND_PRINT("(U)");

	    if ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG)
	      ND_PRINT("(B)");

	    if ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG)
	      ND_PRINT("(E)");

	    if( ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) ||
	        ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) ||
		((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) )
	      ND_PRINT(" ");

	    if (chunkLengthRemaining < sizeof(*dataHdrPtr)) {
		ND_PRINT("bogus chunk length %u]", chunkLength);
		return;
	    }
	    dataHdrPtr=(const struct sctpDataPart*)bp;

	    ppid = EXTRACT_BE_U_4(dataHdrPtr->payloadtype);
	    ND_PRINT("[TSN: %u] ", EXTRACT_BE_U_4(dataHdrPtr->TSN));
	    ND_PRINT("[SID: %u] ", EXTRACT_BE_U_2(dataHdrPtr->streamId));
	    ND_PRINT("[SSEQ %u] ", EXTRACT_BE_U_2(dataHdrPtr->sequence));
	    ND_PRINT("[PPID %s] ",
		    tok2str(PayloadProto_idents, "0x%x", ppid));

	    if (!isforces) {
		isforces = (ppid == SCTP_PPID_FORCES_HP) ||
		    (ppid == SCTP_PPID_FORCES_MP) ||
		    (ppid == SCTP_PPID_FORCES_LP);
	    }

	    bp += sizeof(*dataHdrPtr);
	    sctpPacketLengthRemaining -= sizeof(*dataHdrPtr);
	    chunkLengthRemaining -= sizeof(*dataHdrPtr);
	    payload_size = chunkLengthRemaining;
	    if (payload_size == 0) {
		ND_PRINT("bogus chunk length %u]", chunkLength);
		return;
	    }

	    if (isforces) {
		forces_print(ndo, bp, payload_size);
	    } else if (ndo->ndo_vflag >= 2) {	/* if verbose output is specified */
					/* at the command line */
		switch (ppid) {
		case SCTP_PPID_M3UA :
			m3ua_print(ndo, bp, payload_size);
			break;
		default:
			ND_PRINT("[Payload");
			if (!ndo->ndo_suppress_default_print) {
				ND_PRINT(":");
				ND_DEFAULTPRINT(bp, payload_size);
			}
			ND_PRINT("]");
			break;
		}
	    }
	    bp += payload_size;
	    sctpPacketLengthRemaining -= payload_size;
	    chunkLengthRemaining -= payload_size;
	    break;
	  }
	case SCTP_INITIATION :
	  {
	    const struct sctpInitiation *init;

	    if (chunkLengthRemaining < sizeof(*init)) {
		ND_PRINT("bogus chunk length %u]", chunkLength);
		return;
	    }
	    init=(const struct sctpInitiation*)bp;
	    ND_PRINT("[init tag: %u] ", EXTRACT_BE_U_4(init->initTag));
	    ND_PRINT("[rwnd: %u] ", EXTRACT_BE_U_4(init->rcvWindowCredit));
	    ND_PRINT("[OS: %u] ", EXTRACT_BE_U_2(init->NumPreopenStreams));
	    ND_PRINT("[MIS: %u] ", EXTRACT_BE_U_2(init->MaxInboundStreams));
	    ND_PRINT("[init TSN: %u] ", EXTRACT_BE_U_4(init->initialTSN));
	    bp += sizeof(*init);
 	    sctpPacketLengthRemaining -= sizeof(*init);
	    chunkLengthRemaining -= sizeof(*init);

#if 0 /* ALC you can add code for optional params here */
	    if( chunkLengthRemaining != 0 )
	      ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n",
		     "Optional params present, but not printed.");
#endif
            bp += chunkLengthRemaining;
	    sctpPacketLengthRemaining -= chunkLengthRemaining;
            chunkLengthRemaining = 0;
	    break;
	  }
	case SCTP_INITIATION_ACK :
	  {
	    const struct sctpInitiation *init;

	    if (chunkLengthRemaining < sizeof(*init)) {
		ND_PRINT("bogus chunk length %u]", chunkLength);
		return;
	    }
	    init=(const struct sctpInitiation*)bp;
	    ND_PRINT("[init tag: %u] ", EXTRACT_BE_U_4(init->initTag));
	    ND_PRINT("[rwnd: %u] ", EXTRACT_BE_U_4(init->rcvWindowCredit));
	    ND_PRINT("[OS: %u] ", EXTRACT_BE_U_2(init->NumPreopenStreams));
	    ND_PRINT("[MIS: %u] ", EXTRACT_BE_U_2(init->MaxInboundStreams));
	    ND_PRINT("[init TSN: %u] ", EXTRACT_BE_U_4(init->initialTSN));
            bp += sizeof(*init);
            sctpPacketLengthRemaining -= sizeof(*init);
            chunkLengthRemaining -= sizeof(*init);

#if 0 /* ALC you can add code for optional params here */
	    if( chunkLengthRemaining != 0 )
	      ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n",
		     "Optional params present, but not printed.");
#endif
            bp += chunkLengthRemaining;
	    sctpPacketLengthRemaining -= chunkLengthRemaining;
            chunkLengthRemaining = 0;
	    break;
	  }
	case SCTP_SELECTIVE_ACK:
	  {
	    const struct sctpSelectiveAck *sack;
	    const struct sctpSelectiveFrag *frag;
	    u_int fragNo, tsnNo;
	    const u_char *dupTSN;

	    if (chunkLengthRemaining < sizeof(*sack)) {
	      ND_PRINT("bogus chunk length %u]", chunkLength);
	      return;
	    }
	    sack=(const struct sctpSelectiveAck*)bp;
	    ND_PRINT("[cum ack %u] ", EXTRACT_BE_U_4(sack->highestConseqTSN));
	    ND_PRINT("[a_rwnd %u] ", EXTRACT_BE_U_4(sack->updatedRwnd));
	    ND_PRINT("[#gap acks %u] ", EXTRACT_BE_U_2(sack->numberOfdesc));
	    ND_PRINT("[#dup tsns %u] ", EXTRACT_BE_U_2(sack->numDupTsns));
            bp += sizeof(*sack);
	    sctpPacketLengthRemaining -= sizeof(*sack);
            chunkLengthRemaining -= sizeof(*sack);


	    /* print gaps */
	    for (fragNo=0;
		 chunkLengthRemaining != 0 && fragNo < EXTRACT_BE_U_2(sack->numberOfdesc);
		 bp += sizeof(*frag), sctpPacketLengthRemaining -= sizeof(*frag), chunkLengthRemaining -= sizeof(*frag), fragNo++) {
	      if (chunkLengthRemaining < sizeof(*frag)) {
		ND_PRINT("bogus chunk length %u]", chunkLength);
		return;
	      }
	      frag = (const struct sctpSelectiveFrag *)bp;
	      ND_PRINT("\n\t\t[gap ack block #%u: start = %u, end = %u] ",
		     fragNo+1,
		     EXTRACT_BE_U_4(sack->highestConseqTSN) + EXTRACT_BE_U_2(frag->fragmentStart),
		     EXTRACT_BE_U_4(sack->highestConseqTSN) + EXTRACT_BE_U_2(frag->fragmentEnd));
	    }

	    /* print duplicate TSNs */
	    for (tsnNo=0;
		 chunkLengthRemaining != 0 && tsnNo<EXTRACT_BE_U_2(sack->numDupTsns);
		 bp += 4, sctpPacketLengthRemaining -= 4, chunkLengthRemaining -= 4, tsnNo++) {
	      if (chunkLengthRemaining < 4) {
		ND_PRINT("bogus chunk length %u]", chunkLength);
		return;
	      }
              dupTSN = (const u_char *)bp;
	      ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
	        EXTRACT_BE_U_4(dupTSN));
	    }
	    break;
	  }
	default :
	  {
            bp += chunkLengthRemaining;
            sctpPacketLengthRemaining -= chunkLengthRemaining;
            chunkLengthRemaining = 0;
	    break;
	  }
	}

      /*
       * Any extra stuff at the end of the chunk?
       * XXX - report this?
       */
      bp += chunkLengthRemaining;
      sctpPacketLengthRemaining -= chunkLengthRemaining;

      if (ndo->ndo_vflag < 2)
        sep = ", (";

      if (align != 0) {
	/*
	 * Fail if the alignment padding isn't in the captured data.
	 * Otherwise, skip it.
	 */
	ND_TCHECK_LEN(bp, align);
	bp += align;
	sctpPacketLengthRemaining -= align;
      }
    }
    return;

trunc:
    ND_PRINT("[|sctp]");
}
Esempio n. 22
0
static void
dhcp6opt_print(netdissect_options *ndo,
               const u_char *cp, const u_char *ep)
{
	const struct dhcp6opt *dh6o;
	const u_char *tp;
	u_int i;
	uint16_t opttype;
	uint16_t optlen;
	uint8_t auth_proto;
	uint8_t auth_alg;
	uint8_t auth_rdm;
	u_int authinfolen, authrealmlen;
	u_int remain_len;  /* Length of remaining options */
	u_int label_len;   /* Label length */
	uint16_t subopt_code;
	uint16_t subopt_len;
	uint8_t dh6_reconf_type;
	uint8_t dh6_lq_query_type;

	if (cp == ep)
		return;
	while (cp < ep) {
		if (ep < cp + sizeof(*dh6o))
			goto trunc;
		dh6o = (const struct dhcp6opt *)cp;
		ND_TCHECK_SIZE(dh6o);
		optlen = EXTRACT_BE_U_2(dh6o->dh6opt_len);
		if (ep < cp + sizeof(*dh6o) + optlen)
			goto trunc;
		opttype = EXTRACT_BE_U_2(dh6o->dh6opt_type);
		ND_PRINT(" (%s", tok2str(dh6opt_str, "opt_%u", opttype));
		ND_TCHECK_LEN(cp + sizeof(*dh6o), optlen);
		switch (opttype) {
		case DH6OPT_CLIENTID:
		case DH6OPT_SERVERID:
			if (optlen < 2) {
				/*(*/
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			switch (EXTRACT_BE_U_2(tp)) {
			case 1:
				if (optlen >= 2 + 6) {
					ND_PRINT(" hwaddr/time type %u time %u ",
					    EXTRACT_BE_U_2(tp + 2),
					    EXTRACT_BE_U_4(tp + 4));
					for (i = 8; i < optlen; i++)
						ND_PRINT("%02x", EXTRACT_U_1(tp + i));
					/*(*/
					ND_PRINT(")");
				} else {
					/*(*/
					ND_PRINT(" ?)");
				}
				break;
			case 2:
				if (optlen >= 2 + 8) {
					ND_PRINT(" vid ");
					for (i = 2; i < 2 + 8; i++)
						ND_PRINT("%02x", EXTRACT_U_1(tp + i));
					/*(*/
					ND_PRINT(")");
				} else {
					/*(*/
					ND_PRINT(" ?)");
				}
				break;
			case 3:
				if (optlen >= 2 + 2) {
					ND_PRINT(" hwaddr type %u ",
					    EXTRACT_BE_U_2(tp + 2));
					for (i = 4; i < optlen; i++)
						ND_PRINT("%02x", EXTRACT_U_1(tp + i));
					/*(*/
					ND_PRINT(")");
				} else {
					/*(*/
					ND_PRINT(" ?)");
				}
				break;
			default:
				ND_PRINT(" type %u)", EXTRACT_BE_U_2(tp));
				break;
			}
			break;
		case DH6OPT_IA_ADDR:
			if (optlen < 24) {
				/*(*/
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %s", ip6addr_string(ndo, tp));
			ND_PRINT(" pltime:%u vltime:%u",
			    EXTRACT_BE_U_4(tp + 16),
			    EXTRACT_BE_U_4(tp + 20));
			if (optlen > 24) {
				/* there are sub-options */
				dhcp6opt_print(ndo, tp + 24, tp + optlen);
			}
			ND_PRINT(")");
			break;
		case DH6OPT_ORO:
		case DH6OPT_ERO:
			if (optlen % 2) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			for (i = 0; i < optlen; i += 2) {
				ND_PRINT(" %s",
				    tok2str(dh6opt_str, "opt_%u", EXTRACT_BE_U_2(tp + i)));
			}
			ND_PRINT(")");
			break;
		case DH6OPT_PREFERENCE:
			if (optlen != 1) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %u)", EXTRACT_U_1(tp));
			break;
		case DH6OPT_ELAPSED_TIME:
			if (optlen != 2) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %u)", EXTRACT_BE_U_2(tp));
			break;
		case DH6OPT_RELAY_MSG:
			ND_PRINT(" (");
			tp = (const u_char *)(dh6o + 1);
			dhcp6_print(ndo, tp, optlen);
			ND_PRINT(")");
			break;
		case DH6OPT_AUTH:
			if (optlen < 11) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			auth_proto = EXTRACT_U_1(tp);
			switch (auth_proto) {
			case DH6OPT_AUTHPROTO_DELAYED:
				ND_PRINT(" proto: delayed");
				break;
			case DH6OPT_AUTHPROTO_RECONFIG:
				ND_PRINT(" proto: reconfigure");
				break;
			default:
				ND_PRINT(" proto: %u", auth_proto);
				break;
			}
			tp++;
			auth_alg = EXTRACT_U_1(tp);
			switch (auth_alg) {
			case DH6OPT_AUTHALG_HMACMD5:
				/* XXX: may depend on the protocol */
				ND_PRINT(", alg: HMAC-MD5");
				break;
			default:
				ND_PRINT(", alg: %u", auth_alg);
				break;
			}
			tp++;
			auth_rdm = EXTRACT_U_1(tp);
			switch (auth_rdm) {
			case DH6OPT_AUTHRDM_MONOCOUNTER:
				ND_PRINT(", RDM: mono");
				break;
			default:
				ND_PRINT(", RDM: %u", auth_rdm);
				break;
			}
			tp++;
			ND_PRINT(", RD:");
			for (i = 0; i < 4; i++, tp += 2)
				ND_PRINT(" %04x", EXTRACT_BE_U_2(tp));

			/* protocol dependent part */
			authinfolen = optlen - 11;
			switch (auth_proto) {
			case DH6OPT_AUTHPROTO_DELAYED:
				if (authinfolen == 0)
					break;
				if (authinfolen < 20) {
					ND_PRINT(" ??");
					break;
				}
				authrealmlen = authinfolen - 20;
				if (authrealmlen > 0) {
					ND_PRINT(", realm: ");
				}
				for (i = 0; i < authrealmlen; i++, tp++)
					ND_PRINT("%02x", EXTRACT_U_1(tp));
				ND_PRINT(", key ID: %08x", EXTRACT_BE_U_4(tp));
				tp += 4;
				ND_PRINT(", HMAC-MD5:");
				for (i = 0; i < 4; i++, tp+= 4)
					ND_PRINT(" %08x", EXTRACT_BE_U_4(tp));
				break;
			case DH6OPT_AUTHPROTO_RECONFIG:
				if (authinfolen != 17) {
					ND_PRINT(" ??");
					break;
				}
				switch (EXTRACT_U_1(tp)) {
				case DH6OPT_AUTHRECONFIG_KEY:
					ND_PRINT(" reconfig-key");
					break;
				case DH6OPT_AUTHRECONFIG_HMACMD5:
					ND_PRINT(" type: HMAC-MD5");
					break;
				default:
					ND_PRINT(" type: ??");
					break;
				}
				tp++;
				ND_PRINT(" value:");
				for (i = 0; i < 4; i++, tp+= 4)
					ND_PRINT(" %08x", EXTRACT_BE_U_4(tp));
				break;
			default:
				ND_PRINT(" ??");
				break;
			}

			ND_PRINT(")");
			break;
		case DH6OPT_RAPID_COMMIT: /* nothing todo */
			ND_PRINT(")");
			break;
		case DH6OPT_INTERFACE_ID:
		case DH6OPT_SUBSCRIBER_ID:
			/*
			 * Since we cannot predict the encoding, print hex dump
			 * at most 10 characters.
			 */
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" ");
			for (i = 0; i < optlen && i < 10; i++)
				ND_PRINT("%02x", EXTRACT_U_1(tp + i));
			ND_PRINT("...)");
			break;
		case DH6OPT_RECONF_MSG:
			if (optlen != 1) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			dh6_reconf_type = EXTRACT_U_1(tp);
			switch (dh6_reconf_type) {
			case DH6_RENEW:
				ND_PRINT(" for renew)");
				break;
			case DH6_INFORM_REQ:
				ND_PRINT(" for inf-req)");
				break;
			default:
				ND_PRINT(" for ?\?\?(%02x))", dh6_reconf_type);
				break;
			}
			break;
		case DH6OPT_RECONF_ACCEPT: /* nothing todo */
			ND_PRINT(")");
			break;
		case DH6OPT_SIP_SERVER_A:
		case DH6OPT_DNS_SERVERS:
		case DH6OPT_SNTP_SERVERS:
		case DH6OPT_NIS_SERVERS:
		case DH6OPT_NISP_SERVERS:
		case DH6OPT_BCMCS_SERVER_A:
		case DH6OPT_PANA_AGENT:
		case DH6OPT_LQ_CLIENT_LINK:
			if (optlen % 16) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			for (i = 0; i < optlen; i += 16)
				ND_PRINT(" %s", ip6addr_string(ndo, tp + i));
			ND_PRINT(")");
			break;
		case DH6OPT_SIP_SERVER_D:
		case DH6OPT_DOMAIN_LIST:
			tp = (const u_char *)(dh6o + 1);
			while (tp < cp + sizeof(*dh6o) + optlen) {
				ND_PRINT(" ");
				if ((tp = ns_nprint(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL)
					goto trunc;
			}
			ND_PRINT(")");
			break;
		case DH6OPT_STATUS_CODE:
			if (optlen < 2) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %s)", dhcp6stcode(EXTRACT_BE_U_2(tp)));
			break;
		case DH6OPT_IA_NA:
		case DH6OPT_IA_PD:
			if (optlen < 12) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" IAID:%u T1:%u T2:%u",
			    EXTRACT_BE_U_4(tp),
			    EXTRACT_BE_U_4(tp + 4),
			    EXTRACT_BE_U_4(tp + 8));
			if (optlen > 12) {
				/* there are sub-options */
				dhcp6opt_print(ndo, tp + 12, tp + optlen);
			}
			ND_PRINT(")");
			break;
		case DH6OPT_IA_TA:
			if (optlen < 4) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" IAID:%u", EXTRACT_BE_U_4(tp));
			if (optlen > 4) {
				/* there are sub-options */
				dhcp6opt_print(ndo, tp + 4, tp + optlen);
			}
			ND_PRINT(")");
			break;
		case DH6OPT_IA_PD_PREFIX:
			if (optlen < 25) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %s/%u", ip6addr_string(ndo, tp + 9), EXTRACT_U_1(tp + 8));
			ND_PRINT(" pltime:%u vltime:%u",
			    EXTRACT_BE_U_4(tp),
			    EXTRACT_BE_U_4(tp + 4));
			if (optlen > 25) {
				/* there are sub-options */
				dhcp6opt_print(ndo, tp + 25, tp + optlen);
			}
			ND_PRINT(")");
			break;
		case DH6OPT_LIFETIME:
		case DH6OPT_CLT_TIME:
			if (optlen != 4) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %u)", EXTRACT_BE_U_4(tp));
			break;
		case DH6OPT_REMOTE_ID:
			if (optlen < 4) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %u ", EXTRACT_BE_U_4(tp));
			/*
			 * Print hex dump first 10 characters.
			 */
			for (i = 4; i < optlen && i < 14; i++)
				ND_PRINT("%02x", EXTRACT_U_1(tp + i));
			ND_PRINT("...)");
			break;
		case DH6OPT_LQ_QUERY:
			if (optlen < 17) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			dh6_lq_query_type = EXTRACT_U_1(tp);
			switch (dh6_lq_query_type) {
			case 1:
				ND_PRINT(" by-address");
				break;
			case 2:
				ND_PRINT(" by-clientID");
				break;
			default:
				ND_PRINT(" type_%u", dh6_lq_query_type);
				break;
			}
			ND_PRINT(" %s", ip6addr_string(ndo, tp + 1));
			if (optlen > 17) {
				/* there are query-options */
				dhcp6opt_print(ndo, tp + 17, tp + optlen);
			}
			ND_PRINT(")");
			break;
		case DH6OPT_CLIENT_DATA:
			tp = (const u_char *)(dh6o + 1);
			if (optlen > 0) {
				/* there are encapsulated options */
				dhcp6opt_print(ndo, tp, tp + optlen);
			}
			ND_PRINT(")");
			break;
		case DH6OPT_LQ_RELAY_DATA:
			if (optlen < 16) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT(" %s ", ip6addr_string(ndo, tp));
			/*
			 * Print hex dump first 10 characters.
			 */
			for (i = 16; i < optlen && i < 26; i++)
				ND_PRINT("%02x", EXTRACT_U_1(tp + i));
			ND_PRINT("...)");
			break;
		case DH6OPT_NTP_SERVER:
			if (optlen < 4) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			while (tp < cp + sizeof(*dh6o) + optlen - 4) {
				subopt_code = EXTRACT_BE_U_2(tp);
				tp += 2;
				subopt_len = EXTRACT_BE_U_2(tp);
				tp += 2;
				if (tp + subopt_len > cp + sizeof(*dh6o) + optlen)
					goto trunc;
				ND_PRINT(" subopt:%u", subopt_code);
				switch (subopt_code) {
				case DH6OPT_NTP_SUBOPTION_SRV_ADDR:
				case DH6OPT_NTP_SUBOPTION_MC_ADDR:
					if (subopt_len != 16) {
						ND_PRINT(" ?");
						break;
					}
					ND_PRINT(" %s", ip6addr_string(ndo, tp));
					break;
				case DH6OPT_NTP_SUBOPTION_SRV_FQDN:
					ND_PRINT(" ");
					if (ns_nprint(ndo, tp, tp + subopt_len) == NULL)
						goto trunc;
					break;
				default:
					ND_PRINT(" ?");
					break;
				}
				tp += subopt_len;
			}
			ND_PRINT(")");
			break;
		case DH6OPT_AFTR_NAME:
			if (optlen < 3) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			remain_len = optlen;
			ND_PRINT(" ");
			/* Encoding is described in section 3.1 of RFC 1035 */
			while (remain_len && EXTRACT_U_1(tp)) {
				label_len = EXTRACT_U_1(tp);
				tp++;
				if (label_len < remain_len - 1) {
					(void)fn_printn(ndo, tp, label_len, NULL);
					tp += label_len;
					remain_len -= (label_len + 1);
					if(EXTRACT_U_1(tp)) ND_PRINT(".");
				} else {
					ND_PRINT(" ?");
					break;
				}
			}
			ND_PRINT(")");
			break;
		case DH6OPT_NEW_POSIX_TIMEZONE: /* all three of these options */
		case DH6OPT_NEW_TZDB_TIMEZONE:	/* are encoded similarly */
		case DH6OPT_MUDURL:		/* although GMT might not work */
		        if (optlen < 5) {
				ND_PRINT(" ?)");
				break;
			}
			tp = (const u_char *)(dh6o + 1);
			ND_PRINT("=");
			(void)fn_printn(ndo, tp, (u_int)optlen, NULL);
			ND_PRINT(")");
			break;

		default:
			ND_PRINT(")");
			break;
		}

		cp += sizeof(*dh6o) + optlen;
	}
	return;

trunc:
	ND_PRINT("[|dhcp6ext]");
}
Esempio n. 23
0
void
vqp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
    const struct vqp_common_header_t *vqp_common_header;
    const struct vqp_obj_tlv_t *vqp_obj_tlv;

    const u_char *tptr;
    uint8_t version;
    uint16_t vqp_obj_len;
    uint32_t vqp_obj_type;
    u_int tlen;
    uint8_t nitems;

    tptr=pptr;
    tlen = len;
    vqp_common_header = (const struct vqp_common_header_t *)pptr;
    ND_TCHECK_SIZE(vqp_common_header);
    if (sizeof(struct vqp_common_header_t) > tlen)
        goto trunc;
    version = EXTRACT_U_1(vqp_common_header->version);

    /*
     * Sanity checking of the header.
     */
    if (version != VQP_VERSION) {
	ND_PRINT("VQP version %u packet not supported",
               version);
	return;
    }

    /* in non-verbose mode just lets print the basic Message Type */
    if (ndo->ndo_vflag < 1) {
        ND_PRINT("VQPv%u %s Message, error-code %s (%u), length %u",
               version,
               tok2str(vqp_msg_type_values, "unknown (%u)",EXTRACT_U_1(vqp_common_header->msg_type)),
               tok2str(vqp_error_code_values, "unknown (%u)",EXTRACT_U_1(vqp_common_header->error_code)),
	       EXTRACT_U_1(vqp_common_header->error_code),
               len);
        return;
    }

    /* ok they seem to want to know everything - lets fully decode it */
    nitems = EXTRACT_U_1(vqp_common_header->nitems);
    ND_PRINT("\n\tVQPv%u, %s Message, error-code %s (%u), seq 0x%08x, items %u, length %u",
           version,
	   tok2str(vqp_msg_type_values, "unknown (%u)",EXTRACT_U_1(vqp_common_header->msg_type)),
	   tok2str(vqp_error_code_values, "unknown (%u)",EXTRACT_U_1(vqp_common_header->error_code)),
	   EXTRACT_U_1(vqp_common_header->error_code),
           EXTRACT_BE_U_4(vqp_common_header->sequence),
           nitems,
           len);

    /* skip VQP Common header */
    tptr+=sizeof(struct vqp_common_header_t);
    tlen-=sizeof(struct vqp_common_header_t);

    while (nitems != 0 && tlen != 0) {

        vqp_obj_tlv = (const struct vqp_obj_tlv_t *)tptr;
        ND_TCHECK_SIZE(vqp_obj_tlv);
        if (sizeof(struct vqp_obj_tlv_t) > tlen)
            goto trunc;
        vqp_obj_type = EXTRACT_BE_U_4(vqp_obj_tlv->obj_type);
        vqp_obj_len = EXTRACT_BE_U_2(vqp_obj_tlv->obj_length);
        tptr+=sizeof(struct vqp_obj_tlv_t);
        tlen-=sizeof(struct vqp_obj_tlv_t);

        ND_PRINT("\n\t  %s Object (0x%08x), length %u, value: ",
               tok2str(vqp_obj_values, "Unknown", vqp_obj_type),
               vqp_obj_type, vqp_obj_len);

        /* basic sanity check */
        if (vqp_obj_type == 0 || vqp_obj_len ==0) {
            return;
        }

        /* did we capture enough for fully decoding the object ? */
        ND_TCHECK_LEN(tptr, vqp_obj_len);
        if (vqp_obj_len > tlen)
            goto trunc;

        switch(vqp_obj_type) {
	case VQP_OBJ_IP_ADDRESS:
            if (vqp_obj_len != 4)
                goto trunc;
            ND_PRINT("%s (0x%08x)", ipaddr_string(ndo, tptr), EXTRACT_BE_U_4(tptr));
            break;
            /* those objects have similar semantics - fall through */
        case VQP_OBJ_PORT_NAME:
	case VQP_OBJ_VLAN_NAME:
	case VQP_OBJ_VTP_DOMAIN:
	case VQP_OBJ_ETHERNET_PKT:
            safeputs(ndo, tptr, vqp_obj_len);
            break;
            /* those objects have similar semantics - fall through */
	case VQP_OBJ_MAC_ADDRESS:
	case VQP_OBJ_MAC_NULL:
            if (vqp_obj_len != MAC_ADDR_LEN)
                goto trunc;
	      ND_PRINT("%s", etheraddr_string(ndo, tptr));
              break;
        default:
            if (ndo->ndo_vflag <= 1)
                print_unknown_data(ndo,tptr, "\n\t    ", vqp_obj_len);
            break;
        }
	tptr += vqp_obj_len;
	tlen -= vqp_obj_len;
	nitems--;
    }
    return;
trunc:
    ND_PRINT("\n\t[|VQP]");
}
Esempio n. 24
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);
}
Esempio n. 25
0
void
cfm_print(netdissect_options *ndo,
          const u_char *pptr, u_int length)
{
    const struct cfm_common_header_t *cfm_common_header;
    uint8_t mdlevel_version, opcode, flags, first_tlv_offset;
    const struct cfm_tlv_header_t *cfm_tlv_header;
    const uint8_t *tptr, *tlv_ptr;
    const uint8_t *namesp;
    u_int names_data_remaining;
    uint8_t md_nameformat, md_namelength;
    const uint8_t *md_name;
    uint8_t ma_nameformat, ma_namelength;
    const uint8_t *ma_name;
    u_int hexdump, tlen, cfm_tlv_len, cfm_tlv_type, ccm_interval;


    union {
        const struct cfm_ccm_t *cfm_ccm;
        const struct cfm_lbm_t *cfm_lbm;
        const struct cfm_ltm_t *cfm_ltm;
        const struct cfm_ltr_t *cfm_ltr;
    } msg_ptr;

    tptr=pptr;
    cfm_common_header = (const struct cfm_common_header_t *)pptr;
    if (length < sizeof(*cfm_common_header))
        goto tooshort;
    ND_TCHECK_SIZE(cfm_common_header);

    /*
     * Sanity checking of the header.
     */
    mdlevel_version = EXTRACT_U_1(cfm_common_header->mdlevel_version);
    if (CFM_EXTRACT_VERSION(mdlevel_version) != CFM_VERSION) {
	ND_PRINT("CFMv%u not supported, length %u",
               CFM_EXTRACT_VERSION(mdlevel_version), length);
	return;
    }

    opcode = EXTRACT_U_1(cfm_common_header->opcode);
    ND_PRINT("CFMv%u %s, MD Level %u, length %u",
           CFM_EXTRACT_VERSION(mdlevel_version),
           tok2str(cfm_opcode_values, "unknown (%u)", opcode),
           CFM_EXTRACT_MD_LEVEL(mdlevel_version),
           length);

    /*
     * In non-verbose mode just print the opcode and md-level.
     */
    if (ndo->ndo_vflag < 1) {
        return;
    }

    flags = EXTRACT_U_1(cfm_common_header->flags);
    first_tlv_offset = EXTRACT_U_1(cfm_common_header->first_tlv_offset);
    ND_PRINT("\n\tFirst TLV offset %u", first_tlv_offset);

    tptr += sizeof(struct cfm_common_header_t);
    tlen = length - sizeof(struct cfm_common_header_t);

    /*
     * Sanity check the first TLV offset.
     */
    if (first_tlv_offset > tlen) {
        ND_PRINT(" (too large, must be <= %u)", tlen);
        return;
    }

    switch (opcode) {
    case CFM_OPCODE_CCM:
        msg_ptr.cfm_ccm = (const struct cfm_ccm_t *)tptr;
        if (first_tlv_offset < sizeof(*msg_ptr.cfm_ccm)) {
            ND_PRINT(" (too small 1, must be >= %lu)",
                     (unsigned long) sizeof(*msg_ptr.cfm_ccm));
            return;
        }
        if (tlen < sizeof(*msg_ptr.cfm_ccm))
            goto tooshort;
        ND_TCHECK_SIZE(msg_ptr.cfm_ccm);

        ccm_interval = CFM_EXTRACT_CCM_INTERVAL(flags);
        ND_PRINT(", Flags [CCM Interval %u%s]",
               ccm_interval,
               flags & CFM_CCM_RDI_FLAG ?
               ", RDI" : "");

        /*
         * Resolve the CCM interval field.
         */
        if (ccm_interval) {
            ND_PRINT("\n\t  CCM Interval %.3fs"
                   ", min CCM Lifetime %.3fs, max CCM Lifetime %.3fs",
                   ccm_interval_base[ccm_interval],
                   ccm_interval_base[ccm_interval] * CCM_INTERVAL_MIN_MULTIPLIER,
                   ccm_interval_base[ccm_interval] * CCM_INTERVAL_MAX_MULTIPLIER);
        }

        ND_PRINT("\n\t  Sequence Number 0x%08x, MA-End-Point-ID 0x%04x",
               EXTRACT_BE_U_4(msg_ptr.cfm_ccm->sequence),
               EXTRACT_BE_U_2(msg_ptr.cfm_ccm->ma_epi));

        namesp = msg_ptr.cfm_ccm->names;
        names_data_remaining = sizeof(msg_ptr.cfm_ccm->names);

        /*
         * Resolve the MD fields.
         */
        md_nameformat = EXTRACT_U_1(namesp);
        namesp++;
        names_data_remaining--;  /* We know this is != 0 */
        if (md_nameformat != CFM_CCM_MD_FORMAT_NONE) {
            md_namelength = EXTRACT_U_1(namesp);
            namesp++;
            names_data_remaining--; /* We know this is !=0 */
            ND_PRINT("\n\t  MD Name Format %s (%u), MD Name length %u",
                   tok2str(cfm_md_nameformat_values, "Unknown",
                           md_nameformat),
                   md_nameformat,
                   md_namelength);

            /*
             * -3 for the MA short name format and length and one byte
             * of MA short name.
             */
            if (md_namelength > names_data_remaining - 3) {
                ND_PRINT(" (too large, must be <= %u)", names_data_remaining - 2);
                return;
            }

            md_name = namesp;
            ND_PRINT("\n\t  MD Name: ");
            switch (md_nameformat) {
            case CFM_CCM_MD_FORMAT_DNS:
            case CFM_CCM_MD_FORMAT_CHAR:
                safeputs(ndo, md_name, md_namelength);
                break;

            case CFM_CCM_MD_FORMAT_MAC:
                if (md_namelength == 6) {
                    ND_PRINT("\n\t  MAC %s", etheraddr_string(ndo,
                               md_name));
                } else {
                    ND_PRINT("\n\t  MAC (length invalid)");
                }
                break;

                /* FIXME add printers for those MD formats - hexdump for now */
            case CFM_CCM_MA_FORMAT_8021:
            default:
                print_unknown_data(ndo, md_name, "\n\t    ",
                                   md_namelength);
            }
            namesp += md_namelength;
            names_data_remaining -= md_namelength;
        } else {
            ND_PRINT("\n\t  MD Name Format %s (%u)",
                   tok2str(cfm_md_nameformat_values, "Unknown",
                           md_nameformat),
                   md_nameformat);
        }


        /*
         * Resolve the MA fields.
         */
        ma_nameformat = EXTRACT_U_1(namesp);
        namesp++;
        names_data_remaining--; /* We know this is != 0 */
        ma_namelength = EXTRACT_U_1(namesp);
        namesp++;
        names_data_remaining--; /* We know this is != 0 */
        ND_PRINT("\n\t  MA Name-Format %s (%u), MA name length %u",
               tok2str(cfm_ma_nameformat_values, "Unknown",
                       ma_nameformat),
               ma_nameformat,
               ma_namelength);

        if (ma_namelength > names_data_remaining) {
            ND_PRINT(" (too large, must be <= %u)", names_data_remaining);
            return;
        }

        ma_name = namesp;
        ND_PRINT("\n\t  MA Name: ");
        switch (ma_nameformat) {
        case CFM_CCM_MA_FORMAT_CHAR:
            safeputs(ndo, ma_name, ma_namelength);
            break;

            /* FIXME add printers for those MA formats - hexdump for now */
        case CFM_CCM_MA_FORMAT_8021:
        case CFM_CCM_MA_FORMAT_VID:
        case CFM_CCM_MA_FORMAT_INT:
        case CFM_CCM_MA_FORMAT_VPN:
        default:
            print_unknown_data(ndo, ma_name, "\n\t    ", ma_namelength);
        }
        break;

    case CFM_OPCODE_LTM:
        msg_ptr.cfm_ltm = (const struct cfm_ltm_t *)tptr;
        if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltm)) {
            ND_PRINT(" (too small 4, must be >= %lu)",
                     (unsigned long) sizeof(*msg_ptr.cfm_ltm));
            return;
        }
        if (tlen < sizeof(*msg_ptr.cfm_ltm))
            goto tooshort;
        ND_TCHECK_SIZE(msg_ptr.cfm_ltm);

        ND_PRINT(", Flags [%s]",
               bittok2str(cfm_ltm_flag_values, "none", flags));

        ND_PRINT("\n\t  Transaction-ID 0x%08x, ttl %u",
               EXTRACT_BE_U_4(msg_ptr.cfm_ltm->transaction_id),
               EXTRACT_U_1(msg_ptr.cfm_ltm->ttl));

        ND_PRINT("\n\t  Original-MAC %s, Target-MAC %s",
               etheraddr_string(ndo, msg_ptr.cfm_ltm->original_mac),
               etheraddr_string(ndo, msg_ptr.cfm_ltm->target_mac));
        break;

    case CFM_OPCODE_LTR:
        msg_ptr.cfm_ltr = (const struct cfm_ltr_t *)tptr;
        if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltr)) {
            ND_PRINT(" (too small 5, must be >= %lu)",
                     (unsigned long) sizeof(*msg_ptr.cfm_ltr));
            return;
        }
        if (tlen < sizeof(*msg_ptr.cfm_ltr))
            goto tooshort;
        ND_TCHECK_SIZE(msg_ptr.cfm_ltr);

        ND_PRINT(", Flags [%s]",
               bittok2str(cfm_ltr_flag_values, "none", flags));

        ND_PRINT("\n\t  Transaction-ID 0x%08x, ttl %u",
               EXTRACT_BE_U_4(msg_ptr.cfm_ltr->transaction_id),
               EXTRACT_U_1(msg_ptr.cfm_ltr->ttl));

        ND_PRINT("\n\t  Replay-Action %s (%u)",
               tok2str(cfm_ltr_replay_action_values,
                       "Unknown",
                       EXTRACT_U_1(msg_ptr.cfm_ltr->replay_action)),
               EXTRACT_U_1(msg_ptr.cfm_ltr->replay_action));
        break;

        /*
         * No message decoder yet.
         * Hexdump everything up until the start of the TLVs
         */
    case CFM_OPCODE_LBR:
    case CFM_OPCODE_LBM:
    default:
        print_unknown_data(ndo, tptr, "\n\t  ",
                           tlen -  first_tlv_offset);
        break;
    }

    tptr += first_tlv_offset;
    tlen -= first_tlv_offset;

    while (tlen > 0) {
        cfm_tlv_header = (const struct cfm_tlv_header_t *)tptr;

        /* Enough to read the tlv type ? */
        ND_TCHECK_1(cfm_tlv_header->type);
        cfm_tlv_type = EXTRACT_U_1(cfm_tlv_header->type);

        ND_PRINT("\n\t%s TLV (0x%02x)",
               tok2str(cfm_tlv_values, "Unknown", cfm_tlv_type),
               cfm_tlv_type);

        if (cfm_tlv_type == CFM_TLV_END) {
            /* Length is "Not present if the Type field is 0." */
            return;
        }

        /* do we have the full tlv header ? */
        if (tlen < sizeof(struct cfm_tlv_header_t))
            goto tooshort;
        ND_TCHECK_LEN(tptr, sizeof(struct cfm_tlv_header_t));
        cfm_tlv_len=EXTRACT_BE_U_2(cfm_tlv_header->length);

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

        tptr += sizeof(struct cfm_tlv_header_t);
        tlen -= sizeof(struct cfm_tlv_header_t);
        tlv_ptr = tptr;

        /* do we have the full tlv ? */
        if (tlen < cfm_tlv_len)
            goto tooshort;
        ND_TCHECK_LEN(tptr, cfm_tlv_len);
        hexdump = FALSE;

        switch(cfm_tlv_type) {
        case CFM_TLV_PORT_STATUS:
            if (cfm_tlv_len < 1) {
                ND_PRINT(" (too short, must be >= 1)");
                return;
            }
            ND_PRINT(", Status: %s (%u)",
                   tok2str(cfm_tlv_port_status_values, "Unknown", EXTRACT_U_1(tptr)),
                   EXTRACT_U_1(tptr));
            break;

        case CFM_TLV_INTERFACE_STATUS:
            if (cfm_tlv_len < 1) {
                ND_PRINT(" (too short, must be >= 1)");
                return;
            }
            ND_PRINT(", Status: %s (%u)",
                   tok2str(cfm_tlv_interface_status_values, "Unknown", EXTRACT_U_1(tptr)),
                   EXTRACT_U_1(tptr));
            break;

        case CFM_TLV_PRIVATE:
            if (cfm_tlv_len < 4) {
                ND_PRINT(" (too short, must be >= 4)");
                return;
            }
            ND_PRINT(", Vendor: %s (%u), Sub-Type %u",
                   tok2str(oui_values,"Unknown", EXTRACT_BE_U_3(tptr)),
                   EXTRACT_BE_U_3(tptr),
                   EXTRACT_U_1(tptr + 3));
            hexdump = TRUE;
            break;

        case CFM_TLV_SENDER_ID:
        {
            u_int chassis_id_type, chassis_id_length;
            u_int mgmt_addr_length;

            if (cfm_tlv_len < 1) {
                ND_PRINT(" (too short, must be >= 1)");
                goto next_tlv;
            }

            /*
             * Get the Chassis ID length and check it.
             * IEEE 802.1Q-2014 Section 21.5.3.1
             */
            chassis_id_length = EXTRACT_U_1(tptr);
            tptr++;
            tlen--;
            cfm_tlv_len--;

            if (chassis_id_length) {
                /*
                 * IEEE 802.1Q-2014 Section 21.5.3.2: Chassis ID Subtype, references
                 * IEEE 802.1AB-2005 Section 9.5.2.2, subsequently
                 * IEEE 802.1AB-2016 Section 8.5.2.2: chassis ID subtype
                 */
                if (cfm_tlv_len < 1) {
                    ND_PRINT("\n\t  (TLV too short)");
                    goto next_tlv;
                }
                chassis_id_type = EXTRACT_U_1(tptr);
                cfm_tlv_len--;
                ND_PRINT("\n\t  Chassis-ID Type %s (%u), Chassis-ID length %u",
                       tok2str(cfm_tlv_senderid_chassisid_values,
                               "Unknown",
                               chassis_id_type),
                       chassis_id_type,
                       chassis_id_length);

                if (cfm_tlv_len < chassis_id_length) {
                    ND_PRINT("\n\t  (TLV too short)");
                    goto next_tlv;
                }

                /* IEEE 802.1Q-2014 Section 21.5.3.3: Chassis ID */
                switch (chassis_id_type) {
                case CFM_CHASSIS_ID_MAC_ADDRESS:
                    if (chassis_id_length != MAC_ADDR_LEN) {
                        ND_PRINT(" (invalid MAC address length)");
                        hexdump = TRUE;
                        break;
                    }
                    ND_PRINT("\n\t  MAC %s", etheraddr_string(ndo, tptr + 1));
                    break;

                case CFM_CHASSIS_ID_NETWORK_ADDRESS:
                    hexdump |= cfm_network_addr_print(ndo, tptr + 1, chassis_id_length);
                    break;

                case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */
                case CFM_CHASSIS_ID_INTERFACE_ALIAS:
                case CFM_CHASSIS_ID_LOCAL:
                case CFM_CHASSIS_ID_CHASSIS_COMPONENT:
                case CFM_CHASSIS_ID_PORT_COMPONENT:
                    safeputs(ndo, tptr + 1, chassis_id_length);
                    break;

                default:
                    hexdump = TRUE;
                    break;
                }
                cfm_tlv_len -= chassis_id_length;

                tptr += 1 + chassis_id_length;
                tlen -= 1 + chassis_id_length;
            }

            /*
             * Check if there is a Management Address.
             * IEEE 802.1Q-2014 Section 21.5.3.4: Management Address Domain Length
             * This and all subsequent fields are not present if the TLV length
             * allows only the above fields.
             */
            if (cfm_tlv_len == 0) {
                /* No, there isn't; we're done. */
                break;
            }

            /* Here mgmt_addr_length stands for the management domain length. */
            mgmt_addr_length = EXTRACT_U_1(tptr);
            tptr++;
            tlen--;
            cfm_tlv_len--;
            ND_PRINT("\n\t  Management Address Domain Length %u", mgmt_addr_length);
            if (mgmt_addr_length) {
                /* IEEE 802.1Q-2014 Section 21.5.3.5: Management Address Domain */
                if (cfm_tlv_len < mgmt_addr_length) {
                    ND_PRINT("\n\t  (TLV too short)");
                    goto next_tlv;
                }
                cfm_tlv_len -= mgmt_addr_length;
                /*
                 * XXX - this is an OID; print it as such.
                 */
                hex_print(ndo, "\n\t  Management Address Domain: ", tptr, mgmt_addr_length);
                tptr += mgmt_addr_length;
                tlen -= mgmt_addr_length;

                /*
                 * IEEE 802.1Q-2014 Section 21.5.3.6: Management Address Length
                 * This field is present if Management Address Domain Length is not 0.
                 */
                if (cfm_tlv_len < 1) {
                    ND_PRINT(" (Management Address Length is missing)");
                    hexdump = TRUE;
                    break;
                }

                /* Here mgmt_addr_length stands for the management address length. */
                mgmt_addr_length = EXTRACT_U_1(tptr);
                tptr++;
                tlen--;
                cfm_tlv_len--;
                ND_PRINT("\n\t  Management Address Length %u", mgmt_addr_length);
                if (mgmt_addr_length) {
                    /* IEEE 802.1Q-2014 Section 21.5.3.7: Management Address */
                    if (cfm_tlv_len < mgmt_addr_length) {
                        ND_PRINT("\n\t  (TLV too short)");
                        return;
                    }
                    cfm_tlv_len -= mgmt_addr_length;
                    /*
                     * XXX - this is a TransportDomain; print it as such.
                     */
                    hex_print(ndo, "\n\t  Management Address: ", tptr, mgmt_addr_length);
                    tptr += mgmt_addr_length;
                    tlen -= mgmt_addr_length;
                }
            }
            break;
        }

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

        case CFM_TLV_DATA:
        case CFM_TLV_REPLY_INGRESS:
        case CFM_TLV_REPLY_EGRESS:
        default:
            hexdump = TRUE;
            break;
        }
        /* do we want to see an additional hexdump ? */
        if (hexdump || ndo->ndo_vflag > 1)
            print_unknown_data(ndo, tlv_ptr, "\n\t  ", cfm_tlv_len);

next_tlv:
        tptr+=cfm_tlv_len;
        tlen-=cfm_tlv_len;
    }
    return;

tooshort:
    ND_PRINT("\n\t\t packet is too short");
    return;

trunc:
    ND_PRINT("%s", tstr);
}