Apparently bit 0x80 of a SAMR domain handle is the permission to look
[metze/wireshark/wip.git] / packet-ldp.c
index e7667beaeb3d683c9e57a5980ad2b015e5bf673f..e3c665cb2067b5a8d2b5a46c66c6ea7fcab31116 100644 (file)
@@ -1,10 +1,13 @@
 /* packet-ldp.c
  * Routines for LDP (RFC 3036) packet disassembly
  *
- * $Id: packet-ldp.c,v 1.30 2002/03/16 23:15:45 guy Exp $
- * 
+ * $Id: packet-ldp.c,v 1.43 2002/08/28 21:00:20 jmayer Exp $
+ *
  * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
  *
+ * CRLDP (RFC3212) is now supported
+ *   - (c) 2002 Michael Rozhavsky <mike[AT]tochna.technion.ac.il>
+ *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1999 Gerald Combs
 #include "config.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -47,6 +42,8 @@
 #include "prefs.h"
 #include "afn.h"
 
+#include "packet-frame.h"
+
 #define TCP_PORT_LDP 646
 #define UDP_PORT_LDP 646
 
@@ -107,6 +104,7 @@ static int hf_ldp_tlv_returned_msg_ubit = -1;
 static int hf_ldp_tlv_returned_msg_type = -1;
 static int hf_ldp_tlv_returned_msg_len = -1;
 static int hf_ldp_tlv_returned_msg_id = -1;
+static int hf_ldp_tlv_mac = -1;
 static int hf_ldp_tlv_sess_ver = -1;
 static int hf_ldp_tlv_sess_ka = -1;
 static int hf_ldp_tlv_sess_advbit = -1;
@@ -135,13 +133,43 @@ static int hf_ldp_tlv_fec_vc_controlword = -1;
 static int hf_ldp_tlv_fec_vc_vctype = -1;
 static int hf_ldp_tlv_fec_vc_infolength = -1;
 static int hf_ldp_tlv_fec_vc_groupid = -1;
-static int hf_ldp_tlv_fec_vc_vcid = -1; 
+static int hf_ldp_tlv_fec_vc_vcid = -1;
 static int hf_ldp_tlv_fec_vc_intparam_length = -1;
 static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
 static int hf_ldp_tlv_fec_vc_intparam_id = -1;
 static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
 static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
 static int hf_ldp_tlv_fec_vc_intparam_cembytes = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vpnid_oui = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vpnid_index = -1;
+static int hf_ldp_tlv_lspid_act_flg = -1;
+static int hf_ldp_tlv_lspid_cr_lsp = -1;
+static int hf_ldp_tlv_lspid_ldpid = -1;
+static int hf_ldp_tlv_er_hop_loose = -1;
+static int hf_ldp_tlv_er_hop_prelen = -1;
+static int hf_ldp_tlv_er_hop_prefix4 = -1;
+static int hf_ldp_tlv_er_hop_prefix6 = -1;
+static int hf_ldp_tlv_er_hop_as = -1;
+static int hf_ldp_tlv_er_hop_cr_lsp = -1;
+static int hf_ldp_tlv_er_hop_ldpid = -1;
+static int hf_ldp_tlv_flags_reserv = -1;
+static int hf_ldp_tlv_flags_weight = -1;
+static int hf_ldp_tlv_flags_ebs = -1;
+static int hf_ldp_tlv_flags_cbs = -1;
+static int hf_ldp_tlv_flags_cdr = -1;
+static int hf_ldp_tlv_flags_pbs = -1;
+static int hf_ldp_tlv_flags_pdr = -1;
+static int hf_ldp_tlv_frequency = -1;
+static int hf_ldp_tlv_pdr = -1;
+static int hf_ldp_tlv_pbs = -1;
+static int hf_ldp_tlv_cdr = -1;
+static int hf_ldp_tlv_cbs = -1;
+static int hf_ldp_tlv_ebs = -1;
+static int hf_ldp_tlv_weight = -1;
+static int hf_ldp_tlv_set_prio = -1;
+static int hf_ldp_tlv_hold_prio = -1;
+static int hf_ldp_tlv_route_pinning = -1;
+static int hf_ldp_tlv_resource_class = -1;
 static int ett_ldp = -1;
 static int ett_ldp_header = -1;
 static int ett_ldp_ldpid = -1;
@@ -181,17 +209,28 @@ static int global_ldp_udp_port = UDP_PORT_LDP;
 #define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
 #define TLV_CONFIGURATION_SEQNO    0x0402
 #define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
+#define TLV_MAC                    0x0404
 #define TLV_COMMON_SESSION_PARMS   0x0500
 #define TLV_ATM_SESSION_PARMS      0x0501
 #define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
 #define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
+#define TLV_ER                     0x0800
+#define TLV_ER_HOP_IPV4            0x0801
+#define TLV_ER_HOP_IPV6            0x0802
+#define TLV_ER_HOP_AS              0x0803
+#define TLV_ER_HOP_LSPID           0x0804
+#define TLV_TRAFFIC_PARAM          0x0810
+#define TLV_PREEMPTION             0x0820
+#define TLV_LSPID                  0x0821
+#define TLV_RESOURCE_CLASS         0x0822
+#define TLV_ROUTE_PINNING          0x0823
 
 #define TLV_VENDOR_PRIVATE_START   0x3E00
 #define TLV_VENDOR_PRIVATE_END     0x3EFF
 #define TLV_EXPERIMENTAL_START     0x3F00
 #define TLV_EXPERIMENTAL_END       0x3FFF
 
-static const value_string tlv_type_names[] = { 
+static const value_string tlv_type_names[] = {
   { TLV_FEC,                       "Forwarding Equivalence Classes TLV" },
   { TLV_ADDRESS_LIST,              "Address List TLV"},
   { TLV_HOP_COUNT,                 "Hop Count TLV"},
@@ -207,10 +246,21 @@ static const value_string tlv_type_names[] = {
   { TLV_IPV4_TRANSPORT_ADDRESS,    "IPv4 Transport Address TLV"},
   { TLV_CONFIGURATION_SEQNO,       "Configuration Sequence Number TLV"},
   { TLV_IPV6_TRANSPORT_ADDRESS,    "IPv6 Transport Address TLV"},
+  { TLV_MAC,                       "MAC TLV"},
   { TLV_COMMON_SESSION_PARMS,      "Common Session Parameters TLV"},
   { TLV_ATM_SESSION_PARMS,         "ATM Session Parameters TLV"},
   { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
   { TLV_LABEL_REQUEST_MESSAGE_ID,  "Label Request Message ID TLV"},
+  { TLV_LSPID,                     "LSP ID TLV"},
+  { TLV_ER,                        "Explicit route TLV"},
+  { TLV_ER_HOP_IPV4,               "ER hop IPv4 prefix TLV"},
+  { TLV_ER_HOP_IPV6,               "ER hop IPv6 prefix TLV"},
+  { TLV_ER_HOP_AS,                 "ER hop Autonomous system number prefix TLV"},
+  { TLV_TRAFFIC_PARAM,             "Traffic parameters TLV"},
+  { TLV_PREEMPTION,                "Preemption TLV"},
+  { TLV_ER_HOP_LSPID,              "ER hop LSPID prefix TLV"},
+  { TLV_RESOURCE_CLASS,            "Resource Class (Color) TLV"},
+  { TLV_ROUTE_PINNING,             "Route Pinning TLV"},
   { TLV_VENDOR_PRIVATE_START,  "Vendor Private TLV"},
   { TLV_EXPERIMENTAL_START,    "Experimental TLV"},
   { 0, NULL}
@@ -264,8 +314,8 @@ static const true_false_string hello_targeted_vals = {
 };
 
 static const value_string tlv_unknown_vals[] = {
-  {0, "Known TLV"},
-  {1, "Known TLV"},
+  {0, "Known TLV, do not Forward"},
+  {1, "Known TLV, do Forward"},
   {2, "Unknown TLV, do not Forward"},
   {3, "Unknown TLV, do Forward"},
   {0, NULL}
@@ -274,12 +324,14 @@ static const value_string tlv_unknown_vals[] = {
 #define        WILDCARD_FEC    1
 #define        PREFIX_FEC      2
 #define        HOST_FEC        3
+#define CRLSP_FEC       4
 #define VC_FEC          0x80   /* draft-martini-l2circuit-trans-mpls */
 
 static const value_string fec_types[] = {
   {WILDCARD_FEC, "Wildcard FEC"},
   {PREFIX_FEC, "Prefix FEC"},
   {HOST_FEC, "Host Address FEC"},
+  {CRLSP_FEC, "CR LSP FEC"},
   {VC_FEC, "Virtual Circuit FEC"},
   {0, NULL}
 };
