]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Updates for RFC 4379, bug fixes, and additional bounds checks.
authorGuy Harris <[email protected]>
Sun, 16 Oct 2016 04:41:31 +0000 (21:41 -0700)
committerFrancois-Xavier Le Bail <[email protected]>
Wed, 18 Jan 2017 08:16:40 +0000 (09:16 +0100)
print-lspping.c was written to one of the draft-ietf-mpls-lsp-ping-13
drafts; incorporate subsequent changes that are in RFC 4379.  Not all
LV and subTLV types from that RFC are currently dissected.

Apparently, the IANA has two separate but similar registries, the BGP
Layer 2 Encapsulation Types registry and the MPLS Pseudowire Types
registry.  Have two separate tables for them, and use the tables as
appropriate.  Update them to match the current state of the registries.

11 is not the subTLV code for "BGP labeled IPv4 prefix" (and never was,
from what I can tell from looking at the I-Ds), 12 is.

Do more bounds checking.

print-lspping.c

index e85ff42a0c51ab60ee4e21ddcff75a8378e373bc..7e629dbcd60226c51dadf74e057f8b1993c99450 100644 (file)
@@ -28,6 +28,8 @@
 #include "l2vpn.h"
 #include "oui.h"
 
+/* RFC 4349 */
+
 /*
  * LSPPING common header
  *
@@ -58,7 +60,7 @@
 
 struct lspping_common_header {
     uint8_t version[2];
-    uint8_t reserved[2];
+    uint8_t global_flags[2];
     uint8_t msg_type;
     uint8_t reply_mode;
     uint8_t return_code;
@@ -101,6 +103,7 @@ static const struct tok lspping_return_code_values[] = {
     { 10, "Mapping for this FEC is not the given label at stack depth"},
     { 11, "No label entry at stack-depth"},
     { 12, "Protocol not associated with interface at FEC stack depth"},
+    { 13, "Premature termination of ping due to label stack shrinking to a single label"},
 };
 
 
@@ -127,9 +130,12 @@ struct lspping_tlv_header {
 #define        LSPPING_TLV_TARGET_FEC_STACK      1
 #define        LSPPING_TLV_DOWNSTREAM_MAPPING    2
 #define        LSPPING_TLV_PAD                   3
+/* not assigned                           4 */
 #define LSPPING_TLV_VENDOR_ENTERPRISE     5
 #define LSPPING_TLV_VENDOR_ENTERPRISE_LEN 4
+/* not assigned                           6 */
 #define LSPPING_TLV_INTERFACE_LABEL_STACK 7
+/* not assigned                           8 */
 #define        LSPPING_TLV_ERROR_CODE            9
 #define LSPPING_TLV_REPLY_TOS_BYTE        10
 #define        LSPPING_TLV_BFD_DISCRIMINATOR     15 /* draft-ietf-bfd-mpls-02 */
