From Remi Denis-Courmon: fix some problems with the decoding of Teredo
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 24 Aug 2004 07:48:14 +0000 (07:48 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 24 Aug 2004 07:48:14 +0000 (07:48 +0000)
authentication headers and decode them more verbosely, and make some
other cleanups.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@11819 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
epan/dissectors/packet-teredo.c

diff --git a/AUTHORS b/AUTHORS
index d88d8de0116aa4cc0f74d48328b707f2a1dfc0f1..f23a38e3d126146b02ecec6857e9261010324a2c 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -2263,6 +2263,7 @@ Martin van der Werff      <martin [AT] vanderwerff.org>
 Marco van den Bovenkamp        <marco [AT] linuxgoeroe.dhs.org>
 Ming Zhang             <mingz [AT] ele.uri.edu>
 Neil Piercy            <Neil.Piercy [AT] ipaccess.com>
+RĂ©mi Denis-Courmont   <courmisch [AT] via.ecp.fr>
 
 Alain Magloire <alainm[AT]rcsm.ece.mcgill.ca> was kind enough to
 give his permission to use his version of snprintf.c.
index 873b908a83cbcb333df7a7aac7e438c578d28d01..57f6eab156df54d4d5ec192d9cc1a9349f266c4e 100644 (file)
@@ -1,10 +1,10 @@
 /* packet-teredo.c  v.1.0
- * Routines for TEREDO packet disassembly
- *   draft-huitema-v6ops-teredo-00.txt
- *   Windows XP Teredo
+ * Routines for Teredo packets disassembly
+ *   draft-huitema-v6ops-teredo-02.txt
  *
  * Copyright 2003, Ragi BEJJANI - 6WIND - <ragi.bejjani@6wind.com>
  * Copyright 2003, Vincent JARDIN - 6WIND - <vincent.jardin@6wind.com>
+ * Copyright 2004, Remi DENIS-COURMONT
  *
  * $Id$
  *
 #include "packet-ip.h"
 #include "tap.h"
 
-#define UDP_PORT_TERREDO 3544
+#define UDP_PORT_TEREDO 3544
 
 static int teredo_tap = -1;
 
 static int proto_teredo = -1;
-static int hf_teredo_orgheader = -1;
-static int hf_teredo_authheader = -1;
-static int hf_teredo_orgport = -1;
-static int hf_teredo_orgaddr = -1;
+
+static int hf_teredo_auth = -1;
+static int hf_teredo_auth_idlen = -1;
+static int hf_teredo_auth_aulen = -1;
+static int hf_teredo_auth_id = -1;
+static int hf_teredo_auth_value = -1;
+static int hf_teredo_auth_nonce = -1;
+static int hf_teredo_auth_conf = -1;
+static int hf_teredo_orig = -1;
+static int hf_teredo_orig_port = -1;
+static int hf_teredo_orig_addr = -1;
 
 static gint ett_teredo = -1;
+static gint ett_teredo_auth = -1, ett_teredo_orig = -1;
 
 typedef struct {
        guint16 th_indtyp;
@@ -69,13 +77,113 @@ typedef struct {
        guint32 th_iporgaddr;
 } e_teredohdr;
 
-/* Place TEREDO summary in proto tree */
-static gboolean teredo_summary_in_tree = TRUE;
-
 static dissector_table_t teredo_dissector_table;
 /*static heur_dissector_list_t heur_subdissector_list;*/
 static dissector_handle_t data_handle;
 
+static int
+parse_teredo_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                       int offset, e_teredohdr *teredoh)
+{
+       unsigned idlen, aulen;
+
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_append_sep_str (pinfo->cinfo, COL_INFO, ", ",
+                                       "Authentication header");
+
+       teredoh->th_indtyp = 1;
+       offset += 2;
+
+       idlen = tvb_get_guint8(tvb, offset);
+       teredoh->th_cidlen = idlen;
+       offset++;
+
+       aulen = tvb_get_guint8(tvb, offset);
+       teredoh->th_authdlen = aulen;
+       offset++;
+
+       if (tree) {
+               proto_item *ti;
+
+               ti = proto_tree_add_item(tree, hf_teredo_auth, tvb, offset-4,
+                                               13 + idlen + aulen, FALSE);
+               tree = proto_item_add_subtree(ti, ett_teredo_auth);
+       
+               proto_tree_add_item(tree, hf_teredo_auth_idlen, tvb,
+                                       offset - 2, 1, FALSE);
+               proto_tree_add_item(tree, hf_teredo_auth_aulen, tvb,
+                                       offset - 1, 1, FALSE);
+
+               /* idlen is usually zero */
+               if (idlen) {
+                       proto_tree_add_item(tree, hf_teredo_auth_id, tvb,
+                                               offset, idlen, FALSE);
+                       offset += idlen;
+               }
+
+               /* aulen is usually zero */
+               if (aulen) {
+                       proto_tree_add_item(tree, hf_teredo_auth_value, tvb,
+                                               offset, aulen, FALSE);
+                       offset += aulen;
+               }
+
+               proto_tree_add_item(tree, hf_teredo_auth_nonce, tvb,
+                                       offset, 8, FALSE);
+               offset += 8;
+
+               proto_tree_add_item(tree, hf_teredo_auth_conf, tvb,
+                                       offset, 1, FALSE);
+               offset++;
+       }
+       else
+               offset += idlen + aulen + 9;
+
+       tvb_memcpy(tvb, teredoh->th_nonce, offset - 9, 8);
+       teredoh->th_conf = tvb_get_guint8(tvb, offset - 1);
+
+       return offset;
+}
+
+
+static int
+parse_teredo_orig(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+                       int offset, e_teredohdr *teredoh)
+{
+       if (check_col(pinfo->cinfo, COL_INFO))
+               col_append_sep_str (pinfo->cinfo, COL_INFO, ", ",
+                                       "Origin indication");
+
+       if (tree) {
+               proto_item *ti;
+               guint16 port;
+               guint32 addr;
+
+               ti = proto_tree_add_item(tree, hf_teredo_orig, tvb, offset,
+                                               8, FALSE);
+               tree = proto_item_add_subtree(ti, ett_teredo_orig);
+               offset += 2;
+
+               port = ~tvb_get_ntohs(tvb, offset);
+               proto_tree_add_uint(tree, hf_teredo_orig_port, tvb,
+                                       offset, 2, port);
+               offset += 2;
+
+               tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
+               proto_tree_add_ipv4(tree, hf_teredo_orig_addr, tvb,
+                                       offset, 4, ~addr);
+               offset += 4;
+       }
+       else
+               offset += 8;
+
+       teredoh->th_orgport = tvb_get_ntohs(tvb, offset - 6);
+       tvb_memcpy(tvb, (guint8 *)&teredoh->th_iporgaddr, offset-4, 4);
+
+       return offset;
+}
+
+
 /* Determine if there is a sub-dissector and call it.  This has been */
 /* separated into a stand alone routine to other protocol dissectors */
 /* can call to it, ie. socks   */
