aboutsummaryrefslogtreecommitdiffstats
path: root/packet-ldp.c
diff options
context:
space:
mode:
Diffstat (limited to 'packet-ldp.c')
-rw-r--r--packet-ldp.c118
1 files changed, 87 insertions, 31 deletions
diff --git a/packet-ldp.c b/packet-ldp.c
index 18bc99e4ae..87070889d4 100644
--- a/packet-ldp.c
+++ b/packet-ldp.c
@@ -1,7 +1,7 @@
/* packet-ldp.c
* Routines for ldp packet disassembly
*
- * $Id: packet-ldp.c,v 1.19 2001/07/21 10:27:12 guy Exp $
+ * $Id: packet-ldp.c,v 1.20 2001/11/27 04:59:01 guy Exp $
*
* Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
*
@@ -546,55 +546,73 @@ dissect_ldp_label_abort_request(tvbuff_t *tvb, guint offset, packet_info *pinfo,
}
-static void
-dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int
+dissect_ldp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
{
- proto_tree *ldp_tree = NULL,
- *ti = NULL,
- *hdr_tree = NULL, *ldpid_tree = NULL;
- int offset = 0, msg_cnt = 0;
+ proto_tree *ldp_tree = NULL, *hdr_tree = NULL, *ldpid_tree = NULL;
+ proto_item *ldp_item = NULL, *hdr_item = NULL, *ldpid_item = NULL;
+ int msg_cnt = 0;
guint16 ldp_message = 0;
+ guint pdu_len;
- 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 */
- ti = proto_tree_add_item(tree, proto_ldp, tvb, offset,
- tvb_length_remaining(tvb, offset), FALSE);
- ldp_tree = proto_item_add_subtree(ti, ett_ldp);
+ ldp_item = proto_tree_add_item(tree, proto_ldp, tvb, offset,
+ tvb_length_remaining(tvb, offset), FALSE);
+ ldp_tree = proto_item_add_subtree(ldp_item, ett_ldp);
- ti = proto_tree_add_text(ldp_tree, tvb, 0, 10, "Header");
+ }
+
+ /* Dissect LDP Header */
- hdr_tree = proto_item_add_subtree(ti, ett_ldp_header);
+ hdr_item = proto_tree_add_text(ldp_tree, tvb, offset, 10, "Header");
- proto_tree_add_item(hdr_tree, hf_ldp_version, tvb, offset, 2, FALSE);
+ hdr_tree = proto_item_add_subtree(hdr_item, ett_ldp_header);
- offset += 2;
+ proto_tree_add_item(hdr_tree, hf_ldp_version, tvb, offset, 2, FALSE);
- proto_tree_add_item(hdr_tree, hf_ldp_pdu_len, tvb, offset, 2, FALSE);
+ offset += 2;
- offset += 2;
+ proto_tree_add_item(hdr_tree, hf_ldp_pdu_len, tvb, offset, 2, FALSE);
+ pdu_len = tvb_get_ntohs(tvb, offset);
+ proto_item_set_len(ldp_item, pdu_len + 2);
- ti = proto_tree_add_text(hdr_tree, tvb, offset, 6, "LDP Identifier");
+ /*
+ * XXX - do TCP reassembly, to handle LDP PDUs that cross TCP segment
+ * boundaries.
+ */
- ldpid_tree = proto_item_add_subtree(ti, ett_ldp_ldpid);
+ offset += 2;
- proto_tree_add_item(ldpid_tree, hf_ldp_lsr, tvb, offset, 4, FALSE);
+ if (pdu_len < 6) {
+ /*
+ * PDU is too short to hold the LDP identifier.
+ */
+ proto_tree_add_text(hdr_tree, tvb, offset, pdu_len,
+ "PDU too short (%u bytes, should be at least 6) for LDP Identifier",
+ pdu_len);
+ offset += pdu_len;
+ return offset;
+ }
- offset += 4;
+ ldpid_item = proto_tree_add_text(hdr_tree, tvb, offset, 6, "LDP Identifier");
- proto_tree_add_item(ldpid_tree, hf_ldp_ls_id, tvb, offset, 2, FALSE);
+ ldpid_tree = proto_item_add_subtree(ldpid_item, ett_ldp_ldpid);
- offset += 2;
+ proto_tree_add_item(ldpid_tree, hf_ldp_lsr, tvb, offset, 4, FALSE);
- }
+ offset += 4;
+ pdu_len -= 4;
- offset = 10;
+ proto_tree_add_item(ldpid_tree, hf_ldp_ls_id, tvb, offset, 2, FALSE);
- while (tvb_length_remaining(tvb, offset) > 0) { /* Dissect a message */
+ offset += 2;
+ pdu_len -= 2;
+
+ while (pdu_len > 0) { /* Dissect LDP TLV */
guint msg_len;
@@ -610,7 +628,7 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
else
col_add_fstr(pinfo->fd, COL_INFO, "%s",
val_to_str(ldp_message, ldp_message_types, "Unknown Message (0x%04X)"));
-
+
}
msg_cnt++;
@@ -625,13 +643,25 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
val_to_str(ldp_message, ldp_message_types, "Unknown Message (0x%04X)"));
msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
-
+
proto_tree_add_item(msg_tree, hf_ldp_msg_type, tvb, offset, 2, FALSE);
proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset + 2, 2, FALSE);
+ if (msg_len < 4) {
+ proto_tree_add_text(msg_tree, tvb, offset + 4, msg_len,
+ "Message too short (%u bytes, should be at least 4) for Message ID",
+ msg_len);
+ goto next;
+ }
+
proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset + 4, 4, FALSE);
+ if (msg_len == 4) {
+ /* Nothing past the message ID */
+ goto next;
+ }
+
switch (ldp_message) {
case LDP_NOTIFICATION:
@@ -655,7 +685,7 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
case LDP_KEEPALIVE:
dissect_ldp_keepalive(tvb, offset + 8, pinfo, msg_tree, msg_len - 4);
-
+
break;
case LDP_ADDRESS:
@@ -703,6 +733,8 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
default:
/* Some sort of unknown message, treat as undissected data */
+ proto_tree_add_text(msg_tree, tvb, offset + 8, msg_len - 4,
+ "Message data");
break;
@@ -710,9 +742,33 @@ dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
+next:
offset += msg_len + 4;
+ pdu_len -= msg_len + 4;
}
+ return offset;
+}
+
+static void
+dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (check_col(pinfo->fd, COL_PROTOCOL))
+ col_add_str(pinfo->fd, COL_PROTOCOL, "LDP");
+
+ dissect_ldp_pdu(tvb, 0, pinfo, tree);
+}
+
+static void
+dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+
+ if (check_col(pinfo->fd, COL_PROTOCOL))
+ col_add_str(pinfo->fd, COL_PROTOCOL, "LDP");
+
+ while (tvb_reported_length_remaining(tvb, offset) > 0) /* Dissect LDP PDUs */
+ offset = dissect_ldp_pdu(tvb, offset, pinfo, tree);
}
/* Register all the bits needed with the filtering engine */
@@ -845,7 +901,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, proto_ldp);
+ dissector_add("tcp.port", global_ldp_tcp_port, dissect_ldp_tcp, proto_ldp);
dissector_add("udp.port", global_ldp_udp_port, dissect_ldp, proto_ldp);
}