@@ -149,17 +155,22 @@ static const struct tok lspping_tlv_values[] = {
     { 0, NULL}
 };
 
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4      1
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6      2
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4     3
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6     4
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4    6
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6    7
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT   8
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID_OLD 9
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID   10
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4     11
-#define        LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6     12
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4       1
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6       2
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4      3
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6      4
+/* not assigned                                     5 */
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4     6
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6     7
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT    8
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD 9
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW     10
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_FEC_129_PW     11
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4       12
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6       13
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_GENERIC_IPV4   14
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_GENERIC_IPV6   15
+#define        LSPPING_TLV_TARGETFEC_SUBTLV_NIL_FEC        16
 
 static const struct tok lspping_tlvtargetfec_subtlv_values[] = {
     { LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4, "LDP IPv4 prefix"},
@@ -170,8 +181,8 @@ static const struct tok lspping_tlvtargetfec_subtlv_values[] = {
     { LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4, "VPN IPv4 prefix"},
     { LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6, "VPN IPv6 prefix"},
     { LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT, "L2 VPN endpoint"},
-    { LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID_OLD, "L2 circuit ID (old)"},
-    { LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID, "L2 circuit ID"},
+    { LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD, "FEC 128 pseudowire (old)"},
+    { LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW, "FEC 128 pseudowire"},
     { LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4, "BGP labeled IPv4 prefix"},
     { LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6, "BGP labeled IPv6 prefix"},
     { 0, NULL}
@@ -208,44 +219,6 @@ struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t {
     uint8_t prefix_len;
 };
 
-/*
- * 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |                    Sender identifier                          |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |                         IPv4 prefix                           |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Prefix Length |                 Must Be Zero                  |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t {
-    uint8_t sender_id [4];
-    uint8_t prefix [4];
-    uint8_t prefix_len;
-};
-
-/*
- * 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
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |                    Sender identifier                          |
- * |                          (16 octets)                          |
- * |                                                               |
- * |                                                               |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |                          IPv6 prefix                          |
- * |                          (16 octets)                          |
- * |                                                               |
- * |                                                               |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Prefix Length |                 Must Be Zero                  |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
-struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t {
-    uint8_t sender_id [16];
-    uint8_t prefix [16];
-    uint8_t prefix_len;
-};
-
 /*
  *  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
@@ -351,7 +324,7 @@ struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t {
  * |                      Route Distinguisher                      |
  * |                          (8 octets)                           |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |         Sender's CE ID        |       Receiver's CE ID        |
+ * |         Sender's VE ID        |       Receiver's VE ID        |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |      Encapsulation Type       |         Must Be Zero          |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -359,8 +332,8 @@ struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t {
  */
 struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t {
     uint8_t rd [8];
-    uint8_t sender_ce_id [2];
-    uint8_t receiver_ce_id [2];
+    uint8_t sender_ve_id [2];
+    uint8_t receiver_ve_id [2];
     uint8_t encapsulation[2];
 };
 
@@ -369,15 +342,15 @@ struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t {
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |                      Remote PE Address                        |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |                             VC ID                             |
+ * |                             PW ID                             |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |      Encapsulation Type       |         Must Be Zero          |
+ * |            PW Type            |          Must Be Zero         |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
-struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_old_t {
+struct lspping_tlv_targetfec_subtlv_fec_128_pw_old {
     uint8_t remote_pe_address [4];
-    uint8_t vc_id [4];
-    uint8_t encapsulation[2];
+    uint8_t pw_id [4];
+    uint8_t pw_type[2];
 };
 
 /*
@@ -387,16 +360,45 @@ struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_old_t {
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |                      Remote PE Address                        |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |                             VC ID                             |
+ * |                             PW ID                             |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |      Encapsulation Type       |         Must Be Zero          |
+ * |            PW Type            |          Must Be Zero         |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
-struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t {
+struct lspping_tlv_targetfec_subtlv_fec_128_pw {
     uint8_t sender_pe_address [4];
     uint8_t remote_pe_address [4];
-    uint8_t vc_id [4];
-    uint8_t encapsulation[2];
+    uint8_t pw_id [4];
+    uint8_t pw_type[2];
+};
+
+/*
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         IPv4 prefix                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Prefix Length |                 Must Be Zero                  |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t {
+    uint8_t prefix [4];
+    uint8_t prefix_len;
+};
+
+/*
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                          IPv6 prefix                          |
+ * |                          (16 octets)                          |
+ * |                                                               |
+ * |                                                               |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Prefix Length |                 Must Be Zero                  |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t {
+    uint8_t prefix [16];
+    uint8_t prefix_len;
 };
 
 /*
@@ -409,7 +411,7 @@ struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t {
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * |         Downstream Interface Address (4 or 16 octets)         |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Hash Key Type | Depth Limit   |        Multipath Length       |
+ * | Multipath Type| Depth Limit   |        Multipath Length       |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * .                                                               .
  * .                     (Multipath Information)                   .
@@ -424,10 +426,25 @@ struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t {
  * |               Downstream Label                |    Protocol   |
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  */
+/* Enough to get the address type */
+struct lspping_tlv_downstream_map_t {
+    uint8_t mtu [2];
+    uint8_t address_type;
+    uint8_t ds_flags;
+};
+
 struct lspping_tlv_downstream_map_ipv4_t {
     uint8_t mtu [2];
     uint8_t address_type;
-    uint8_t res;
+    uint8_t ds_flags;
+    uint8_t downstream_ip[4];
+    uint8_t downstream_interface[4];
+};
+
+struct lspping_tlv_downstream_map_ipv4_unmb_t {
+    uint8_t mtu [2];
+    uint8_t address_type;
+    uint8_t ds_flags;
     uint8_t downstream_ip[4];
     uint8_t downstream_interface[4];
 };
@@ -435,25 +452,35 @@ struct lspping_tlv_downstream_map_ipv4_t {
 struct lspping_tlv_downstream_map_ipv6_t {
     uint8_t mtu [2];
     uint8_t address_type;
-    uint8_t res;
+    uint8_t ds_flags;
     uint8_t downstream_ip[16];
     uint8_t downstream_interface[16];
 };
 
+struct lspping_tlv_downstream_map_ipv6_unmb_t {
+    uint8_t mtu [2];
+    uint8_t address_type;
+    uint8_t ds_flags;
+    uint8_t downstream_ip[16];
+    uint8_t downstream_interface[4];
+};
+
 struct lspping_tlv_downstream_map_info_t {
-    uint8_t hash_key_type;
+    uint8_t multipath_type;
     uint8_t depth_limit;
     uint8_t multipath_length [2];
 };
 
-#define LSPPING_AFI_IPV4 1
-#define LSPPING_AFI_UNMB 2
-#define LSPPING_AFI_IPV6 3
+#define LSPPING_AFI_IPV4      1
+#define LSPPING_AFI_IPV4_UNMB 2
+#define LSPPING_AFI_IPV6      3
+#define LSPPING_AFI_IPV6_UNMB 4
 
 static const struct tok lspping_tlv_downstream_addr_values[] = {
-    { LSPPING_AFI_IPV4, "IPv4"},
-    { LSPPING_AFI_IPV6, "IPv6"},
-    { LSPPING_AFI_UNMB, "Unnumbered"},
+    { LSPPING_AFI_IPV4,      "IPv4"},
+    { LSPPING_AFI_IPV4_UNMB, "Unnumbered IPv4"},
+    { LSPPING_AFI_IPV6,      "IPv6"},
+    { LSPPING_AFI_IPV6_UNMB, "IPv6"},
     { 0, NULL}
 };
 
@@ -465,14 +492,17 @@ lspping_print(netdissect_options *ndo,
     const struct lspping_tlv_header *lspping_tlv_header;
     const struct lspping_tlv_header *lspping_subtlv_header;
     const u_char *tptr,*tlv_tptr,*subtlv_tptr;
-    int tlen,lspping_tlv_len,lspping_tlv_type,tlv_tlen;
+    u_int tlen,lspping_tlv_len,lspping_tlv_type,tlv_tlen;
     int tlv_hexdump,subtlv_hexdump;
-    int lspping_subtlv_len,lspping_subtlv_type;
+    u_int lspping_subtlv_len,lspping_subtlv_type;
     struct timeval timestamp;
 
     union {
+        const struct lspping_tlv_downstream_map_t *lspping_tlv_downstream_map;
         const struct lspping_tlv_downstream_map_ipv4_t *lspping_tlv_downstream_map_ipv4;
+        const struct lspping_tlv_downstream_map_ipv4_unmb_t *lspping_tlv_downstream_map_ipv4_unmb;
         const struct lspping_tlv_downstream_map_ipv6_t *lspping_tlv_downstream_map_ipv6;
+        const struct lspping_tlv_downstream_map_ipv6_unmb_t *lspping_tlv_downstream_map_ipv6_unmb;
         const struct lspping_tlv_downstream_map_info_t  *lspping_tlv_downstream_map_info;
     } tlv_ptr;
 
@@ -484,14 +514,16 @@ lspping_print(netdissect_options *ndo,
         const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *lspping_tlv_targetfec_subtlv_l3vpn_ipv4;
         const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *lspping_tlv_targetfec_subtlv_l3vpn_ipv6;
         const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *lspping_tlv_targetfec_subtlv_l2vpn_endpt;
-        const struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_old_t *lspping_tlv_targetfec_subtlv_l2vpn_vcid_old;
-        const struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t *lspping_tlv_targetfec_subtlv_l2vpn_vcid;
+        const struct lspping_tlv_targetfec_subtlv_fec_128_pw_old *lspping_tlv_targetfec_subtlv_l2vpn_vcid_old;
+        const struct lspping_tlv_targetfec_subtlv_fec_128_pw *lspping_tlv_targetfec_subtlv_l2vpn_vcid;
         const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *lspping_tlv_targetfec_subtlv_bgp_ipv4;
         const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *lspping_tlv_targetfec_subtlv_bgp_ipv6;
     } subtlv_ptr;
 
     tptr=pptr;
     lspping_com_header = (const struct lspping_common_header *)pptr;
+    if (len < sizeof(const struct lspping_common_header))
+        goto tooshort;
     ND_TCHECK(*lspping_com_header);
 
     /*
@@ -566,7 +598,10 @@ lspping_print(netdissect_options *ndo,
     tptr+=sizeof(const struct lspping_common_header);
     tlen-=sizeof(const struct lspping_common_header);
 
-    while(tlen>(int)sizeof(struct lspping_tlv_header)) {
+    while (tlen != 0) {
+        /* Does the TLV go past the end of the packet? */
+        if (tlen < sizeof(struct lspping_tlv_header))
+            goto tooshort;
 
         /* did we capture enough for fully decoding the tlv header ? */
         ND_TCHECK2(*tptr, sizeof(struct lspping_tlv_header));
@@ -575,15 +610,6 @@ lspping_print(netdissect_options *ndo,
         lspping_tlv_type=EXTRACT_16BITS(lspping_tlv_header->type);
         lspping_tlv_len=EXTRACT_16BITS(lspping_tlv_header->length);
 
-        /* some little sanity checking */
-        if (lspping_tlv_type == 0 || lspping_tlv_len == 0)
-            return;
-
-        if(lspping_tlv_len < 4) {
-            ND_PRINT((ndo, "\n\t  ERROR: TLV %u bogus size %u",lspping_tlv_type,lspping_tlv_len));
-            return;
-        }
-
         ND_PRINT((ndo, "\n\t  %s TLV (%u), length: %u",
                tok2str(lspping_tlv_values,
                        "Unknown",
@@ -591,19 +617,33 @@ lspping_print(netdissect_options *ndo,
                lspping_tlv_type,
                lspping_tlv_len));
 
+        /* some little sanity checking */
+        if (lspping_tlv_len == 0) {
+            tptr+=sizeof(struct lspping_tlv_header);
+            tlen-=sizeof(struct lspping_tlv_header);
+            continue;    /* no value to dissect */
+        }
+
         tlv_tptr=tptr+sizeof(struct lspping_tlv_header);
         tlv_tlen=lspping_tlv_len; /* header not included -> no adjustment */
 
+        /* Does the TLV go past the end of the packet? */
+        if (tlen < lspping_tlv_len+sizeof(struct lspping_tlv_header))
+            goto tooshort;
         /* did we capture enough for fully decoding the tlv ? */
-        ND_TCHECK2(*tptr, lspping_tlv_len);
+        ND_TCHECK2(*tlv_tptr, lspping_tlv_len);
         tlv_hexdump=FALSE;
 
         switch(lspping_tlv_type) {
         case LSPPING_TLV_TARGET_FEC_STACK:
-            while(tlv_tlen>(int)sizeof(struct lspping_tlv_header)) {
-
+            while (tlv_tlen != 0) {
+                /* Does the subTLV go past the end of the TLV? */
+                if (tlv_tlen < sizeof(struct lspping_tlv_header)) {
+                    subtlv_hexdump = TRUE;
+                    goto subtlv_too_short;
+                }
                 /* did we capture enough for fully decoding the subtlv header ? */
-                ND_TCHECK2(*tptr, sizeof(struct lspping_tlv_header));
+                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_header));
                 subtlv_hexdump=FALSE;
 
                 lspping_subtlv_header = (const struct lspping_tlv_header *)tlv_tptr;
@@ -611,8 +651,14 @@ lspping_print(netdissect_options *ndo,
                 lspping_subtlv_len=EXTRACT_16BITS(lspping_subtlv_header->length);
                 subtlv_tptr=tlv_tptr+sizeof(struct lspping_tlv_header);
 
-                if (lspping_subtlv_len == 0)
-                    break;
+                /* Does the subTLV go past the end of the TLV? */
+                if (tlv_tlen < lspping_subtlv_len+sizeof(struct lspping_tlv_header)) {
+                    subtlv_hexdump = TRUE;
+                    goto subtlv_too_short;
+                }
+
+                /* Did we capture enough for fully decoding the subTLV? */
+                ND_TCHECK2(*subtlv_tptr, lspping_subtlv_len);
 
                 ND_PRINT((ndo, "\n\t    %s subTLV (%u), length: %u",
                        tok2str(lspping_tlvtargetfec_subtlv_values,
@@ -624,124 +670,185 @@ lspping_print(netdissect_options *ndo,
                 switch(lspping_subtlv_type) {
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4 = \
-                        (const struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      %s/%u",
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix),
-                           subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix_len));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 5) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      %s/%u",
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix),
+                               subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix_len));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6 = \
-                        (const struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      %s/%u",
-                           ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix),
-                           subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix_len));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 17) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      %s/%u",
+                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix),
+                               subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix_len));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4 = \
-                        (const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      %s/%u, sender-id %s",
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix),
-                           subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix_len,
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->sender_id)));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 5) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      %s/%u",
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix),
+                               subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix_len));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6 = \
-                        (const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      %s/%u, sender-id %s",
-                           ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix),
-                           subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix_len,
-                           ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->sender_id)));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 17) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      %s/%u",
+                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix),
+                               subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix_len));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4 = \
-                        (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \
-                           "\n\t      tunnel-id 0x%04x, extended tunnel-id %s",
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_endpoint),
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_sender),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->lsp_id),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_id),
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->extended_tunnel_id)));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 20) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \
+                               "\n\t      tunnel-id 0x%04x, extended tunnel-id %s",
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_endpoint),
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_sender),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->lsp_id),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_id),
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->extended_tunnel_id)));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6 = \
-                        (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \
-                           "\n\t      tunnel-id 0x%04x, extended tunnel-id %s",
-                           ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_endpoint),
-                           ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_sender),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->lsp_id),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_id),
-                           ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->extended_tunnel_id)));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 56) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \
+                               "\n\t      tunnel-id 0x%04x, extended tunnel-id %s",
+                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_endpoint),
+                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_sender),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->lsp_id),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_id),
+                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->extended_tunnel_id)));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4 = \
-                        (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      RD: %s, %s/%u",
-                           bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->rd),
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix),
-                           subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix_len));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 13) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      RD: %s, %s/%u",
+                               bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->rd),
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix),
+                               subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix_len));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6 = \
-                        (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      RD: %s, %s/%u",
-                           bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->rd),
-                           ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix),
-                           subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix_len));
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 25) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      RD: %s, %s/%u",
+                               bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->rd),
+                               ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix),
+                               subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix_len));
+                    }
                     break;
 
                 case LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt = \
-                        (const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      RD: %s, Sender CE-ID: %u, Receiver CE-ID: %u" \
-                           "\n\t      Encapsulation Type: %s (%u)",
-                           bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->rd),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->sender_ce_id),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->receiver_ce_id),
-                           tok2str(l2vpn_encaps_values,
-                                   "unknown",
-                                   EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)));
-
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 14) {
+                        ND_PRINT((ndo, "\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((ndo, "\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),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->sender_ve_id),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->receiver_ve_id),
+                               tok2str(mpls_pw_types_values,
+                                       "unknown",
+                                       EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)),
+                               EXTRACT_16BITS(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_L2VPN_VCID_OLD:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old = \
-                        (const struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_old_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      Remote PE: %s" \
-                           "\n\t      VC-ID: 0x%08x, Encapsulation Type: %s (%u)",
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->remote_pe_address),
-                           EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->vc_id),
-                           tok2str(l2vpn_encaps_values,
-                                   "unknown",
-                                   EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->encapsulation)),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->encapsulation)));
-
+                case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD:
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 10) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      Remote PE: %s" \
+                               "\n\t      PW ID: 0x%08x, PW Type: %s (%u)",
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->remote_pe_address),
+                               EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_id),
+                               tok2str(mpls_pw_types_values,
+                                       "unknown",
+                                       EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type)),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type)));
+                    }
                     break;
 