@@ -103,9 +211,6 @@ dissect_teredo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        static e_teredohdr teredohstruct[4], *teredoh;
        static int teredoh_count = 0;
 
-       proto_item *to;
-       proto_tree *teredo_origin_tree;
-
        teredoh_count++;
        if(teredoh_count>=4){
                teredoh_count=0;
@@ -113,108 +218,34 @@ dissect_teredo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        teredoh = &teredohstruct[teredoh_count];
 
        if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "TEREDO");
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "Teredo");
        if (check_col(pinfo->cinfo, COL_INFO))
                col_clear(pinfo->cinfo, COL_INFO);
 
-       teredoh->th_header  = tvb_get_ntohs(tvb, offset);
-       teredoh->th_ip_v_hl = tvb_get_guint8(tvb, offset);
-       teredoh->th_indtyp  = 0;
+       if (tree) {
+               ti = proto_tree_add_item(tree, proto_teredo, tvb, 0, -1, FALSE);
+               teredo_tree = proto_item_add_subtree(ti, ett_teredo);
+       }
+       else
+               teredo_tree = NULL;
 
-       if ( (teredoh->th_header)== 1 ) {
-               teredoh->th_indtyp   = teredoh->th_header;
-               teredoh->th_cidlen   = tvb_get_guint8(tvb,offset+2);     /*Authentication header octet*/
-               teredoh->th_authdlen = tvb_get_guint8(tvb,offset+3);
-               tvb_memcpy(tvb,teredoh->th_nonce,offset+4,sizeof teredoh->th_nonce);
-               teredoh->th_conf     = tvb_get_guint8(tvb,offset+12);
+       teredoh->th_header  = tvb_get_ntohs(tvb, offset);
 
-               /*Skip over Authentication Header (fixed length-no authentication)*/
-               offset+=13;
+       if (teredoh->th_header == 1) {
+               offset = parse_teredo_auth(tvb, pinfo, teredo_tree,
+                                               offset, teredoh);
                teredoh->th_header  = tvb_get_ntohs(tvb, offset);
-               teredoh->th_ip_v_hl = tvb_get_guint8(tvb, offset);
-
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_set_str(pinfo->cinfo, COL_INFO,
-                               "Teredo : Tunneling IPv6 over UDP through NATs");
-
-               proto_tree_add_uint_hidden(tree, hf_teredo_authheader, tvb, offset-13, 2, teredoh->th_indtyp);  
-
-               if (teredo_summary_in_tree) {
-
-                       if (teredoh->th_header!=0) {
-                               ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset-13, 13,
-                                       "TEREDO with Authentication encapsulation"); 
-                       }
-
-        } else {
-                       ti = proto_tree_add_item(tree, proto_teredo, tvb, offset, 13, FALSE);
-               }
        }