@@ -296,6 +348,7 @@ static const value_string fec_vc_types_vals[] = {
   {0x0009, "ATM VCC cell transport"},
   {0x8008, "CEM"},
   {0x000A, "ATM VPC cell transport"},
+  {0x000B, "Ethernet VPLS"},
   {0, NULL}
 };
 
@@ -305,6 +358,7 @@ static const value_string fec_vc_types_vals[] = {
 #define FEC_VC_INTERFACEPARAM_DESCRIPTION  0x03
 #define FEC_VC_INTERFACEPARAM_CEMBYTES     0x04
 #define FEC_VC_INTERFACEPARAM_CEMOPTIONS   0x05
+#define FEC_VC_INTERFACEPARAM_VPNID        0x06
 
 
 static const value_string fec_vc_interfaceparm[] = {
@@ -312,7 +366,8 @@ static const value_string fec_vc_interfaceparm[] = {
   {FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
   {FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
   {FEC_VC_INTERFACEPARAM_CEMBYTES, "CEM Payload Bytes"},
-  {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"}
+  {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"},
+  {FEC_VC_INTERFACEPARAM_VPNID, "VPN Id"}
 };
 
 static const true_false_string fec_vc_cbit = {
@@ -354,6 +409,36 @@ static const value_string tlv_fr_len_vals[] = {
   {0, NULL}
 };
 
+static const value_string ldp_act_flg_vals[] = {
+  {0, "indicates initial LSP setup"},
+  {1, "indicates modify LSP"},
+  {0, NULL}
+};
+
+static const value_string route_pinning_vals[] = {
+  {0, "route pinning is not requested"},
+  {1, "route pinning is requested"},
+  {0, NULL}
+};
+
+static const value_string ldp_loose_vals[] = {
+  {0, "strict hop"},
+  {1, "loose hop"},
+  {0, NULL}
+};
+
+static const true_false_string tlv_negotiable = {
+  "Negotiable",
+  "Not negotiable"
+};
+
+static const value_string freq_values[] = {
+  {0, "Unspecified"},
+  {1, "Frequent"},
+  {2, "VeryFrequent"},
+  {0, NULL}
+};
+
 static const true_false_string tlv_atm_dirbit = {
   "Bidirectional capability",
   "Unidirectional capability"
@@ -431,7 +516,7 @@ static const value_string tlv_status_data[] = {
 
 /* Dissect FEC TLV */
 
-void
+static void
 dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
@@ -442,12 +527,6 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
        char *str;
 
        if (tree) {
-
-               if( rem < 4 ) {
-                       proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
-                       return;
-               }
-
                ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
                val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
                if(val_tree == NULL) return;
@@ -455,10 +534,11 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                while (rem > 0){
                        switch (tvb_get_guint8(tvb, offset)) {
                        case WILDCARD_FEC:
-                               ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
+                       case CRLSP_FEC:
+                               ti = proto_tree_add_text(val_tree, tvb, offset, 1, "FEC Element %u", ix);
                                fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
                                if(fec_tree == NULL) return;
-                               proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 4, FALSE);
+                               proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 1, FALSE);
                                rem -= 1;
                                offset += 1;
                                break;
@@ -471,7 +551,7 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                                family=tvb_get_ntohs(tvb, offset+1);
                                prefix_len=tvb_get_guint8(tvb, offset+3);
                                prefix_len_octets=(prefix_len+7)/8;
-                               
+
                                implemented=1;
                                switch(family) {
                                        case AFNUM_INET: /*IPv4*/
@@ -489,7 +569,7 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                                if( !implemented ) {
                                        guint16 noctets;
-                                       
+
                                        noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
                                        proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
                                        offset+=noctets;
@@ -514,8 +594,8 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                                proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
                                offset += 1;
-                               
-                               
+
+
                                if( addr_size < prefix_len_octets) {
                                        offset+=addr_size;
                                        rem-=addr_size;
@@ -528,7 +608,7 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                                        fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
                                        return;
                                }
-                               
+
                                for(ax=0; ax+1 <= prefix_len_octets; ax++)
                                        addr[ax]=tvb_get_guint8(tvb, offset+ax);
                                if( prefix_len % 8 )
@@ -536,7 +616,7 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                                str = (* (char* (*)(guint8 *))str_handler)(addr);
                                proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
-                               
+
                                offset += prefix_len_octets;
                                rem -= 4+prefix_len_octets;
                                g_free(addr);
@@ -567,7 +647,7 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                                if( !implemented ) {
                                        guint16 noctets;
-                                       
+
                                        noctets= rem>4+host_len?4+host_len:rem;
                                        proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
                                        offset+=noctets;
@@ -592,8 +672,8 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                                proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
                                offset += 1;
-                               
-                               
+
+
                                if( addr_size != host_len) {
                                        offset+=addr_size;
                                        rem-=addr_size;
@@ -606,13 +686,13 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                                        fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
                                        return;
                                }
-                               
+
                                for(ax=0; ax+1 <= host_len; ax++)
                                        addr[ax]=tvb_get_guint8(tvb, offset+ax);
 
                                str = (* (char* (*)(guint8 *))str_handler)(addr);
                                proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
-                               
+
                                offset += host_len;
                                rem -= 4+host_len;
                                g_free(addr);
@@ -636,12 +716,12 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                          proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
                          rem -=8;
                          offset +=8;
-                         
+
                          if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
                            proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
                            proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
 
-                         } else {                 
+                         } else {
                            proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
                            return;
                          }
@@ -651,7 +731,7 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                          while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
                            intparam_len = tvb_get_guint8(tvb, offset+1);
-                           ti = proto_tree_add_text(fec_tree, tvb, offset, 4, "Interface Paramameter");
+                           ti = proto_tree_add_text(fec_tree, tvb, offset, intparam_len, "Interface Paramameter");
                            vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
                            if(vcintparam_tree == NULL) return;
                            proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
@@ -677,6 +757,12 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                              proto_item_append_text(ti,": CEM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
                              proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cembytes,tvb, offset+2, 2, FALSE);
                              break;
+                           case FEC_VC_INTERFACEPARAM_VPNID:
+                             /* draft-lasserre-tls-mpls-00.txt */
+                             proto_item_append_text(ti,": VPN Id");
+                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vpnid_oui, tvb, offset+2, 3, FALSE);
+                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vpnid_index, tvb, offset+5, 4, FALSE);
+                             break;
                            case FEC_VC_INTERFACEPARAM_CEMOPTIONS:
                                /* draft-malis-sonet-ces-mpls CEM options still undefined */
                            default: /* unknown */
@@ -708,7 +794,7 @@ dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
 /* Dissect Address List TLV */
 
-void
+static void
 dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
@@ -720,7 +806,8 @@ dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
        if (tree) {
                if( rem < 2 ) {
                        proto_tree_add_text(tree, tvb, offset, rem,
-                                        "Error processing TLV");
+                           "Error processing Address List TLV: length is %d, should be >= 2",
+                           rem);
                        return;
                }
 
@@ -761,23 +848,24 @@ dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                        str = (* (char* (*)(guint8 *))str_handler)(addr);
                        proto_tree_add_string_format(val_tree,
-                       hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
-                       "Address %u : %s", ix, str);
+                           hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
+                           "Address %u: %s", ix, str);
                }
                if(rem)
                        proto_tree_add_text(val_tree, tvb, offset, rem,
-                                        "Error processing TLV");
+                           "Error processing TLV: Extra data at end of address list");
                g_free(addr);
        }
 }
 
 /* Dissect Path Vector TLV */
 
-void
+static void
 dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
-       guint8  ix, *addr;
+       guint8  ix;
+       guint32 addr;
 
        if (tree) {
                ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
@@ -786,22 +874,21 @@ dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                if(val_tree == NULL) return;
 
                for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
-                       if( (addr=(guint8 *)tvb_get_ptr(tvb, offset, 4))
-                                                        == NULL)
-                               break;
-                       proto_tree_add_ipv4_format(val_tree, hf_ldp_tlv_pv_lsrid, tvb,
-                       offset, 4, tvb_get_ntohl(tvb, offset), "LSR Id %u : %s", ix,
-                       ip_to_str(addr));
+                       tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
+                       proto_tree_add_ipv4_format(val_tree,
+                           hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
+                           addr, "LSR Id %u: %s", ix,
+                           ip_to_str((guint8 *)&addr));
                }
                if(rem)
                        proto_tree_add_text(val_tree, tvb, offset, rem,
-                                        "Error processing TLV");
+                           "Error processing TLV: Extra data at end of path vector");
        }
 }
 
 /* Dissect ATM Label TLV */
 
-void
+static void
 dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
@@ -809,7 +896,9 @@ dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
        if(tree) {
                if(rem != 4){
-                       proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing ATM Label TLV: length is %d, should be 4",
+                           rem);
                        return;
                }
                ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
@@ -819,16 +908,16 @@ dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
 
                id=tvb_get_ntohs(tvb, offset)&0x0FFF;
-               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id); 
-                       
+               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id);
+
                id=tvb_get_ntohs(tvb, offset+2);