-                case LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID:
-                    subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid = \
-                        (const struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t *)subtlv_tptr;
-                    ND_PRINT((ndo, "\n\t      Sender PE: %s, Remote PE: %s" \
-                           "\n\t      VC-ID: 0x%08x, Encapsulation Type: %s (%u)",
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->sender_pe_address),
-                           ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->remote_pe_address),
-                           EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->vc_id),
-                           tok2str(l2vpn_encaps_values,
-                                   "unknown",
-                                   EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->encapsulation)),
-                           EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->encapsulation)));
-
+                case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW:
+                    /* Is the subTLV length correct? */
+                    if (lspping_subtlv_len != 14) {
+                        ND_PRINT((ndo, "\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((ndo, "\n\t      Sender PE: %s, Remote PE: %s" \
+                               "\n\t      PW ID: 0x%08x, PW Type: %s (%u)",
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->sender_pe_address),
+                               ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->remote_pe_address),
+                               EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_id),
+                               tok2str(mpls_pw_types_values,
+                                       "unknown",
+                                       EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type)),
+                               EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type)));
+                    }
                     break;
 
                 default:
@@ -749,35 +856,62 @@ lspping_print(netdissect_options *ndo,
                     break;
                 }
                 /* do we want to see an additionally subtlv hexdump ? */