+       else
+               teredoh->th_indtyp  = 0;
 
-       if ( (teredoh->th_header)== 0 ) {
-               teredoh->th_orgport=tvb_get_ntohs(tvb, offset+2);
-               tvb_memcpy(tvb, (guint8 *)&teredoh->th_iporgaddr, offset + 4, 4);
-
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_set_str(pinfo->cinfo, COL_INFO,
-                               "Teredo : Tunneling IPv6 over UDP through NATs");
-
-               if (tree) {
-                       if (teredo_summary_in_tree) { 
-                               if (teredoh->th_indtyp==1){
-                                       to = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset-13, 13+8,
-                                               "TEREDO with Authentication and Origin Indicator encapsulation");  
-                                       teredo_tree = proto_item_add_subtree(to, ett_teredo);
-                                       proto_tree_add_protocol_format(teredo_tree,proto_teredo, tvb,offset-13, 13,
-                                               "Authentication encapsulation");
-                                       ti = proto_tree_add_protocol_format(teredo_tree, proto_teredo, tvb, offset, 8,
-                                               "Origin indicator encapsulation")  ;
-                               } else { 
-                                       ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset, 8,
-                                               "TEREDO with Origin indicator encapsulation");
-                               }
-                       } else {
-                               ti = proto_tree_add_item(tree, proto_teredo, tvb, offset, 8, FALSE);
-                       }
-
-                       teredo_origin_tree = proto_item_add_subtree(ti, ett_teredo);
-
-                       proto_tree_add_uint_format(teredo_origin_tree, hf_teredo_orgheader, tvb, offset, 2,
-                               teredoh->th_header,
-                               "Teredo Origin encapsulation header: 0x%04x",
-                                       (teredoh->th_header));
-                       proto_tree_add_uint_format(teredo_origin_tree, hf_teredo_orgport, tvb, offset + 2, 2,
-                               teredoh->th_orgport,
-                               "Origin port:  %u",
-                                       ((teredoh->th_orgport)^(0xFFFF)));
-                       proto_tree_add_ipv4_format(teredo_origin_tree, hf_teredo_orgaddr, tvb, offset + 4, 4,
-                               teredoh->th_iporgaddr,
-                               "Origin address: %s",
-                                       get_hostname((teredoh->th_iporgaddr)^(0xFFFFFFFF)));
-
-                       proto_tree_add_uint_hidden(teredo_origin_tree, hf_teredo_orgheader, tvb, offset, 2,
-                               teredoh->th_header);
-                       proto_tree_add_uint_hidden(teredo_origin_tree, hf_teredo_orgport, tvb, offset+2, 2,
-                               ((teredoh->th_orgport)^(0xFFFF)));
-                       proto_tree_add_ipv4_hidden(teredo_origin_tree, hf_teredo_orgaddr, tvb, offset + 4, 4,
-                               ((teredoh->th_iporgaddr)^(0xFFFFFFFF)));
-               };
-
-               offset+=8; /*Skip over Origin Header*/ 
-       };
-
-       if ( (hi_nibble(teredoh->th_ip_v_hl) == 6)
-               && ((teredoh->th_indtyp) != 1) ) { /* checking if the first 4 bits = 6 */
-
-               if (tree) {
-                       if (teredo_summary_in_tree) {
-                               ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset, 0,"TEREDO simple encapsulation  ");
-                       }
-               }
-
-               offset+=0;
+       if ( teredoh->th_header == 0 ) {
+               offset = parse_teredo_orig(tvb, pinfo, teredo_tree,
+                                               offset, teredoh);
        }
 
