aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-teredo.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2004-09-09 06:50:03 +0000
committerGuy Harris <guy@alum.mit.edu>2004-09-09 06:50:03 +0000
commitd614d107cf88f769fa274cff7b93106ee38eaed2 (patch)
tree0886a057d712d9740eb60fb0dd08abda591d9420 /epan/dissectors/packet-teredo.c
parenta8d0f1d31fd868c0ccda61e1339589db7a6653c7 (diff)
From Remi Denis-Courmont: heuristic dissector for Teredo.
svn path=/trunk/; revision=11948
Diffstat (limited to 'epan/dissectors/packet-teredo.c')
-rw-r--r--epan/dissectors/packet-teredo.c87
1 files changed, 86 insertions, 1 deletions
diff --git a/epan/dissectors/packet-teredo.c b/epan/dissectors/packet-teredo.c
index 57f6eab156..b9a10f6ae9 100644
--- a/epan/dissectors/packet-teredo.c
+++ b/epan/dissectors/packet-teredo.c
@@ -81,6 +81,9 @@ static dissector_table_t teredo_dissector_table;
/*static heur_dissector_list_t heur_subdissector_list;*/
static dissector_handle_t data_handle;
+static gboolean global_teredo_heur = FALSE;
+
+
static int
parse_teredo_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
int offset, e_teredohdr *teredoh)
@@ -250,6 +253,78 @@ dissect_teredo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tap_queue_packet(teredo_tap, pinfo, teredoh);
}
+
+static gboolean
+dissect_teredo_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ guint16 val;
+ int offset = 0;
+
+ if (!global_teredo_heur)
+ return FALSE;
+
+ if (tvb_length_remaining(tvb, offset) < 40)
+ return FALSE;
+
+ val = tvb_get_ntohs(tvb, offset);
+
+ if (val == 1) /* possible auth header */
+ {
+ guint8 idlen, aulen;
+
+ offset += 2;
+
+ idlen = tvb_get_guint8(tvb, offset);
+ offset++;
+
+ aulen = tvb_get_guint8(tvb, offset);
+ offset += 10;
+
+ if (tvb_length_remaining(tvb, offset) < idlen + aulen + 40)
+ return FALSE;
+
+ offset += idlen + aulen;
+
+ val = tvb_get_ntohs(tvb, offset);
+ }
+
+ if (val == 0) /* origin indication */
+ {
+ offset += 8;
+
+ if (tvb_length_remaining(tvb, offset) < 40)
+ return FALSE;
+
+ val = tvb_get_ntohs(tvb, offset);
+ }
+
+ /*
+ * We have to check upper-layer packet a little bit otherwise we will
+ * match -almost- *ANY* packet.
+ * These checks are in the Teredo specification by the way.
+ * Unfortunately, that will cause false-negative if the snaplen is too
+ * short to get the packet entirely.
+ */
+ if ((val >> 12) == 6) /* IPv6 header */
+ {
+ /* checks IPv6 payload length */
+ val = tvb_get_ntohs(tvb, offset + 4);
+ offset += 40;
+
+ if (val > 65467)
+ return FALSE; /* length too big for Teredo */
+
+ if (tvb_length_remaining(tvb, offset) != val)
+ return FALSE; /* length mismatch */
+
+ dissect_teredo (tvb, pinfo, tree);
+ return TRUE;
+ }
+
+ return FALSE; /* not an IPv6 packet */
+}
+
+
void
proto_register_teredo(void)
{
@@ -313,6 +388,8 @@ proto_register_teredo(void)
&ett_teredo, &ett_teredo_auth, &ett_teredo_orig
};
+ module_t *teredo_module;
+
proto_teredo = proto_register_protocol(
"Teredo IPv6 over UDP tunneling", "Teredo", "teredo");
proto_register_field_array(proto_teredo, hf, array_length(hf));
@@ -320,7 +397,14 @@ proto_register_teredo(void)
/* subdissector code */
teredo_dissector_table = register_dissector_table("teredo","Teredo ", FT_UINT16, BASE_DEC);
-/* register_heur_dissector_list("teredo.heur", &heur_subdissector_list); */
+
+ teredo_module = prefs_register_protocol(proto_teredo, NULL);
+
+ prefs_register_bool_preference(teredo_module, "heuristic_teredo",
+ "Try to decode UDP packets as Teredo IPv6",
+ "Check this to decode IPv6 traffic between Teredo clients and "
+ "relays",
+ &global_teredo_heur);
}
@@ -334,5 +418,6 @@ proto_reg_handoff_teredo(void)
teredo_tap = register_tap("teredo");
dissector_add("udp.port", UDP_PORT_TEREDO, teredo_handle);
+ heur_dissector_add("udp", dissect_teredo_heur, proto_teredo);
}