+            subtlv_too_short:
                 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((ndo, "\n\t\t TLV is too short"));
+                        return;
+                    }
+                }
                 tlv_tptr+=lspping_subtlv_len;
                 tlv_tlen-=lspping_subtlv_len+sizeof(struct lspping_tlv_header);
             }
             break;
 
         case LSPPING_TLV_DOWNSTREAM_MAPPING:
+            /* Does the header go past the end of the TLV? */
+            if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_t)) {
+                ND_PRINT((ndo, "\n\t      TLV is too short"));
+                goto map_tlv_tooshort;
+            }
+            /* Did we capture enough to get the address family? */
+            ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_t));
+
+            tlv_ptr.lspping_tlv_downstream_map= \
+                (const struct lspping_tlv_downstream_map_t *)tlv_tptr;
+
             /* that strange thing with the downstream map TLV is that until now
-             * we do not know if its IPv4 or IPv6 , after we found the address-type
-             * lets recast the tlv_tptr and move on */
+             * we do not know if its IPv4 or IPv6 or is unnumbered; after
+             * we find the address-type, we recast the tlv_tptr and move on. */
 
-            tlv_ptr.lspping_tlv_downstream_map_ipv4= \
-                (const struct lspping_tlv_downstream_map_ipv4_t *)tlv_tptr;
-            tlv_ptr.lspping_tlv_downstream_map_ipv6= \
-                (const struct lspping_tlv_downstream_map_ipv6_t *)tlv_tptr;
             ND_PRINT((ndo, "\n\t    MTU: %u, Address-Type: %s (%u)",
-                   EXTRACT_16BITS(tlv_ptr.lspping_tlv_downstream_map_ipv4->mtu),
+                   EXTRACT_16BITS(tlv_ptr.lspping_tlv_downstream_map->mtu),
                    tok2str(lspping_tlv_downstream_addr_values,
                            "unknown",
-                           tlv_ptr.lspping_tlv_downstream_map_ipv4->address_type),
-                   tlv_ptr.lspping_tlv_downstream_map_ipv4->address_type));
+                           tlv_ptr.lspping_tlv_downstream_map->address_type),
+                   tlv_ptr.lspping_tlv_downstream_map->address_type));
 