+       teredoh->th_ip_v_hl = tvb_get_guint8(tvb, offset);
+
        decode_teredo_ports(tvb, offset, pinfo, tree, teredoh->th_header /* , teredoh->th_orgport*/);
        tap_queue_packet(teredo_tap, pinfo, teredoh);    
 }
@@ -223,32 +254,72 @@ void
 proto_register_teredo(void)
 {
        static hf_register_info hf[] = {
-
-               { &hf_teredo_authheader,
-               { "Teredo Authentication packet Header","teredo.authheader", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
-
-               { &hf_teredo_orgheader,
-               { "Teredo Origin encapsulation header","teredo.orgheader", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
-
-               { &hf_teredo_orgport,
-               { "Origin Port",        "teredo.orgport", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
-
-               { &hf_teredo_orgaddr,
-               { "Origin IPv4 address","teredo.orgaddr", FT_IPv4, BASE_NONE, NULL, 0x0,"", HFILL }},
-
+               /* Authentication header */
+               { &hf_teredo_auth,
+               { "Teredo Authentication header", "teredo.auth",
+                 FT_NONE, BASE_NONE, NULL, 0x0,
+                 "Teredo Authentication header", HFILL }},
+  
+               { &hf_teredo_auth_idlen,
+               { "Client identifier length", "teredo.auth.idlen",
+                 FT_UINT8, BASE_DEC, NULL, 0x0,
+                 "Client identifier length (ID-len)", HFILL }},
+
+               { &hf_teredo_auth_aulen,
+               { "Authentication value length", "teredo.auth.aulen",
+                 FT_UINT8, BASE_DEC, NULL, 0x0,
+                 "Authentication value length (AU-len)", HFILL }},
+
+               { &hf_teredo_auth_id,
+               { "Client identifier", "teredo.auth.id",
+                 FT_BYTES, BASE_NONE, NULL, 0x0,
+                 "Client identifier (ID)", HFILL }},
+
+               { &hf_teredo_auth_value,
+               { "Authentication value", "teredo.auth.value",
+                 FT_BYTES, BASE_NONE, NULL, 0x0,
+                 "Authentication value (hash)", HFILL }},
+
+               { &hf_teredo_auth_nonce,
+               { "Nonce value", "teredo.auth.nonce",
+                 FT_BYTES, BASE_NONE, NULL, 0x0,
+                 "Nonce value prevents spoofing Teredo server.",
+                 HFILL }},
+
+               { &hf_teredo_auth_conf,
+               { "Confirmation byte", "teredo.auth.conf",
+                 FT_BYTES, BASE_NONE, NULL, 0x0,
+                 "Confirmation byte is zero upon successful authentication.",
+                 HFILL }},
+
+               /* Origin indication */
+               { &hf_teredo_orig,
+               { "Teredo Origin Indication header", "teredo.orig",
+                 FT_NONE, BASE_NONE, NULL, 0x0,
+                 "Teredo Origin Indication", HFILL }},
+
+               { &hf_teredo_orig_port,
+               { "Origin UDP port", "teredo.orig.port",
+                 FT_UINT16, BASE_DEC, NULL, 0x0,
+                 "Origin UDP port", HFILL }},
+
+               { &hf_teredo_orig_addr,
+               { "Origin IPv4 address", "teredo.orig.addr",
+                 FT_IPv4, BASE_NONE, NULL, 0x0,
+                 "Origin IPv4 address", HFILL }},
        };
 
        static gint *ett[] = {
-               &ett_teredo,
+               &ett_teredo, &ett_teredo_auth, &ett_teredo_orig
        };
 
-       proto_teredo = proto_register_protocol("TEREDO Tunneling IPv6 over UDP through NATs",
-           "TEREDO", "teredo");
+       proto_teredo = proto_register_protocol(
+               "Teredo IPv6 over UDP tunneling", "Teredo", "teredo");
        proto_register_field_array(proto_teredo, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
 /* subdissector code */
-       teredo_dissector_table = register_dissector_table("teredo","TEREDO ", FT_UINT16, BASE_DEC);
+       teredo_dissector_table = register_dissector_table("teredo","Teredo ", FT_UINT16, BASE_DEC);
 /*     register_heur_dissector_list("teredo.heur", &heur_subdissector_list); */
 
 }
@@ -262,6 +333,6 @@ proto_reg_handoff_teredo(void)
        data_handle   = find_dissector("ipv6");
        teredo_tap    = register_tap("teredo");
 
-       dissector_add("udp.port", UDP_PORT_TERREDO, teredo_handle);
+       dissector_add("udp.port", UDP_PORT_TEREDO, teredo_handle);
 }