+ lspping_subtlv_header = (const struct lspping_tlv_header *)tlv_tptr;
+ lspping_subtlv_type=GET_BE_U_2(lspping_subtlv_header->type);
+ lspping_subtlv_len=GET_BE_U_2(lspping_subtlv_header->length);
+ subtlv_tptr=tlv_tptr+sizeof(struct lspping_tlv_header);
+
+ /* Does the subTLV go past the end of the TLV? */
+ if (tlv_tlen < lspping_subtlv_len+sizeof(struct lspping_tlv_header)) {
+ ND_PRINT("\n\t TLV is too short");
+ tlv_hexdump = TRUE;
+ goto tlv_tooshort;
+ }
+
+ /* Did we capture enough for fully decoding the subTLV? */
+ ND_TCHECK_LEN(subtlv_tptr, lspping_subtlv_len);
+
+ ND_PRINT("\n\t %s subTLV (%u), length: %u",
+ tok2str(lspping_tlvtargetfec_subtlv_values,
+ "Unknown",
+ lspping_subtlv_type),
+ lspping_subtlv_type,
+ lspping_subtlv_len);
+
+ switch(lspping_subtlv_type) {
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 5) {
+ ND_PRINT("\n\t invalid subTLV length, should be 5");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4 =
+ (const struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t *)subtlv_tptr;
+ ND_PRINT("\n\t %s/%u",
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix),
+ GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix_len));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 17) {
+ ND_PRINT("\n\t invalid subTLV length, should be 17");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6 =
+ (const struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t *)subtlv_tptr;
+ ND_PRINT("\n\t %s/%u",
+ GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix),
+ GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix_len));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 5) {
+ ND_PRINT("\n\t invalid subTLV length, should be 5");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4 =
+ (const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *)subtlv_tptr;
+ ND_PRINT("\n\t %s/%u",
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix),
+ GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix_len));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 17) {
+ ND_PRINT("\n\t invalid subTLV length, should be 17");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6 =
+ (const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *)subtlv_tptr;
+ ND_PRINT("\n\t %s/%u",
+ GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix),
+ GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix_len));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 20) {
+ ND_PRINT("\n\t invalid subTLV length, should be 20");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4 =
+ (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t *)subtlv_tptr;
+ ND_PRINT("\n\t tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x"
+ "\n\t tunnel-id 0x%04x, extended tunnel-id %s",
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_endpoint),
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_sender),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->lsp_id),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_id),
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->extended_tunnel_id));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 56) {
+ ND_PRINT("\n\t invalid subTLV length, should be 56");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6 =
+ (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t *)subtlv_tptr;
+ ND_PRINT("\n\t tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x"
+ "\n\t tunnel-id 0x%04x, extended tunnel-id %s",
+ GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_endpoint),
+ GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_sender),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->lsp_id),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_id),
+ GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->extended_tunnel_id));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 13) {
+ ND_PRINT("\n\t invalid subTLV length, should be 13");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4 =
+ (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *)subtlv_tptr;
+ ND_PRINT("\n\t RD: %s, %s/%u",
+ bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->rd),
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix),
+ GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix_len));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 25) {
+ ND_PRINT("\n\t invalid subTLV length, should be 25");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6 =
+ (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *)subtlv_tptr;
+ ND_PRINT("\n\t RD: %s, %s/%u",
+ bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->rd),
+ GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix),
+ GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix_len));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 14) {
+ ND_PRINT("\n\t invalid subTLV length, should be 14");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt =
+ (const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *)subtlv_tptr;
+ ND_PRINT("\n\t RD: %s, Sender VE ID: %u, Receiver VE ID: %u"
+ "\n\t Encapsulation Type: %s (%u)",
+ bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->rd),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->sender_ve_id),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->receiver_ve_id),
+ tok2str(mpls_pw_types_values,
+ "unknown",
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation));
+ }
+ break;
+
+ /* the old L2VPN VCID subTLV does not have support for the sender field */
+ case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 10) {
+ ND_PRINT("\n\t invalid subTLV length, should be 10");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old =
+ (const struct lspping_tlv_targetfec_subtlv_fec_128_pw_old *)subtlv_tptr;
+ ND_PRINT("\n\t Remote PE: %s"
+ "\n\t PW ID: 0x%08x, PW Type: %s (%u)",
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->remote_pe_address),
+ GET_BE_U_4(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_id),
+ tok2str(mpls_pw_types_values,
+ "unknown",
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type)),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type));
+ }
+ break;
+
+ case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW:
+ /* Is the subTLV length correct? */
+ if (lspping_subtlv_len != 14) {
+ ND_PRINT("\n\t invalid subTLV length, should be 14");
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ } else {
+ subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid =
+ (const struct lspping_tlv_targetfec_subtlv_fec_128_pw *)subtlv_tptr;
+ ND_PRINT("\n\t Sender PE: %s, Remote PE: %s"
+ "\n\t PW ID: 0x%08x, PW Type: %s (%u)",
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->sender_pe_address),
+ GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->remote_pe_address),
+ GET_BE_U_4(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_id),
+ tok2str(mpls_pw_types_values,
+ "unknown",
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type)),
+ GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type));
+ }
+ break;
+
+ default:
+ subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
+ break;
+ }
+ /* do we want to see an additionally subtlv hexdump ? */
+ if (ndo->ndo_vflag > 1 || subtlv_hexdump==TRUE)
+ print_unknown_data(ndo, tlv_tptr+sizeof(struct lspping_tlv_header),
+ "\n\t ",
+ lspping_subtlv_len);
+
+ /* All subTLVs are aligned to four octet boundary */
+ if (lspping_subtlv_len % 4) {
+ lspping_subtlv_len += 4 - (lspping_subtlv_len % 4);
+ /* Does the subTLV, including padding, go past the end of the TLV? */
+ if (tlv_tlen < lspping_subtlv_len+sizeof(struct lspping_tlv_header)) {
+ ND_PRINT("\n\t\t TLV is too short");
+ return;
+ }
+ }
+ tlv_tptr+=lspping_subtlv_len;
+ tlv_tlen-=lspping_subtlv_len+sizeof(struct lspping_tlv_header);
+ }
+ break;