-               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id); 
+               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id);
        }
 }
 
 /* Dissect FRAME RELAY Label TLV */
 
-void
+static void
 dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
@@ -837,7 +926,9 @@ dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
        if(tree) {
                if(rem != 4){
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Frame Relay Label TLV: length is %d, should be 4",
+                           rem);
                        return;
                }
                ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
@@ -845,17 +936,17 @@ dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                if(val_tree == NULL) return;
 
                len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
-               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_fr_label_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len); 
+               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_fr_label_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
 
                id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
-               proto_tree_add_uint_format(val_tree, 
-               hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id); 
+               proto_tree_add_uint_format(val_tree,
+               hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id);
        }
 }
 
 /* Dissect STATUS TLV */
 
-void
+static void
 dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
@@ -863,7 +954,9 @@ dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
        if(tree) {
                if(rem != 10){
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Status TLV: length is %d, should be 10",
+                           rem);
                        return;
                }
 
@@ -871,37 +964,39 @@ dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
                if(val_tree == NULL) return;
 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE); 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE); 
+               proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE);
+               proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE);
 
                data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
-               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_status_data, tvb, offset, 4, data, "Status Data: %s (0x%X)", val_to_str(data, tlv_status_data, "Unknown Status Data"), data); 
+               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_status_data, tvb, offset, 4, data, "Status Data: %s (0x%X)", val_to_str(data, tlv_status_data, "Unknown Status Data"), data);
 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE); 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE); 
+               proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE);
+               proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE);
        }
 }
 
 /* Dissect Returned PDU TLV */
 
-void
+static void
 dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
 
        if(tree) {
                if(rem < 10){
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Returned PDU TLV: length is %d, should be >= 10",
+                           rem);
                        return;
                }
                ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
                val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
                if(val_tree == NULL) return;
 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE); 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE); 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE); 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE); 
+               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE);
+               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE);
+               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE);
+               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE);
                offset += 10;
                rem -= 10;
 
@@ -914,7 +1009,7 @@ dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
 /* Dissect Returned MESSAGE TLV */
 
-void
+static void
 dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
@@ -922,24 +1017,26 @@ dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int
 
        if(tree) {
                if(rem < 4){
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Returned Message TLV: length is %d, should be >= 4",
+                           rem);
                        return;
                }
                ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
                val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
                if(val_tree == NULL) return;
 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE); 
+               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE);
 
                type=tvb_get_ntohs(tvb, offset)&0x7FFF;
-               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_returned_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type); 
+               proto_tree_add_uint_format(val_tree, hf_ldp_tlv_returned_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
 
-               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE); 
+               proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE);
                offset += 4;
                rem -= 4;
 
                if( rem >= 4  ) { /*have msg_id*/
-                       proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE); 
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE);
                        offset += 4;
                        rem -= 4;
                }
@@ -953,10 +1050,17 @@ dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int
 
 /* Dissect the common hello params */
 
-void 
+static void
+#if 0
 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+#else
+dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree)
+#endif
 {
-       proto_tree *ti = NULL, *val_tree = NULL;
+#if 0
+       proto_tree *ti = NULL;
+#endif
+       proto_tree *val_tree = NULL;
 
        if (tree) {
 #if 0
@@ -967,49 +1071,79 @@ dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, in
                val_tree=tree;
 #endif
                proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
-               proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 1, FALSE);
-               proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 1, FALSE);
+               proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
+               proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 2, FALSE);
                proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
        }
 }
 
+/* Dissect MAC TLV */
+
+static void
+dissect_tlv_mac(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+       guint8  ix;
+       const guint8 *mac;
+
+       if (tree) {
+               ti=proto_tree_add_text(tree, tvb, offset, rem, "MAC addresses");
+               val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree == NULL) return;
+
+               for(ix=1; rem >= 6; ix++, offset += 6, rem -= 6) {
+                       mac = tvb_get_ptr(tvb, offset, 6);
+                       proto_tree_add_ether(val_tree,
+                            hf_ldp_tlv_mac, tvb, offset, 6, mac);
+               }
+               if(rem)
+                       proto_tree_add_text(val_tree, tvb, offset, rem,
+                           "Error processing TLV: Extra data at end of path vector");
+       }
+}
+
+
+
 /* Dissect the common session params */
 
-void 
+static void
 dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL;
 
        if (tree != NULL) {
-               ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
                if( rem != 14) { /*length of Comm Sess Parms tlv*/
-                       proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
-                       return ;
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Common Session Parameters TLV: length is %d, should be 14",
+                           rem);
+                       return;
                }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
                val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
 
                if(val_tree != NULL) {
                        /*Protocol Version*/
-                       proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE); 
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE);
 
                        /*KeepAlive Time*/
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
 
                        /*A bit*/
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
-                                        
+
                        /*D bit*/
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
-                                        
+
                        /*Path Vector Limit*/
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
-                                        
+
                        /*Max PDU Length*/
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
-                                        
+
                        /*Rx LSR*/
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
-                                        
+
                        /*Rx LS*/
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
                }
@@ -1018,7 +1152,7 @@ dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree,
 
 /* Dissect the atm session params */
 
-void 
+static void
 dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
@@ -1028,7 +1162,8 @@ dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int
        if (tree != NULL) {
                if(rem < 4) {
                        proto_tree_add_text(tree, tvb, offset, rem,
-                                                "Error processing TLV");
+                           "Error processing ATM Parameters TLV: length is %d, should be >= 4",
+                           rem);
                        return;
                }
 
@@ -1036,21 +1171,21 @@ dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int
                val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
 
                if(val_tree != NULL) {
-                       proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE); 
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE);
 
-                       /*get the number of label ranges*/      
+                       /*get the number of label ranges*/
                        numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
                        proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
                        tvb, offset, 1, numlr, "Number of Label Range components: %u",
-                       numlr); 
+                       numlr);
 
-                       proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE); 
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE);
 
                        /*move into range components*/
                        offset += 4;
                        rem -= 4;
                        ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
