WinPcap 2.1 allows you to capture on Token Ring, so remove the note
[obnox/wireshark/wip.git] / packet-ldp.c
index 02e0e99784bc338991556230abc2c416a30dff27..7edade18307a667a6017037596074f800638851e 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-ldp.c
  * Routines for ldp packet disassembly
  *
- * $Id: packet-ldp.c,v 1.2 2000/11/30 06:24:53 sharpe Exp $
+ * $Id: packet-ldp.c,v 1.14 2001/01/25 06:14:14 guy Exp $
  * 
  * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
  *
@@ -59,10 +59,30 @@ static int hf_ldp_version = -1;
 static int hf_ldp_pdu_len = -1;
 static int hf_ldp_lsr = -1;
 static int hf_ldp_ls_id = -1;
+static int hf_ldp_msg_type = -1;
+static int hf_ldp_msg_len = -1;
+static int hf_ldp_msg_id = -1;
+static int hf_ldp_tlv_value = -1;
+static int hf_ldp_tlv_type = -1;
+static int hf_ldp_tlv_len = -1;
+static int hf_ldp_tlv_val_hold = -1;
+static int hf_ldp_tlv_val_target = -1;
+static int hf_ldp_tlv_val_request = -1;
+static int hf_ldp_tlv_val_res = -1;
+static int hf_ldp_tlv_config_seqno = -1;
+static int hf_ldp_tlv_fec_wc = -1;
+static int hf_ldp_tlv_fec_af = -1;
+static int hf_ldp_tlv_fec_len = -1;
+static int hf_ldp_tlv_fec_pfval = -1;
+static int hf_ldp_tlv_generic_label = -1;
 
 static int ett_ldp = -1;
 static int ett_ldp_header = -1;
 static int ett_ldp_ldpid = -1;
+static int ett_ldp_message = -1;
+static int ett_ldp_tlv = -1;
+static int ett_ldp_tlv_val = -1;
+static int ett_ldp_fec = -1;
 
 static int tcp_port = 0;
 static int udp_port = 0;
@@ -72,6 +92,61 @@ static int udp_port = 0;
 static int global_ldp_tcp_port = TCP_PORT_LDP;
 static int global_ldp_udp_port = UDP_PORT_LDP;
 
