aboutsummaryrefslogtreecommitdiffstats
path: root/packet-ldp.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2001-11-27 04:59:01 +0000
committerGuy Harris <guy@alum.mit.edu>2001-11-27 04:59:01 +0000
commita18d29bede94e246d78af9d3d47f4c2bc493bc03 (patch)
tree4ba8052f1da590c56ff3ef58e307badeaf3f2365 /packet-ldp.c
parentc5124017ed25a196ac40ec24e8d9bcc857e5f450 (diff)
Handle the case of multiple LDP PDUs per TCP segment. (Still needs to
handle the case of more than one TCP segment per LDP PDU....) Fix the handling of some of the length fields. svn path=/trunk/; revision=4276
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);
}