-                                
+
                        if(numlr) {
                                val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
                                if( ! val_tree ) return;
@@ -1064,30 +1199,39 @@ dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int
                                if( lbl_tree == NULL ) break;
 
                                id=tvb_get_ntohs(tvb, offset)&0x0FFF;
-                               proto_tree_add_uint_format(lbl_tree, 
-                       hf_ldp_tlv_sess_atm_minvpi,tvb, offset, 2, id, "Minimum VPI: %u", id); 
+                               proto_tree_add_uint_format(lbl_tree,
+                                   hf_ldp_tlv_sess_atm_minvpi,
+                                   tvb, offset, 2,
+                                   id, "Minimum VPI: %u", id);
                                id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
-                               proto_tree_add_uint_format(lbl_tree, 
-                       hf_ldp_tlv_sess_atm_maxvpi,tvb, (offset+4), 2, id, "Maximum VPI: %u", id); 
-                                
+                               proto_tree_add_uint_format(lbl_tree,
+                                   hf_ldp_tlv_sess_atm_maxvpi,
+                                   tvb, (offset+4), 2, id,
+                                   "Maximum VPI: %u", id);
+
                                id=tvb_get_ntohs(tvb, offset+2);
-                               proto_tree_add_uint_format(lbl_tree, 
-                       hf_ldp_tlv_sess_atm_minvci,tvb, offset+2, 2, id, "Minimum VCI: %u", id); 
+                               proto_tree_add_uint_format(lbl_tree,
+                                   hf_ldp_tlv_sess_atm_minvci,
+                                   tvb, offset+2, 2,
+                                   id, "Minimum VCI: %u", id);
                                id=tvb_get_ntohs(tvb, offset+6);
-                               proto_tree_add_uint_format(lbl_tree, 
-                       hf_ldp_tlv_sess_atm_maxvci,tvb, offset+6, 2, id, "Maximum VCI: %u", id); 
+                               proto_tree_add_uint_format(lbl_tree,
+                                   hf_ldp_tlv_sess_atm_maxvci,
+                                   tvb, offset+6, 2,
+                                   id, "Maximum VCI: %u", id);
 
                                offset += 8;
                        }
                        if( rem || numlr)
-                               proto_tree_add_text(val_tree, tvb, offset, rem,"Error processing TLV");
+                               proto_tree_add_text(val_tree, tvb, offset, rem,
+                                   "Error processing TLV: Extra data at end of TLV");
                }
        }
 }
 
 /* Dissect the frame relay session params */
 
-void 
+static void
 dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
 {
        proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
@@ -1097,7 +1241,8 @@ dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tr
        if (tree != NULL) {
                if(rem < 4) {
                        proto_tree_add_text(tree, tvb, offset, rem,
-                                                "Error processing TLV");
+                           "Error processing Frame Relay Parameters TLV: length is %d, should be >= 4",
+                           rem);
                        return;
                }
 
@@ -1107,16 +1252,16 @@ dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tr
 
                if(val_tree != NULL) {
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
-                               tvb, offset, 1, FALSE); 
+                               tvb, offset, 1, FALSE);
 
-                       /*get the number of label ranges*/      
+                       /*get the number of label ranges*/
                        numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
                        proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
                        tvb, offset, 1, numlr, "Number of Label Range components: %u",
-                       numlr); 
+                       numlr);
 
                        proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
-                                tvb, offset, 1, FALSE); 
+                                tvb, offset, 1, FALSE);
 
                        /*move into range components*/
                        offset += 4;
@@ -1139,21 +1284,332 @@ dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tr
                                if( lbl_tree == NULL ) break;
 
                                len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
-                               proto_tree_add_uint_format(lbl_tree, hf_ldp_tlv_sess_fr_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len); 
+                               proto_tree_add_uint_format(lbl_tree, hf_ldp_tlv_sess_fr_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
 
                                id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
-                               proto_tree_add_uint_format(lbl_tree, 
-                       hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id); 
+                               proto_tree_add_uint_format(lbl_tree,
+                       hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id);
                                id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
-                               proto_tree_add_uint_format(lbl_tree, 
-                       hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id); 
+                               proto_tree_add_uint_format(lbl_tree,
+                       hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id);
 
                                offset += 8;
                        }
 
                        if( rem || numlr)
                                proto_tree_add_text(val_tree, tvb, offset, rem,
-                                "Error processing TLV");
+                                "Error processing TLV: Extra data at end of TLV");
+               }
+       }
+}
+
+
+static void
+dissect_tlv_lspid(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+       if (tree != NULL) {
+               if(rem != 8) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing LSP ID TLV: length is %d, should be 8",
+                           rem);
+                       return;
+               }
+
+               ti = proto_tree_add_text(tree, tvb, offset, rem,
+                                               "LSP ID");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_act_flg,
+                                          tvb, offset, 2, FALSE);
+                       offset += 2;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_cr_lsp,
+                                          tvb, offset, 2, FALSE);
+                       offset += 2;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_ldpid,
+                                          tvb, offset, 4, FALSE);
+               }
+       }
+}
+
+static void
+dissect_tlv_er_hop_ipv4(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+
+       if (tree != NULL) {
+               if(rem != 8) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing ER HOP IPv4 TLV: length is %d, should be 8",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv4");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+                                          tvb, offset, 3, FALSE);
+                       offset += 3;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
+                                          tvb, offset, 1, FALSE);
+                       offset ++;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix4,
+                                          tvb, offset, 4, FALSE);
+               }
+       }
+}
+
+static void
+dissect_tlv_er_hop_ipv6(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+       if (tree != NULL) {
+               if(rem != 20) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing ER HOP IPv6 TLV: length is %d, should be 20",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv6");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+                                          tvb, offset, 3, FALSE);
+                       offset += 3;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
+                                         tvb, offset, 1, FALSE);
+                       offset ++;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix6,
+                                          tvb, offset, 16, FALSE);
+               }
+       }
+}
+
+static void
+dissect_tlv_er_hop_as(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+       if (tree != NULL) {
+               if(rem != 4) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing ER HOP AS TLV: length is %d, should be 4",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP AS");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+                                          tvb, offset, 2, FALSE);
+                       offset += 2;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_as,
+                                          tvb, offset, 2, FALSE);
+               }
+       }
+}
+
+static void
+dissect_tlv_er_hop_lspid(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+       if (tree != NULL) {
+               if(rem != 8) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing ER HOP LSPID TLV: length is %d, should be 8",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP LSPID");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+                                          tvb, offset, 2, FALSE);
+                       offset += 2;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_cr_lsp,
+                                          tvb, offset, 2, FALSE);
+                       offset += 2;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_ldpid,
+                                          tvb, offset, 4, FALSE);
+               }
+       }
+}
+
+static void
+dissect_tlv_traffic(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+       guint8  val_8;
+       float   val_f;
+       proto_item *pi;
+
+       if (tree != NULL) {
+               if(rem != 24) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Traffic Parameters TLV: length is %d, should be 24",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "Traffic parameters");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       /* flags */
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_flags_reserv, tvb, offset, 1, FALSE);
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_flags_weight, tvb, offset, 1, FALSE);
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_flags_ebs, tvb, offset, 1, FALSE);
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cbs, tvb, offset, 1, FALSE);
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cdr, tvb, offset, 1, FALSE);
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pbs, tvb, offset, 1, FALSE);
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pdr, tvb, offset, 1, FALSE);
+
+                       offset ++;
+                       /* frequency */
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_frequency, tvb, offset, 1, FALSE);
+                       offset ++;
+
+                       /* reserver byte */
+                       offset ++;
+
+                       /* weight */
+                       pi = proto_tree_add_item(val_tree, hf_ldp_tlv_weight, tvb, offset, 1, FALSE);
+                       val_8 = tvb_get_guint8(tvb, offset);
+                       if (val_8 == 0)
+                               proto_item_set_text(pi, "Weight: Not applicable");
+                       offset ++;
+
+                       /* PDR */
+                       val_f = tvb_get_ntohieee_float (tvb, offset);
+                       proto_tree_add_double_format(val_tree, hf_ldp_tlv_pdr, tvb, offset,
+                                                   4, val_f, "PDR: %.10g Bps", val_f);
+                       offset += 4;
+                       /* PBS */
+                       val_f = tvb_get_ntohieee_float (tvb, offset);
+                       proto_tree_add_double_format(val_tree, hf_ldp_tlv_pbs, tvb, offset,
+                                                   4, val_f, "PBS: %.10g Bytes", val_f);
+                       offset += 4;
+
+                       /* CDR */
+                       val_f = tvb_get_ntohieee_float (tvb, offset);
+                       proto_tree_add_double_format(val_tree, hf_ldp_tlv_cdr, tvb, offset,
+                                                   4, val_f, "CDR: %.10g Bps", val_f);
+                       offset += 4;
+
+                       /* CBS */
+                       val_f = tvb_get_ntohieee_float (tvb, offset);
+                       proto_tree_add_double_format(val_tree, hf_ldp_tlv_cbs, tvb, offset,
+                                                   4, val_f, "CBS: %.10g Bytes", val_f);
+                       offset += 4;
+
+                       /* EBS */
+                       val_f = tvb_get_ntohieee_float (tvb, offset);
+                       proto_tree_add_double_format(val_tree, hf_ldp_tlv_ebs, tvb, offset,
+                                                   4, val_f, "EBS: %.10g Bytes", val_f);
+
+               }
+       }
+}
+
+static void
+dissect_tlv_route_pinning(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+       if (tree != NULL) {
+               if(rem != 4) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Route Pinning TLV: length is %d, should be 4",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "Route Pinning");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_route_pinning,
+                                          tvb, offset, 4, FALSE);
+               }
+       }
+}
+
+
+static void
+dissect_tlv_resource_class(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+       if (tree != NULL) {
+               if(rem != 4) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Resource Class TLV: length is %d, should be 4",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "Resource Class");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_resource_class,
+                                          tvb, offset, 4, FALSE);
+               }
+       }
+}
+
+
+static void
+dissect_tlv_preemption(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+
+       if (tree != NULL) {
+               if(rem != 4) {
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Preemption TLV: length is %d, should be 4",
+                           rem);
+                       return;
+               }
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "Preemption");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_set_prio,
+                                          tvb, offset, 1, FALSE);
+                       offset += 1;
+                       proto_tree_add_item(val_tree, hf_ldp_tlv_hold_prio,
+                                          tvb, offset, 1, FALSE);
+               }
+       }
+}
+
+static int
+dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem);
+
+static void
+dissect_tlv_er(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+       proto_tree *ti = NULL, *val_tree = NULL;
+       int len;
+
+       if (tree != NULL) {
+               ti = proto_tree_add_text(tree, tvb, offset, rem, "Explicit route");
+               val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+               if(val_tree != NULL) {
+                       len = 0;
+                       while (rem > 0) {
+                               len = dissect_tlv (tvb, offset, val_tree, rem);
+                               offset += len;
+                               rem -= len;
+                       }
                }
        }
 }