-            switch(tlv_ptr.lspping_tlv_downstream_map_ipv4->address_type) {
+            switch(tlv_ptr.lspping_tlv_downstream_map->address_type) {
 
             case LSPPING_AFI_IPV4:
+                /* Does the data go past the end of the TLV? */
+                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv4_t)) {
+                    ND_PRINT((ndo, "\n\t      TLV is too short"));
+                    goto map_tlv_tooshort;
+                }
+                /* Did we capture enough for this part of the TLV? */
+                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv4_t));
+
+                tlv_ptr.lspping_tlv_downstream_map_ipv4= \
+                    (const struct lspping_tlv_downstream_map_ipv4_t *)tlv_tptr;
                 ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
                        "\n\t    Downstream Interface IP: %s",
                        ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_ip),
@@ -785,7 +919,35 @@ lspping_print(netdissect_options *ndo,
                 tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
                 tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
                 break;
-             case LSPPING_AFI_IPV6:
+            case LSPPING_AFI_IPV4_UNMB:
+                /* Does the data go past the end of the TLV? */
+                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t)) {
+                    ND_PRINT((ndo, "\n\t      TLV is too short"));
+                    goto map_tlv_tooshort;
+                }
+                /* Did we capture enough for this part of the TLV? */
+                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t));
+
+                tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb= \
+                    (const struct lspping_tlv_downstream_map_ipv4_unmb_t *)tlv_tptr;
+                ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
+                       "\n\t    Downstream Interface Index: 0x%08x",
+                       ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb->downstream_ip),
+                       EXTRACT_32BITS(tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb->downstream_interface)));
+                tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t);
+                tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t);
+                break;
+            case LSPPING_AFI_IPV6:
+                /* Does the data go past the end of the TLV? */
+                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv6_t)) {
+                    ND_PRINT((ndo, "\n\t      TLV is too short"));
+                    goto map_tlv_tooshort;
+                }
+                /* Did we capture enough for this part of the TLV? */
+                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv6_t));
+
+                tlv_ptr.lspping_tlv_downstream_map_ipv6= \
+                    (const struct lspping_tlv_downstream_map_ipv6_t *)tlv_tptr;
                 ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
                        "\n\t    Downstream Interface IP: %s",
                        ip6addr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv6->downstream_ip),
