aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/libwireshark.def1
-rw-r--r--epan/xdlc.c70
-rw-r--r--epan/xdlc.h14
-rw-r--r--plugins/rlm/packet-rlm.c24
4 files changed, 98 insertions, 11 deletions
diff --git a/epan/libwireshark.def b/epan/libwireshark.def
index d7142a863d..d25f71a3d3 100644
--- a/epan/libwireshark.def
+++ b/epan/libwireshark.def
@@ -65,6 +65,7 @@ capture_sll
capture_tr
capture_wlancap
check_col
+check_xdlc_control
circuit_add_proto_data
circuit_get_proto_data
circuit_new
diff --git a/epan/xdlc.c b/epan/xdlc.c
index 362ad16a98..7f54f0083b 100644
--- a/epan/xdlc.c
+++ b/epan/xdlc.c
@@ -136,7 +136,7 @@ const value_string modifier_vals_resp[] = {
};
int
-get_xdlc_control(const guchar *pd, int offset, int is_extended)
+get_xdlc_control(const guchar *pd, int offset, gboolean is_extended)
{
guint16 control;
@@ -170,13 +170,71 @@ get_xdlc_control(const guchar *pd, int offset, int is_extended)
return control;
}
+/*
+ * Check whether the control field of the packet looks valid.
+ */
+gboolean
+check_xdlc_control(tvbuff_t *tvb, int offset,
+ const value_string *u_modifier_short_vals_cmd,
+ const value_string *u_modifier_short_vals_resp, gboolean is_response,
+ gboolean is_extended _U_)
+{
+ guint16 control;
+
+ if (!tvb_bytes_exist(tvb, offset, 1))
+ return FALSE; /* not enough data to check */
+ switch (tvb_get_guint8(tvb, offset) & 0x03) {
+
+ case XDLC_S:
+ /*
+ * Supervisory frame.
+ * No fields to check for validity here.
+ */
+ return TRUE;
+
+ case XDLC_U:
+ /*
+ * Unnumbered frame.
+ *
+ * XXX - is this two octets, with a P/F bit, in HDLC extended
+ * operation? It's one octet in LLC, even though the control
+ * field of I and S frames is a 2-byte extended-operation field
+ * in LLC. Given that there are no sequence numbers in the
+ * control field of a U frame, there doesn't appear to be any
+ * need for it to be 2 bytes in extended operation.
+ */
+ if (u_modifier_short_vals_cmd == NULL)
+ u_modifier_short_vals_cmd = modifier_short_vals_cmd;
+ if (u_modifier_short_vals_resp == NULL)
+ u_modifier_short_vals_resp = modifier_short_vals_resp;
+ control = tvb_get_guint8(tvb, offset);
+ if (is_response) {
+ if (match_strval(control & XDLC_U_MODIFIER_MASK,
+ u_modifier_short_vals_resp) == NULL)
+ return FALSE; /* unknown modifier */
+ } else {
+ if (match_strval(control & XDLC_U_MODIFIER_MASK,
+ u_modifier_short_vals_cmd) == NULL)
+ return FALSE; /* unknown modifier */
+ }
+ return TRUE;
+
+ default:
+ /*
+ * Information frame.
+ * No fields to check for validity here.
+ */
+ return TRUE;
+ }
+}
+
int
dissect_xdlc_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *xdlc_tree, int hf_xdlc_control, gint ett_xdlc_control,
const xdlc_cf_items *cf_items_nonext, const xdlc_cf_items *cf_items_ext,
const value_string *u_modifier_short_vals_cmd,
- const value_string *u_modifier_short_vals_resp, int is_response,
- int is_extended, int append_info)
+ const value_string *u_modifier_short_vals_resp, gboolean is_response,
+ gboolean is_extended, gboolean append_info)
{
guint16 control;
int control_len;
@@ -192,6 +250,9 @@ dissect_xdlc_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
switch (tvb_get_guint8(tvb, offset) & 0x03) {
case XDLC_S:
+ /*
+ * Supervisory frame.
+ */
if (is_extended) {
control = tvb_get_letohs(tvb, offset);
control_len = 2;
@@ -203,9 +264,6 @@ dissect_xdlc_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
cf_items = cf_items_nonext;
control_format = "Control field: %s (0x%02X)";
}
- /*
- * Supervisory frame.
- */
switch (control & XDLC_S_FTYPE_MASK) {
case XDLC_RR:
frame_type = "RR";
diff --git a/epan/xdlc.h b/epan/xdlc.h
index 0f1612cc69..d081537b1e 100644
--- a/epan/xdlc.h
+++ b/epan/xdlc.h
@@ -128,13 +128,21 @@ extern const value_string stype_vals[];
extern const value_string modifier_vals_cmd[];
extern const value_string modifier_vals_resp[];
-extern int get_xdlc_control(const guchar *pd, int offset, int extended);
+extern int get_xdlc_control(const guchar *pd, int offset, gboolean is_extended);
+
+/*
+ * Check whether the control field of the packet looks valid.
+ */
+extern gboolean check_xdlc_control(tvbuff_t *tvb, int offset,
+ const value_string *u_modifier_short_vals_cmd,
+ const value_string *u_modifier_short_vals_resp, gboolean is_response,
+ gboolean is_extended _U_);
extern int dissect_xdlc_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *xdlc_tree, int hf_xdlc_control, gint ett_xdlc_control,
const xdlc_cf_items *cf_items_nonext, const xdlc_cf_items *cf_items_ext,
const value_string *u_modifier_short_vals_cmd,
- const value_string *u_modifier_short_vals_resp, int is_response,
- int is_extended, int append_info);
+ const value_string *u_modifier_short_vals_resp, gboolean is_response,
+ gboolean is_extended, gboolean append_info);
#endif
diff --git a/plugins/rlm/packet-rlm.c b/plugins/rlm/packet-rlm.c
index ce98977efa..db05bab821 100644
--- a/plugins/rlm/packet-rlm.c
+++ b/plugins/rlm/packet-rlm.c
@@ -28,7 +28,7 @@
* many redundant NASes. I don't know much about the format, but you
* can read about the feature here:
*
- * http://www.cisco.com/univercd/cc/td/doc/product/software/ios120/120newft/120t/120t3/rlm_123.htm
+ * http://www.cisco.com/en/US/docs/ios/12_0t/12_0t3/feature/guide/rlm_123.html
*
* RLM runs on a UDP port (default 3000) between the MGC and the NAS.
* On port N+1 (default 3001), a Q.931/LAPD/UDP connection is maintained.
@@ -57,6 +57,7 @@
#include <glib.h>
#include <epan/packet.h>
+#include <epan/xdlc.h>
/* Initialize the protocol and registered fields */
static int proto_rlm = -1;
@@ -86,6 +87,7 @@ static gint ett_rlm = -1;
Maybe this isn't the best place for it, but RLM goes hand in hand
with Q.931 traffic on a higher port.
*/
+static dissector_handle_t lapd_handle;
static gboolean
dissect_udp_lapd(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree) {
@@ -95,7 +97,20 @@ dissect_udp_lapd(tvbuff_t *tvb, packet_info *pinfo _U_ , proto_tree *tree) {
|| pinfo->destport != pinfo->srcport)
return FALSE;
- call_dissector(find_dissector("lapd"), tvb, pinfo, tree);
+ /*
+ * XXX - check for a valid LAPD address field.
+ */
+
+ /*
+ * OK, check whether the control field looks valid.
+ */
+ if (!check_xdlc_control(tvb, 2, NULL, NULL, FALSE, FALSE))
+ return FALSE;
+
+ /*
+ * Loooks OK - call the LAPD dissector.
+ */
+ call_dissector(lapd_handle, tvb, pinfo, tree);
return TRUE;
}
@@ -175,6 +190,11 @@ dissect_rlm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
void
proto_reg_handoff_rlm(void)
{
+ /*
+ * Find a handle for the LAPD dissector.
+ */
+ lapd_handle = find_dissector("lapd");
+
heur_dissector_add("udp", dissect_rlm, proto_rlm);
heur_dissector_add("udp", dissect_udp_lapd, proto_get_id_by_filter_name("lapd"));
}