aboutsummaryrefslogtreecommitdiffstats
path: root/packet-ldp.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2002-04-28 00:18:50 +0000
committerGuy Harris <guy@alum.mit.edu>2002-04-28 00:18:50 +0000
commitf6439823828714b5b72394836dbcd13262bfbcdb (patch)
tree27243404917982a490dad79c955143396f7f1612 /packet-ldp.c
parentdb119f15d4b42f0ae99523e06ce81719ce714ba2 (diff)
Make the LDP dissectors new-style dissectors, so they can reject packets
if the version number isn't 1; the LDP port number appears to be popular for ONC RPC protocols, and this lets them be dissected as such, at least if they don't begin with a 2-byte big-endian 1. Do a standard TCP loop, which: handles LDP headers split across TCP segments; gives each LDP PDU in a TCP stream a tvbuff of its own, so we don't run past the end of the PDU; gives each LDP PDU its own tree. svn path=/trunk/; revision=5261
Diffstat (limited to 'packet-ldp.c')
-rw-r--r--packet-ldp.c282
1 files changed, 191 insertions, 91 deletions
diff --git a/packet-ldp.c b/packet-ldp.c
index e0486c9c35..fb11ce7bdb 100644
--- a/packet-ldp.c
+++ b/packet-ldp.c
@@ -1,7 +1,7 @@
/* packet-ldp.c
* Routines for LDP (RFC 3036) packet disassembly
*
- * $Id: packet-ldp.c,v 1.36 2002/04/25 06:34:41 guy Exp $
+ * $Id: packet-ldp.c,v 1.37 2002/04/28 00:18:50 guy Exp $
*
* Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
*
@@ -50,6 +50,8 @@
#include "prefs.h"
#include "afn.h"
+#include "packet-frame.h"
+
#define TCP_PORT_LDP 646
#define UDP_PORT_LDP 646
@@ -1818,15 +1820,14 @@ dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
/* Dissect a Message and return the number of bytes consumed ... */
static int
-dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem)
+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) )
@@ -1908,120 +1909,219 @@ dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, i
return length+8+extra;
}
-/* Dissect a PDU and return the number of bytes consumed ... */
-
-static 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: length is %d, should be >= 6",
- 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: length is %d, should be <= %d",
- length, rem);
- }
- 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 */
@@ -2421,13 +2521,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;