@@ -793,13 +955,23 @@ lspping_print(netdissect_options *ndo,
                 tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv6_t);
                 tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv6_t);
                 break;
-            case LSPPING_AFI_UNMB:
+             case LSPPING_AFI_IPV6_UNMB:
+                /* Does the data go past the end of the TLV? */
+                if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t)) {
+                    ND_PRINT((ndo, "\n\t      TLV is too short"));
+                    goto map_tlv_tooshort;
+                }
+                /* Did we capture enough for this part of the TLV? */
+                ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t));
+
+                tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb= \
+                   (const struct lspping_tlv_downstream_map_ipv6_unmb_t *)tlv_tptr;
                 ND_PRINT((ndo, "\n\t    Downstream IP: %s" \
                        "\n\t    Downstream Interface Index: 0x%08x",
-                       ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_ip),
-                       EXTRACT_32BITS(tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_interface)));
-                tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
-                tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
+                       ip6addr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb->downstream_ip),
+                       EXTRACT_32BITS(tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb->downstream_interface)));
+                tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t);
+                tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t);
                 break;
 
             default:
@@ -807,37 +979,51 @@ lspping_print(netdissect_options *ndo,
                 break;
             }
 
+            /* Does the data go past the end of the TLV? */
+            if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_info_t)) {
+                ND_PRINT((ndo, "\n\t      TLV is too short"));
+                goto map_tlv_tooshort;
+            }
+            /* Did we capture enough for this part of the TLV? */
+            ND_TCHECK2(*tlv_tptr, sizeof(struct lspping_tlv_downstream_map_info_t));
+
             tlv_ptr.lspping_tlv_downstream_map_info= \
                 (const struct lspping_tlv_downstream_map_info_t *)tlv_tptr;
 
             /* FIXME add hash-key type, depth limit, multipath processing */
 