+/*
+ * The following define all the TLV types I know about
+ */
+
+#define TLV_FEC                    0x0100
+#define TLV_ADDRESS_LIST           0x0101
+#define TLV_HOP_COUNT              0x0103
+#define TLV_PATH_VECTOR            0x0104
+#define TLV_GENERIC_LABEL          0x0200
+#define TLV_ATM_LABEL              0x0201
+#define TLV_FRAME_LABEL            0x0202
+#define TLV_STATUS                 0x0300
+#define TLV_EXTENDED_STATUS        0x0301
+#define TLV_RETURNED_PDU           0x0302
+#define TLV_RETURNED_MESSAGE       0x0303
+#define TLV_COMMON_HELLO_PARMS     0x0400
+#define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
+#define TLV_CONFIGURATION_SEQNO    0x0402
+#define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
+#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_VENDOR_PRIVATE_START   0x3E00
+#define TLV_VENDOR_PROVATE_END     0x3EFF
+#define TLV_EXPERIMENTAL_START     0x3F00
+#define TLV_EXPERIMENTAL_END       0x3FFF
+
+static const value_string tlv_type_names[] = { 
+  { TLV_FEC,                       "Forwarding Equivalence Classes" },
+  { TLV_ADDRESS_LIST,              "Address List"},
+  { TLV_HOP_COUNT,                 "Hop Count"},
+  { TLV_PATH_VECTOR,               "Path Vector"},
+  { TLV_GENERIC_LABEL,             "Generic Label"},
+  { TLV_ATM_LABEL,                 "Frame Label"},
+  { TLV_STATUS,                    "Status"},
+  { TLV_EXTENDED_STATUS,           "Extended Status"},
+  { TLV_RETURNED_PDU,              "Returned PDU"},
+  { TLV_RETURNED_MESSAGE,          "Returned Message"},
+  { TLV_COMMON_HELLO_PARMS,        "Common Hello Parameters"},
+  { TLV_IPV4_TRANSPORT_ADDRESS,    "IPv4 Transport Address"},
+  { TLV_CONFIGURATION_SEQNO,       "Configuration Sequence Number"},
+  { TLV_IPV6_TRANSPORT_ADDRESS,    "IPv6 Transport Address"},
+  { TLV_COMMON_SESSION_PARMS,      "Common Session Parameters"},
+  { TLV_ATM_SESSION_PARMS,         "ATM Session Parameters"},
+  { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters"},
+  { TLV_LABEL_REQUEST_MESSAGE_ID,  "Label Request Message ID"},
+  { 0, NULL}
+};
+
+/*
+ * The following define all the message types I know about
+ */
+
 #define LDP_NOTIFICATION       0x0001
 #define LDP_HELLO              0x0100
 #define LDP_INITIALIZATION     0x0200
@@ -83,6 +158,10 @@ static int global_ldp_udp_port = UDP_PORT_LDP;
 #define LDP_LABEL_WITHDRAWAL   0x0402
 #define LDP_LABEL_RELEASE      0x0403
 #define LDP_LABEL_ABORT_REQUEST 0x0404
+#define LDP_VENDOR_PRIVATE_START 0x3E00
+#define LDP_VENDOR_PRIVATE_END   0x3EFF
+#define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
+#define LDP_EXPERIMENTAL_MESSAGE_END   0x3FFF
 
 static const value_string ldp_message_types[] = {
   {LDP_NOTIFICATION,             "Notification"},
@@ -99,74 +178,357 @@ static const value_string ldp_message_types[] = {
   {0, NULL}
 };
 
-int dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree)
+static const true_false_string hello_targeted_vals = {
+  "Targeted Hello",
+  "Link Hello"
+};
+
+static const value_string fec_types[] = {
+  {1, "Wildcard FEC"},
+  {2, "Prefix FEC"},
+  {3, "Host Address FEC"},
+  {0, NULL}
+};
+
+static const value_string fec_af_types[] = {
+  {0, "Reserved"},
+  {1, "IP (IPv4)"},
+  {2, "IP6 (IPv6)"},
+  {3, "NSAP"},
+  {4, "HDLC (8-bit multidrop)"},
+  {5, "BBN 1822"},
+  {6, "802"},
+  {10, "X.121 (X.25, Frame Relay)"},
+  {11, "IPX"},
+  {12, "Appletalk"},
+  {0, NULL}
+};
+
+static const true_false_string hello_requested_vals = {
+  "Source requests periodic hellos",
+  "Source does not request periodic hellos"
+};
+
+/* Dissect the common hello params */
+
+void dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+  proto_tree *ti = NULL, *val_tree = NULL;
+
+  if (tree) {
+
+    ti = proto_tree_add_bytes(tree, hf_ldp_tlv_value, tvb, offset, rem,
+                             tvb_get_ptr(tvb, offset, rem));
+
+    val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+    proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
+
+    proto_tree_add_boolean(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
+    proto_tree_add_boolean(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 a TLV and return the number of bytes consumed ... */
+
+int dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
 {
+  guint16 message = tvb_get_ntohs(tvb, offset),
+          length = tvb_get_ntohs(tvb, offset + 2),
+          pad = 0, fec_len = 0;
+  proto_tree *ti = NULL, *tlv_tree = NULL;
+
+  /* Hmmm, check for illegal alignment padding */
+
+  if (message == 0x00) {
+
+    proto_tree_add_text(tree, tvb, offset, 2, "Illegal Padding: %04X", message);
+    offset += 2; pad = 2;
+    message = tvb_get_ntohs(tvb, offset);
+    length = tvb_get_ntohs(tvb, offset + 2);
+
+  }
+
+  length = MIN(length, rem);  /* Don't go haywire if a problem ... */
+
+  if (tree) {
+
+    /* FIXME: Account for vendor and special messages */
+
+    ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
+                            val_to_str(message, tlv_type_names, "Unknown TLV type (0x%04X)"));
+
+    tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
+
+    proto_tree_add_item(tlv_tree, hf_ldp_tlv_type, tvb, offset, 2, FALSE);
+
+    proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
+
+    switch (message) {
+
+    case TLV_FEC:  /* Process an FEC */
+
+      offset += 4;  /* Skip the TLV header */
+
+      fec_len = length;
+
+      while (fec_len > 0) {
+       proto_tree *fec_tree = NULL;
+
+
+       switch (tvb_get_guint8(tvb, offset)) {
+       case 1:   /* Wild Card */
+
+         proto_tree_add_item(tlv_tree, hf_ldp_tlv_fec_wc, tvb, offset, 4, FALSE);
+         fec_len -= 4;
+
+         offset += 4;
+
+         break;
+
+       case 2:   /* Prefix    */
+
+         /* Add a subtree for this ... */
+
+         ti = proto_tree_add_text(tlv_tree, tvb, offset, 8, "Prefix FEC Element");
+
+         fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
+
+         proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
+
+         offset += 1;
+
+         /* XXX - the address family length should be extracted and used to
+            dissect the prefix field. */
+         proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
+         offset += 2;
+
+
+         proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
+
+         offset += 1;
+
+         proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, 4, FALSE);
+
+         fec_len -= 8;
+
+         break;
+
+       case 3:   /* Host address */
+
+         /* XXX - write me. */
+
+         fec_len -= 8;
+
+         offset += 8;
+
+         break;
+
+       default:  /* Unknown */
+
+          /* XXX - do all FEC's have a length that's a multiple of 4? */
+          /* Hmmm, don't think so. Will check. RJS. */
+
+         fec_len -= 4;
+
+         offset += 4;
+
+         break;
+
+       }
+
+      }
+
+      break;;
+
+    case TLV_GENERIC_LABEL:
+
+      proto_tree_add_item(tlv_tree, hf_ldp_tlv_generic_label, tvb, offset + 4, 4, FALSE);
+
+      break;
+
+    case TLV_COMMON_HELLO_PARMS:
+
+      dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
+      break;
+
+    case TLV_CONFIGURATION_SEQNO:
+
+      proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
+      break;
+
+    default:
+      proto_tree_add_bytes(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, 
+                          length, tvb_get_ptr(tvb, offset + 4, length));
+
+      break;
+    }
+
+  }
+
+  return length + pad + 4;  /* Length of the value field + header */
 
 }
 
-int
-dissect_ldp_notification(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+/* 
+ * Each of these routines dissect the relevant messages, but the msg header 
+ * has already been dissected.
+ */
+
+void
+dissect_ldp_notification(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_hello(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+/* Dissect a Hello Message ... */
+void
+dissect_ldp_hello(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_initialization(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_initialization(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_keepalive(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_keepalive(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_address(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_address(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_address_withdrawal(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_address_withdrawal(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_label_mapping(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_label_mapping(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_label_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_label_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_label_withdrawal(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_label_withdrawal(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_label_release(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_label_release(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
-int 
-dissect_ldp_label_abort_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
+void
+dissect_ldp_label_abort_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, guint length)
 {
+  guint rem = length, cc = 0;
+
+  while (rem > 0) {
+
+    rem -= (cc = dissect_tlv(tvb, offset, tree, rem));
+    offset += cc;
+
+  }
 
 }
 
@@ -179,19 +541,10 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   int           offset = 0, msg_cnt = 0;
   guint16        ldp_message = 0;
 
-/* Add your variables here */
-
-#if 1
-  CHECK_DISPLAY_AS_DATA(proto_ldp, tvb, pinfo, tree);
-#else
-  OLD_CHECK_DISPLAY_AS_DATA(proto_ldp, pd, offset, fd, tree);
-#endif
-
-/* Add your dissection code here */
-
   if (check_col(pinfo->fd, COL_PROTOCOL))
-
     col_add_str(pinfo->fd, COL_PROTOCOL, "LDP");
+  if (check_col(pinfo->fd, COL_INFO))
+    col_clear(pinfo->fd, COL_INFO);
 
   if (tree) {  /* Build the tree info ..., this is wrong! FIXME */
 
@@ -229,12 +582,16 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
   while (tvb_length_remaining(tvb, offset) > 0) { /* Dissect a message */
 
+    guint msg_len;
+
     ldp_message = tvb_get_ntohs(tvb, offset) & 0x7FFF; /* Get the message type */
 
+    msg_len = tvb_get_ntohs(tvb, offset + 2);
+
     if (check_col(pinfo->fd, COL_INFO)) {  /* Check the type ... */
 
       if (msg_cnt > 0) 
-       col_append_fstr(pinfo->fd, COL_INFO, " %s",
+       col_append_fstr(pinfo->fd, COL_INFO, ", %s",
                        val_to_str(ldp_message, ldp_message_types, "Unknown Message (0x%04X)"));
       else
        col_add_fstr(pinfo->fd, COL_INFO, "%s", 
@@ -244,64 +601,104 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     msg_cnt++;
 
-    switch (ldp_message) {
+    if (tree) {
 
-    case LDP_NOTIFICATION:
+      proto_tree *ti = NULL, *msg_tree = NULL;
 
-      offset += dissect_ldp_notification(tvb, offset, pinfo, ldp_tree); 
+      /* FIXME: Account for vendor and experimental messages */
 
-      break;
+      ti = proto_tree_add_text(ldp_tree, tvb, offset, msg_len + 4, "%s",
+                              val_to_str(ldp_message, ldp_message_types, "Unknown Message (0x%04X)"));
 
-    case LDP_HELLO:
+      msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
 
-      break;
+      proto_tree_add_item(msg_tree, hf_ldp_msg_type, tvb, offset, 2, FALSE);
 
-    case LDP_INITIALIZATION:
+      proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset + 2, 2, FALSE);
 
-      break;
+      proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset + 4, 4, FALSE);
 
-    case LDP_KEEPALIVE:
+      switch (ldp_message) {
 
-      break;
+      case LDP_NOTIFICATION:
 
-    case LDP_ADDRESS:
+       dissect_ldp_notification(tvb, offset + 8, pinfo, msg_tree, msg_len - 4); 
 
-      break;
+       break;
 
-    case LDP_ADDRESS_WITHDRAWAL:
+      case LDP_HELLO:
 
-      break;
+       dissect_ldp_hello(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
 
-    case LDP_LABEL_MAPPING:
+       break;
 
-      break;
+      case LDP_INITIALIZATION:
 
-    case LDP_LABEL_REQUEST:
+       dissect_ldp_initialization(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
 
-      break;
+       break;
 
-    case LDP_LABEL_WITHDRAWAL:
+      case LDP_KEEPALIVE:
 
-      break;
+       dissect_ldp_keepalive(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
 
-    case LDP_LABEL_RELEASE:
+       break;
 
-      break;
+      case LDP_ADDRESS:
 
-    case LDP_LABEL_ABORT_REQUEST:
+       dissect_ldp_address(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
 
-      break;
+       break;
 
-    default:
+      case LDP_ADDRESS_WITHDRAWAL:
 
-      break;
+       dissect_ldp_address_withdrawal(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
 
-    }
+       break;
+
+      case LDP_LABEL_MAPPING:
+
+       dissect_ldp_label_mapping(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
+
+       break;
+
+      case LDP_LABEL_REQUEST:
+
+       dissect_ldp_label_request(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
+
+       break;
+
+      case LDP_LABEL_WITHDRAWAL:
+
+       dissect_ldp_label_withdrawal(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
+
+       break;
+
+      case LDP_LABEL_RELEASE:
+
+       dissect_ldp_label_release(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
+
+       break;
+
+      case LDP_LABEL_ABORT_REQUEST:
+
+       dissect_ldp_label_abort_request(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
+
+       break;
+
+      default:
+
+       /* Some sort of unknown message, treat as undissected data */
+
+       break;
+
+      }
     
-    offset += tvb_length_remaining(tvb, offset); /* FIXME: Fake this out */
+    }
 
-  }
+    offset += msg_len + 4;
 
+  }
 }
 
 /* Register all the bits needed with the filtering engine */
@@ -318,29 +715,86 @@ proto_register_ldp(void)
       { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "" }},
 
     { &hf_ldp_version,
-      { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "" }},
+      { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number" }},
 
     { &hf_ldp_pdu_len,
-      { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, ""}},
+      { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length"}},
 
     { &hf_ldp_lsr,
-      { "LSR ID", "ldp.hdr.ldpid.lsr", FT_UINT32, BASE_HEX, NULL, 0x0, ""}},
+      { "LSR ID", "ldp.hdr.ldpid.lsr", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID"}},
 
     { &hf_ldp_ls_id,
-      { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, ""}},
+      { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID"}},
+
+    { &hf_ldp_msg_type,
+      { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x0, "LDP message type"}},
+
+    { &hf_ldp_msg_len,
+      { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)"}},
+
+    { &hf_ldp_msg_id, 
+      { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID"}},
+
+    { &hf_ldp_tlv_type, 
+      { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x0, "TLV Type Field"}},
+
+    { &hf_ldp_tlv_len,
+      {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field"}},
+
+    { &hf_ldp_tlv_value,
+      { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes"}},
+
+    { &hf_ldp_tlv_val_hold,
+      { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time"}},
+
+    { &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"}},
+
+    { &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" }},
+    { &hf_ldp_tlv_val_res,
+      { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field"}},
+
+    { &hf_ldp_tlv_config_seqno,
+      { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_HEX, NULL, 0x0, "Hello COnfiguration Sequence Number"}},
+
+    { &hf_ldp_tlv_fec_wc,
+      { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types"}},
+
+    { &hf_ldp_tlv_fec_af,
+      { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(fec_af_types), 0x0, "Forwarding Equivalence Class Element Address Family"}},
+
+    { &hf_ldp_tlv_fec_len,
+      { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length"}},
+
+    { &hf_ldp_tlv_fec_pfval,
+      { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_UINT32, BASE_HEX, NULL, 0x0, "Forwarding Equivalence Class Element Prefix"}},
+
+    { &hf_ldp_tlv_generic_label,
+      { "Generic Label", "ldp.msg.tlv.label", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Mapping Generic Label"}},
 
-    /* Add more fields here */
   };
   static gint *ett[] = {
     &ett_ldp,
     &ett_ldp_header,
     &ett_ldp_ldpid,
+    &ett_ldp_message,
+    &ett_ldp_tlv,
+    &ett_ldp_tlv_val,
+    &ett_ldp_fec,
   };
   module_t *ldp_module; 
 
+  proto_ldp = proto_register_protocol("Label Distribution Protocol",
+                                      "LDP", "ldp");
+
+  proto_register_field_array(proto_ldp, hf, array_length(hf));
+  proto_register_subtree_array(ett, array_length(ett));
+
   /* Register our configuration options for , particularly our port */
 
-  ldp_module = prefs_register_module("ldp", "LDP", proto_reg_handoff_ldp);
+  ldp_module = prefs_register_protocol(proto_ldp, proto_reg_handoff_ldp);
 
   prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
                                 "Set the port for  messages (if other"
@@ -352,12 +806,6 @@ proto_register_ldp(void)
                                 " than the default of 646)",
                                 10, &global_ldp_udp_port);
 
-  proto_ldp = proto_register_protocol("Label Distribution Protocol",
-                                      "ldp");
-
-  proto_register_field_array(proto_ldp, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
-
 }
 
 /* The registration hand-off routine */
@@ -383,8 +831,7 @@ proto_reg_handoff_ldp(void)
   tcp_port = global_ldp_tcp_port;
   udp_port = global_ldp_udp_port;
 
-  dissector_add("tcp.port", global_ldp_tcp_port, dissect_ldp);
-  dissector_add("udp.port", global_ldp_udp_port, dissect_ldp);
+  dissector_add("tcp.port", global_ldp_tcp_port, dissect_ldp, proto_ldp);
+  dissector_add("udp.port", global_ldp_udp_port, dissect_ldp, proto_ldp);
 
 }
-