@@ -1161,7 +1617,7 @@ dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tr
 
 /* Dissect a TLV and return the number of bytes consumed ... */
 
-int
+static int
 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
        guint16 type, typebak;
@@ -1173,7 +1629,9 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
        if( rem < 4 ) {/*chk for minimum header*/
                if(tree)
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing TLV: length is %d, should be >= 4",
+                           rem);
                return rem;
        }
        type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
@@ -1185,12 +1643,12 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
        if (tree != NULL) {
                /*chk for vendor-private*/
                if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
-                       typebak=type;           /*keep type*/   
+                       typebak=type;           /*keep type*/
                        type=TLV_VENDOR_PRIVATE_START;
 
                /*chk for experimental*/
                } else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
-                       typebak=type;           /*keep type*/   
+                       typebak=type;           /*keep type*/
                        type=TLV_EXPERIMENTAL_START;
                }
 
@@ -1201,7 +1659,7 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
 
-               proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_type, tvb, offset, 2, type, "TLV Type: %s (0x%X)", val_to_str(type, tlv_type_names, "Unknown TLV type"), type ); 
+               proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_type, tvb, offset, 2, type, "TLV Type: %s (0x%X)", val_to_str(type, tlv_type_names, "Unknown TLV type"), type );
 
                proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
 
@@ -1217,9 +1675,11 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                case TLV_HOP_COUNT:
                        if( length != 1 ) /*error, only one byte*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4,length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4,length,
+                                   "Error processing Hop Count TLV: length is %d, should be 1",
+                                   length);
                        else
-                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE); 
+                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE);
                        break;
 
                case TLV_PATH_VECTOR:
@@ -1228,12 +1688,14 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                case TLV_GENERIC_LABEL:
                        if( length != 4 ) /*error, need only label*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing Generic Label TLV: length is %d, should be 4",
+                                   length);
                        else {
                                guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
 
                                proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
-                                       tvb, offset+4, length, label, "Generic Label: %u", label); 
+                                       tvb, offset+4, length, label, "Generic Label: %u", label);
                        }
                        break;
 
@@ -1251,9 +1713,11 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                case TLV_EXTENDED_STATUS:
                        if( length != 4 ) /*error, need only status_code(guint32)*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing Extended Status TLV: length is %d, should be 4",
+                                   length);
                        else {
-                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE); 
+                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE);
                        }
                        break;
 
@@ -1266,12 +1730,18 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
                        break;
 
                case TLV_COMMON_HELLO_PARMS:
+#if 0
                        dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
+#else
+                       dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree);
+#endif
                        break;
 
                case TLV_IPV4_TRANSPORT_ADDRESS:
                        if( length != 4 ) /*error, need only ipv4*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing IPv4 Transport Address TLV: length is %d, should be 4",
+                                   length);
                        else {
                                proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
                        }
@@ -1279,7 +1749,9 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                case TLV_CONFIGURATION_SEQNO:
                        if( length != 4 ) /*error, need only seq_num(guint32)*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing Configuration Sequence Number TLV: length is %d, should be 4",
+                                   length);
                        else {
                                proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
                        }
@@ -1287,12 +1759,18 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                case TLV_IPV6_TRANSPORT_ADDRESS:
                        if( length != 16 ) /*error, need only ipv6*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing IPv6 Transport Address TLV: length is %d, should be 16",
+                                   length);
                        else {
                                proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
                        }
                        break;
 
+               case TLV_MAC: /* draft-lasserre-vkompella-ppvpn-vpls-02.txt */
+                       dissect_tlv_mac(tvb, offset + 4, tlv_tree, length);
+                       break;
+
                case TLV_COMMON_SESSION_PARMS:
                        dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
                        break;
@@ -1307,27 +1785,73 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
                case TLV_LABEL_REQUEST_MESSAGE_ID:
                        if( length != 4 ) /*error, need only one msgid*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing Label Request Message ID TLV: length is %d, should be 4",
+                                   length);
                        else
-                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE); 
+                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE);
+                       break;
+
+               case TLV_LSPID:
+                       dissect_tlv_lspid(tvb, offset + 4, tlv_tree, length);
+                       break;
+
+               case TLV_ER:
+                       dissect_tlv_er(tvb, offset + 4, tlv_tree, length);
+                       break;
+
+               case TLV_ER_HOP_IPV4:
+                       dissect_tlv_er_hop_ipv4(tvb, offset + 4, tlv_tree, length);
+                       break;
+
+               case TLV_ER_HOP_IPV6:
+                       dissect_tlv_er_hop_ipv6(tvb, offset +4, tlv_tree, length);
+                       break;
+
+               case TLV_ER_HOP_AS:
+                       dissect_tlv_er_hop_as(tvb, offset + 4, tlv_tree, length);
+                       break;
+
+               case TLV_ER_HOP_LSPID:
+                       dissect_tlv_er_hop_lspid(tvb, offset +4, tlv_tree, length);
+                       break;
+
+               case TLV_TRAFFIC_PARAM:
+                       dissect_tlv_traffic(tvb, offset +4, tlv_tree, length);
+                       break;
+
+               case TLV_PREEMPTION:
+                       dissect_tlv_preemption(tvb, offset +4, tlv_tree, length);
+                       break;
+
+               case TLV_RESOURCE_CLASS:
+                       dissect_tlv_resource_class(tvb, offset +4, tlv_tree, length);
+                       break;
+
+               case TLV_ROUTE_PINNING:
+                       dissect_tlv_route_pinning(tvb, offset +4, tlv_tree, length);
                        break;
 
                case TLV_VENDOR_PRIVATE_START:
                        if( length < 4 ) /*error, at least Vendor ID*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing Vendor Private Start TLV: length is %d, should be >= 4",
+                                   length);
                        else {
-                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE); 
-                               if( length > 4 )  /*have data*/ 
+                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE);
+                               if( length > 4 )  /*have data*/
                                        proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
                        }
                        break;
 
                case TLV_EXPERIMENTAL_START:
                        if( length < 4 ) /*error, at least Experiment ID*/
-                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+                               proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+                                   "Error processing Experimental Start TLV: length is %d, should be >= 4",
+                                   length);
                        else {
-                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE); 
-                               if( length > 4 )  /*have data*/ 
+                               proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE);
+                               if( length > 4 )  /*have data*/
                                        proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
                        }
                        break;
@@ -1344,34 +1868,35 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 
 /* Dissect a Message and return the number of bytes consumed ... */
 
-int
-dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem)
+static int
+dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
 {
        guint16 type, typebak;
        guint8  extra=0;
-       int length, ao=0, co;
+       int length, rem, ao=0, co;
        proto_tree *ti = NULL, *msg_tree = NULL;
 
-       length=tvb_reported_length_remaining(tvb, offset);
-       rem=MIN(rem, length);
+       rem=tvb_reported_length_remaining(tvb, offset);
 
        if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
                if( check_col(pinfo->cinfo, COL_INFO) )
                        col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
                if(tree)
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Message: length is %d, should be >= 8",
+                           rem);
                return rem;
        }
        type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
 
        /*chk for vendor-private*/
        if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
-               typebak=type;           /*keep type*/   
+               typebak=type;           /*keep type*/
                type=LDP_VENDOR_PRIVATE_START;
                extra=4;
        /*chk for experimental*/
        } else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
-               typebak=type;           /*keep type*/   
+               typebak=type;           /*keep type*/
                type=LDP_EXPERIMENTAL_MESSAGE_START;
                extra=4;
        }
@@ -1380,10 +1905,12 @@ dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, i
                if( check_col(pinfo->cinfo, COL_INFO) )
                        col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
                if(tree)
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message Length");
+                       proto_tree_add_text(tree, tvb, offset, rem,
+                           "Error processing Message Length: length is %d, should be >= %u",
+                           length, 4+extra);
                return rem;
        }
-       rem -= 4; 
+       rem -= 4;
        length = MIN(length, rem);  /* Don't go haywire if a problem ... */
 
        if( check_col(pinfo->cinfo, COL_INFO) ){
@@ -1399,7 +1926,7 @@ dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, i
                proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
 
                type=tvb_get_ntohs(tvb, offset)&0x7FFF;
-               proto_tree_add_uint_format(msg_tree, hf_ldp_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type); 
+               proto_tree_add_uint_format(msg_tree, hf_ldp_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
 
                proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
                proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
@@ -1417,135 +1944,238 @@ dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, i
                        proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
                }
        }
-               
+
        offset += (8+extra);
        length -= (4+extra);
-       
-       if( tree )      
+
+       if( tree )
                while( (length-ao) > 0 ) {
                        co=dissect_tlv(tvb, offset, msg_tree, length-ao);
                        offset += co;
                        ao += co;
                }
-       
+
        return length+8+extra;
 }
 
-/* Dissect a PDU and return the number of bytes consumed ... */
-
-int
-dissect_ldp_pdu(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem, guint ix)
+/* Dissect a PDU */
+static void
+dissect_ldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       int length, ao=0, co;
+       int offset = 0, co;
+       int rem, length;
        proto_tree *ti=NULL, *pdu_tree = NULL;
-       
-       length=tvb_reported_length_remaining(tvb, offset);
-       rem=MIN(rem, length);
-       
-       if( rem < 10 ){/*don't even have a PDU header*/
-/*XXX Need changes in desegment_tcp to handle multiple requests*/
-#if 0
-               if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){
-                       pinfo->desegment_offset=offset;
-                       pinfo->desegment_len=10-rem;
-               }
-#else
-               if(tree)
-                       proto_tree_add_text(tree, tvb, offset, rem,"Not enough bytes for PDU Hdr in TCP segment");
-#endif
-               return rem;
-       }
 
-       if( (length = tvb_get_ntohs(tvb, offset + 2)) < 6 ) {/*not enough*/
-               if( check_col(pinfo->cinfo, COL_INFO) && ix )
-                       col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
-               if( check_col(pinfo->cinfo, COL_INFO) ){
-                       col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
-               }
-               if(tree)
-                       proto_tree_add_text(tree, tvb, offset, rem,"Error processing PDU Length");
-               return rem;
-       }
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
 
-       rem -=4;
-       if( length>rem ){
-               if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){/*ask for more*/
-                       pinfo->desegment_offset=offset;
-                       pinfo->desegment_len=length-rem;
-               }else {
-                       if( check_col(pinfo->cinfo, COL_INFO) && ix )
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
-                       if( check_col(pinfo->cinfo, COL_INFO) )
-                               col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
-                       if(tree)
-                               proto_tree_add_text(tree, tvb, offset, rem+4,"Error processing PDU Length");
-               }
-               return rem+4;
-       }
-       
-       if( check_col(pinfo->cinfo, COL_INFO) && ix )
-               col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_clear(pinfo->cinfo, COL_INFO);
 
        if( tree ){
-               ti=proto_tree_add_protocol_format(tree, proto_ldp, tvb, offset,
-                   length+4, ix?"LDP PDU %u":"LDP PDU", ix);
+               ti=proto_tree_add_item(tree, proto_ldp, tvb, 0, -1, FALSE);
                pdu_tree = proto_item_add_subtree(ti, ett_ldp);
-       }
 
-       if(pdu_tree){
                proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
-               proto_tree_add_item(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, FALSE);
+       }
+
+       length = tvb_get_ntohs(tvb, offset+2);
+       if( tree )
+               proto_tree_add_uint(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, length);
+
+       length += 4;    /* add the version and type sizes */
+       rem = tvb_reported_length_remaining(tvb, offset);
+       if (length < rem)
+               tvb_set_reported_length(tvb, length);
+
+       if( tree ){
                proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
                proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
        }
        offset += 10;
-       length -= 6;
 
-       while( (length-ao) > 0 ) {
-               co=dissect_msg(tvb, offset, pinfo, pdu_tree, length-ao);
+       while( tvb_reported_length_remaining(tvb, offset) > 0 ) {
+               co=dissect_msg(tvb, offset, pinfo, pdu_tree);
                offset += co;
-               ao += co;
        }
-       
-       return length+10;
 }
 
-static void
+static int
 dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
+       /*
+        * Make sure the first PDU has a version number of 1;
+        * if not, reject this, so we don't get confused by
+        * packets that happen to be going to or from the
+        * LDP port but that aren't LDP packets.
+        */
+       if (!tvb_bytes_exist(tvb, 0, 2)) {
+               /*
+                * Not enough information to tell.
+                */
+               return 0;
+       }
+       if (tvb_get_ntohs(tvb, 0) != 1) {
+               /*
+                * Not version 1.
+                */
+               return 0;
+       }
 
-       if (check_col(pinfo->cinfo, COL_INFO))
-               col_clear(pinfo->cinfo, COL_INFO);
+       dissect_ldp_pdu(tvb, pinfo, tree);
 
-       dissect_ldp_pdu(tvb, 0, pinfo, tree, tvb_reported_length(tvb), 0);
+       /*
+        * XXX - return minimum of this and the length of the PDU?
+        */
+       return tvb_length(tvb);
 }
 
-static void
+static int
 dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{ 
-       int offset=0, length, rtn;
-       guint ix=1;
-  
+{
+       volatile gboolean first = TRUE;
+       volatile int offset = 0;
+       int length_remaining;
+       guint16 plen;
+       int length;
+       tvbuff_t *next_tvb;
+
+       while (tvb_reported_length_remaining(tvb, offset) != 0) {
+               length_remaining = tvb_length_remaining(tvb, offset);
+
+               /*
+                * Make sure the first PDU has a version number of 1;
+                * if not, reject this, so we don't get confused by
+                * packets that happen to be going to or from the
+                * LDP port but that aren't LDP packets.
+                *
+                * XXX - this means we can't handle an LDP PDU of which
+                * only one byte appears in a TCP segment.  If that's
+                * a problem, we'll either have to completely punt on
+                * rejecting non-LDP packets, or will have to assume
+                * that if we have only one byte, it's an LDP packet.
+                */
+               if (first) {
+                       if (length_remaining < 2) {
+                               /*
+                                * Not enough information to tell.
+                                */
+                               return 0;
+                       }
+                       if (tvb_get_ntohs(tvb, offset) != 1) {
+                               /*
+                                * Not version 1.
+                                */
+                               return 0;
+                       }
+                       first = FALSE;
+               }
 
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
+               /*
+                * Can we do reassembly?
+                */
+               if (ldp_desegment && pinfo->can_desegment) {
+                       /*
+                        * Yes - is the LDP header split across segment
+                        * boundaries?
+                        */
+                       if (length_remaining < 4) {
+                               /*
+                                * Yes.  Tell the TCP dissector where
+                                * the data for this message starts in
+                                * the data it handed us, and how many
+                                * more bytes we need, and return.
+                                */
+                               pinfo->desegment_offset = offset;
+                               pinfo->desegment_len = 4 - length_remaining;
+                               return -pinfo->desegment_len;
+                       }
+               }
 
-       if (check_col(pinfo->cinfo, COL_INFO))
-               col_clear(pinfo->cinfo, COL_INFO);
+               /*
+                * Get the length of the rest of the LDP packet.
+                * XXX - check for a version of 1 first?
+                */
+               plen = tvb_get_ntohs(tvb, offset + 2);
+
+               /*
+                * Can we do reassembly?
+                */
+               if (ldp_desegment && pinfo->can_desegment) {
+                       /*
+                        * Yes - is the LDP packet split across segment
+                        * boundaries?
+                        */
+                       if (length_remaining < plen + 4) {
+                               /*
+                                * Yes.  Tell the TCP dissector where the
+                                * data for this message starts in the data
+                                * it handed us, and how many more bytes we
+                                * need, and return.
+                                */
+                               pinfo->desegment_offset = offset;
+                               pinfo->desegment_len =
+                                   (plen + 4) - length_remaining;
+                               return -pinfo->desegment_len;
+                       }
+               }
+
+               /*
+                * Construct a tvbuff containing the amount of the payload
+                * we have available.  Make its reported length the
+                * amount of data in the DNS-over-TCP packet.
+                *
+                * XXX - if reassembly isn't enabled. the subdissector
+                * will throw a BoundsError exception, rather than a
+                * ReportedBoundsError exception.  We really want
+                * a tvbuff where the length is "length", the reported
+                * length is "plen + 4", and the "if the snapshot length
+                * were infinite" length is the minimum of the
+                * reported length of the tvbuff handed to us and "plen+4",
+                * with a new type of exception thrown if the offset is
+                * within the reported length but beyond that third length,
+                * with that exception getting the "Unreassembled Packet"
+                * error.
+                */
+               length = length_remaining;
+               if (length > plen + 4)
+                       length = plen + 4;
+               next_tvb = tvb_new_subset(tvb, offset, length, plen + 4);
+
+               /*
+                * Dissect the LDP packet.
+                *
+                * Catch the ReportedBoundsError exception; if this
+                * particular message happens to get a ReportedBoundsError
+                * exception, that doesn't mean that we should stop
+                * dissecting LDP messages within this frame or chunk of
+                * reassembled data.
+                *
+                * If it gets a BoundsError, we can stop, as there's nothing
+                * more to see, so we just re-throw it.
+                */
+               TRY {
+                       dissect_ldp_pdu(next_tvb, pinfo, tree);
+               }
+               CATCH(BoundsError) {
+                       RETHROW;
+               }
+               CATCH(ReportedBoundsError) {
+                       show_reported_bounds_error(tvb, pinfo, tree);
+               }
+               ENDTRY;
 
-       length=tvb_reported_length(tvb);
-       while (length > 0){
-               rtn = dissect_ldp_pdu(tvb, offset, pinfo, tree, length, ix++);
-               offset += rtn;
-               length -= rtn;
+               /*
+                * Skip the LDP header and the payload.
+                */
+               offset += plen + 4;
        }
+       return tvb_length(tvb);
 }
 
 /* Register all the bits needed with the filtering engine */
 
-void 
+void
 proto_register_ldp(void)
 {
   static hf_register_info hf[] = {
@@ -1577,19 +2207,19 @@ proto_register_ldp(void)
     { &hf_ldp_msg_len,
       { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
 
-    { &hf_ldp_msg_id, 
+    { &hf_ldp_msg_id,
       { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
 
-    { &hf_ldp_msg_vendor_id, 
+    { &hf_ldp_msg_vendor_id,
       { "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
 
-    { &hf_ldp_msg_experiment_id, 
+    { &hf_ldp_msg_experiment_id,
       { "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
 
-    { &hf_ldp_tlv_unknown, 
+    { &hf_ldp_tlv_unknown,
       { "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
 
-    { &hf_ldp_tlv_type, 
+    { &hf_ldp_tlv_type,
       { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
 
     { &hf_ldp_tlv_len,
@@ -1602,11 +2232,11 @@ proto_register_ldp(void)
       { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
 
     { &hf_ldp_tlv_val_target,
-      { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 8, TFS(&hello_targeted_vals), 0x80, "Hello Common Parameters Targeted Bit", HFILL }},
+      { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 16, TFS(&hello_targeted_vals), 0x8000, "Hello Common Parameters Targeted Bit", HFILL }},
 
     { &hf_ldp_tlv_val_request,
-      { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 8, TFS(&hello_requested_vals), 0x40, "Hello Common Parameters Hello Requested Bit", HFILL }},
+      { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 16, TFS(&hello_requested_vals), 0x4000, "Hello Common Parameters Hello Requested Bit", HFILL }},
+
     { &hf_ldp_tlv_val_res,
       { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
 
@@ -1654,7 +2284,7 @@ proto_register_ldp(void)
 
     { &hf_ldp_tlv_sess_advbit,
       { "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
- FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80, 
+ FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80,
        "Common Session Parameters Label Advertisement Discipline", HFILL }},
 
     { &hf_ldp_tlv_sess_ldetbit,
@@ -1711,7 +2341,7 @@ proto_register_ldp(void)
     { &hf_ldp_tlv_sess_fr_maxdlci,
       { "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
 
-    { &hf_ldp_tlv_lbl_req_msg_id, 
+    { &hf_ldp_tlv_lbl_req_msg_id,
       { "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
 
     { &hf_ldp_tlv_vendor_id,
@@ -1747,7 +2377,7 @@ proto_register_ldp(void)
     { &hf_ldp_tlv_status_data,
       { "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
 
-    { &hf_ldp_tlv_status_msg_id, 
+    { &hf_ldp_tlv_status_msg_id,
       { "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
 
     { &hf_ldp_tlv_status_msg_type,
@@ -1768,7 +2398,7 @@ proto_register_ldp(void)
     { &hf_ldp_tlv_returned_ls_id,
       { "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
 
-    { &hf_ldp_tlv_returned_msg_ubit, 
+    { &hf_ldp_tlv_returned_msg_ubit,
       { "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_UINT8, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
 
     { &hf_ldp_tlv_returned_msg_type,
@@ -1777,9 +2407,12 @@ proto_register_ldp(void)
     { &hf_ldp_tlv_returned_msg_len,
       { "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
 
-    { &hf_ldp_tlv_returned_msg_id, 
+    { &hf_ldp_tlv_returned_msg_id,
       { "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
 
+    { &hf_ldp_tlv_mac,
+      { "MAC address", "ldp.msg.tlv.mac", FT_ETHER, BASE_NONE, NULL, 0x0, "MAC address", HFILL}},
+
     {&hf_ldp_tlv_fec_vc_controlword,
      {"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
 
@@ -1810,9 +2443,98 @@ proto_register_ldp(void)
     { &hf_ldp_tlv_fec_vc_intparam_desc,
       { "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
 
-    {&hf_ldp_tlv_fec_vc_intparam_cembytes,
+    { &hf_ldp_tlv_fec_vc_intparam_cembytes,
      {"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cembytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEM Payload Bytes", HFILL }},
 
+    { &hf_ldp_tlv_fec_vc_intparam_vpnid_oui,
+      { "VPN OUI", "ldp.msg.tlv.fec.vc.intparam.vpnid.oui", FT_UINT24, BASE_HEX, NULL, 0x0, "VC FEC Interface Param VPN OUI", HFILL }},
+
+    { &hf_ldp_tlv_fec_vc_intparam_vpnid_index,
+      { "VPN Index", "ldp.msg.tlv.fec.vc.intparam.vpnid.index", FT_UINT32, BASE_HEX, NULL, 0x0, "VC FEC Interface Param VPN Index", HFILL }},
+
+    { &hf_ldp_tlv_lspid_act_flg,
+      { "Action Indicator Flag", "ldp.msg.tlv.lspid.actflg", FT_UINT16, BASE_HEX, VALS(ldp_act_flg_vals), 0x000F, "Action Indicator Flag", HFILL}},
+
+    { &hf_ldp_tlv_lspid_cr_lsp,
+      { "Local CR-LSP ID", "ldp.msg.tlv.lspid.locallspid", FT_UINT16, BASE_HEX, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+    { &hf_ldp_tlv_lspid_ldpid,
+      { "Ingress LSR Router ID", "ldp.msg.tlv.lspid.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Ingress LSR Router ID", HFILL}},
+
+    { &hf_ldp_tlv_er_hop_loose,
+      { "Loose route bit", "ldp.msg.tlv.er_hop.loose", FT_UINT24, BASE_HEX, VALS(ldp_loose_vals), 0x800000, "Loose route bit", HFILL}},
+
+    { &hf_ldp_tlv_er_hop_prelen,
+      { "Prefix length", "ldp.msg.tlv.er_hop.prefixlen", FT_UINT8, BASE_DEC, NULL, 0x0, "Prefix len", HFILL}},
+
+    { &hf_ldp_tlv_er_hop_prefix4,
+      { "IPv4 Address", "ldp.msg.tlv.er_hop.prefix4", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Address", HFILL}},
+   { &hf_ldp_tlv_er_hop_prefix6,
+     { "IPv6 Address", "ldp.msg.tlv.er_hop.prefix6", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Address", HFILL}},
+
+    { &hf_ldp_tlv_er_hop_as,
+      { "AS Number", "ldp.msg.tlv.er_hop.as", FT_UINT16, BASE_DEC, NULL, 0x0, "AS Number", HFILL}},
+
+    { &hf_ldp_tlv_er_hop_cr_lsp,
+      { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.locallspid", FT_UINT16, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+    { &hf_ldp_tlv_er_hop_ldpid,
+      { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+    { &hf_ldp_tlv_flags_reserv,
+      { "Reserved", "ldp.msg.tlv.flags_reserv", FT_UINT8, BASE_HEX, NULL, 0xC0, "Reserved", HFILL}},
+
+    { &hf_ldp_tlv_flags_pdr,
+      { "PDR", "ldp.msg.tlv.flags_pdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x1, "PDR negotiability flag", HFILL}},
+
+    { &hf_ldp_tlv_flags_pbs,
+      { "PBS", "ldp.msg.tlv.flags_pbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x2, "PBS negotiability flag", HFILL}},
+
+    { &hf_ldp_tlv_flags_cdr,
+      { "CDR", "ldp.msg.tlv.flags_cdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x4, "CDR negotiability flag", HFILL}},
+
+    { &hf_ldp_tlv_flags_cbs,
+      { "CBS", "ldp.msg.tlv.flags_cbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x8, "CBS negotiability flag", HFILL}},
+
+    { &hf_ldp_tlv_flags_ebs,
+      { "EBS", "ldp.msg.tlv.flags_ebs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x10, "EBS negotiability flag", HFILL}},
+
+    { &hf_ldp_tlv_flags_weight,
+      { "Weight", "ldp.msg.tlv.flags_weight", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x20, "Weight negotiability flag", HFILL}},
+
+    { &hf_ldp_tlv_frequency,
+      { "Frequency", "ldp.msg.tlv.frequency", FT_UINT8, BASE_DEC, VALS(freq_values), 0, "Frequency", HFILL}},
+
+    { &hf_ldp_tlv_weight,
+      { "Weight", "ldp.msg.tlv.weight", FT_UINT8, BASE_DEC, NULL, 0, "Weight of the CR-LSP", HFILL}},
+
+    { &hf_ldp_tlv_pdr,
+      { "PDR", "ldp.msg.tlv.pdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Data Rate", HFILL}},
+
+    { &hf_ldp_tlv_pbs,
+      { "PBS", "ldp.msg.tlv.pbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Burst Size", HFILL}},
+
+    { &hf_ldp_tlv_cdr,
+      { "CDR", "ldp.msg.tlv.cdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Data Rate", HFILL}},
+
+    { &hf_ldp_tlv_cbs,
+      { "CBS", "ldp.msg.tlv.cbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Burst Size", HFILL}},
+
+    { &hf_ldp_tlv_ebs,
+      { "EBS", "ldp.msg.tlv.ebs", FT_DOUBLE, BASE_NONE, NULL, 0, "Excess Burst Size", HFILL}},
+
+    { &hf_ldp_tlv_set_prio,
+      { "Set Prio", "ldp.msg.tlv.set_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP setup priority", HFILL}},
+
+    { &hf_ldp_tlv_hold_prio,
+      { "Hold Prio", "ldp.msg.tlv.hold_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP hold priority", HFILL}},
+
+    { &hf_ldp_tlv_route_pinning,
+      { "Route Pinning", "ldp.msg.tlv.route_pinning", FT_UINT32, BASE_DEC, VALS(route_pinning_vals), 0x80000000, "Route Pinning", HFILL}},
+
+    { &hf_ldp_tlv_resource_class,
+      { "Resource Class", "ldp.msg.tlv.resource_class", FT_UINT32, BASE_HEX, NULL, 0, "Resource Class (Color)", HFILL}},
+
   };
 
   static gint *ett[] = {
@@ -1825,7 +2547,7 @@ proto_register_ldp(void)
     &ett_ldp_fec,
     &ett_ldp_fec_vc_interfaceparam
   };
-  module_t *ldp_module; 
+  module_t *ldp_module;
 
   proto_ldp = proto_register_protocol("Label Distribution Protocol",
                                       "LDP", "ldp");
@@ -1857,13 +2579,13 @@ proto_register_ldp(void)
 void
 proto_reg_handoff_ldp(void)
 {
-  static int ldp_prefs_initialized = FALSE;
+  static gboolean ldp_prefs_initialized = FALSE;
   static dissector_handle_t ldp_tcp_handle, ldp_handle;
 
   if (!ldp_prefs_initialized) {
 
-    ldp_tcp_handle = create_dissector_handle(dissect_ldp_tcp, proto_ldp);
-    ldp_handle = create_dissector_handle(dissect_ldp, proto_ldp);
+    ldp_tcp_handle = new_create_dissector_handle(dissect_ldp_tcp, proto_ldp);
+    ldp_handle = new_create_dissector_handle(dissect_ldp, proto_ldp);
 
     ldp_prefs_initialized = TRUE;