-
             tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_info_t);
             tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_info_t);
 
             /* FIXME print downstream labels */
 
-
+        map_tlv_tooshort:
             tlv_hexdump=TRUE; /* dump the TLV until code complete */
 
             break;
 
         case LSPPING_TLV_BFD_DISCRIMINATOR:
-            tptr += sizeof(struct lspping_tlv_header);
-            ND_TCHECK2(*tptr, LSPPING_TLV_BFD_DISCRIMINATOR_LEN);
-            ND_PRINT((ndo, "\n\t    BFD Discriminator 0x%08x", EXTRACT_32BITS(tptr)));
+            if (tlv_tlen < LSPPING_TLV_BFD_DISCRIMINATOR_LEN) {
+                ND_PRINT((ndo, "\n\t      TLV is too short"));
+            } else {
+                ND_TCHECK2(*tptr, LSPPING_TLV_BFD_DISCRIMINATOR_LEN);
+                ND_PRINT((ndo, "\n\t    BFD Discriminator 0x%08x", EXTRACT_32BITS(tptr)));
+            }
             break;
 
         case  LSPPING_TLV_VENDOR_ENTERPRISE:
         {
             uint32_t vendor_id;
 
-            ND_TCHECK2(*tptr, LSPPING_TLV_VENDOR_ENTERPRISE_LEN);
-            vendor_id = EXTRACT_32BITS(tlv_tptr);
-            ND_PRINT((ndo, "\n\t    Vendor: %s (0x%04x)",
-                   tok2str(smi_values, "Unknown", vendor_id),
-                   vendor_id));
+            if (tlv_tlen < LSPPING_TLV_VENDOR_ENTERPRISE_LEN) {
+                ND_PRINT((ndo, "\n\t      TLV is too short"));
+            } else {
+                ND_TCHECK2(*tptr, LSPPING_TLV_VENDOR_ENTERPRISE_LEN);
+                vendor_id = EXTRACT_32BITS(tlv_tptr);
+                ND_PRINT((ndo, "\n\t    Vendor: %s (0x%04x)",
+                       tok2str(smi_values, "Unknown", vendor_id),
+                       vendor_id));
+            }
         }
             break;
 
@@ -863,14 +1049,21 @@ lspping_print(netdissect_options *ndo,
         /* All TLVs are aligned to four octet boundary */
         if (lspping_tlv_len % 4) {
             lspping_tlv_len += (4 - lspping_tlv_len % 4);
+            /* Does the TLV, including padding, go past the end of the packet? */
+            if (tlen < lspping_tlv_len+sizeof(struct lspping_tlv_header))
+                goto tooshort;
         }
 
         tptr+=lspping_tlv_len+sizeof(struct lspping_tlv_header);
         tlen-=lspping_tlv_len+sizeof(struct lspping_tlv_header);
     }
     return;
+tooshort:
+    ND_PRINT((ndo, "\n\t\t packet is too short"));
+    return;
 trunc:
     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
+    return;
 }
 /*
  * Local Variables: