Fix some aclocal warnings during autogen.sh
[obnox/wireshark/wip.git] / packet-teredo.c
1 /* packet-teredo.c  v.1.0
2  * Routines for TEREDO packet disassembly
3  *   draft-huitema-v6ops-teredo-00.txt
4  *   Windows XP Teredo
5  *
6  * Copyright 2003, Ragi BEJJANI - 6WIND - <ragi.bejjani@6wind.com>
7  * Copyright 2003, Vincent JARDIN - 6WIND - <vincent.jardin@6wind.com>
8  *
9  * $Id: packet-teredo.c,v 1.4 2003/12/29 00:19:00 guy Exp $
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <glib.h>
39 #include <epan/packet.h>
40 #include <epan/resolv.h>
41 #include "ipproto.h"
42 #include "prefs.h"
43
44 #include "packet-ip.h"
45 #include "tap.h"
46
47 #define UDP_PORT_TERREDO 3544
48
49 static int teredo_tap = -1;
50
51 static int proto_teredo = -1;
52 static int hf_teredo_orgheader = -1;
53 static int hf_teredo_authheader = -1;
54 static int hf_teredo_orgport = -1;
55 static int hf_teredo_orgaddr = -1;
56
57 static gint ett_teredo = -1;
58
59 typedef struct {
60         guint16 th_indtyp;
61         guint8 th_cidlen;
62         guint8 th_authdlen;
63         guint8 th_nonce[8];
64         guint8 th_conf; 
65
66         guint8 th_ip_v_hl;  
67         guint16 th_header;
68         guint16 th_orgport;
69         guint32 th_iporgaddr;
70 } e_teredohdr;
71
72 /* Place TEREDO summary in proto tree */
73 static gboolean teredo_summary_in_tree = TRUE;
74
75 static dissector_table_t teredo_dissector_table;
76 /*static heur_dissector_list_t heur_subdissector_list;*/
77 static dissector_handle_t data_handle;
78
79 /* Determine if there is a sub-dissector and call it.  This has been */
80 /* separated into a stand alone routine to other protocol dissectors */
81 /* can call to it, ie. socks    */
82
83
84 static void
85 decode_teredo_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,proto_tree *tree, int th_header)
86 {
87         tvbuff_t *next_tvb;
88
89         next_tvb = tvb_new_subset(tvb, offset, -1, -1);
90
91         if (dissector_try_port(teredo_dissector_table, th_header, next_tvb, pinfo, tree))
92                 return;
93
94         call_dissector(data_handle,next_tvb, pinfo, tree);  
95 }
96
97 static void
98 dissect_teredo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
99 {
100         proto_tree *teredo_tree;
101         proto_item *ti;
102         int        offset = 0;
103         static e_teredohdr teredohstruct[4], *teredoh;
104         static int teredoh_count = 0;
105
106         proto_item *to;
107         proto_tree *teredo_origin_tree;
108
109         teredoh_count++;
110         if(teredoh_count>=4){
111                 teredoh_count=0;
112         }
113         teredoh = &teredohstruct[teredoh_count];
114
115         if (check_col(pinfo->cinfo, COL_PROTOCOL))
116                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TEREDO");
117         if (check_col(pinfo->cinfo, COL_INFO))
118                 col_clear(pinfo->cinfo, COL_INFO);
119
120         teredoh->th_header  = tvb_get_ntohs(tvb, offset);
121         teredoh->th_ip_v_hl = tvb_get_guint8(tvb, offset);
122         teredoh->th_indtyp  = 0;
123
124         if ( (teredoh->th_header)== 1 ) {
125                 teredoh->th_indtyp   = teredoh->th_header;
126                 teredoh->th_cidlen   = tvb_get_guint8(tvb,offset+2);     /*Authentication header octet*/
127                 teredoh->th_authdlen = tvb_get_guint8(tvb,offset+3);
128                 tvb_memcpy(tvb,teredoh->th_nonce,offset+4,sizeof teredoh->th_nonce);
129                 teredoh->th_conf     = tvb_get_guint8(tvb,offset+12);
130
131                 /*Skip over Authentication Header (fixed length-no authentication)*/
132                 offset+=13;
133                 teredoh->th_header  = tvb_get_ntohs(tvb, offset);
134                 teredoh->th_ip_v_hl = tvb_get_guint8(tvb, offset);
135
136                 if (check_col(pinfo->cinfo, COL_INFO))
137                         col_set_str(pinfo->cinfo, COL_INFO,
138                                 "Teredo : Tunneling IPv6 over UDP through NATs");
139
140                 proto_tree_add_uint_hidden(tree, hf_teredo_authheader, tvb, offset-13, 2, teredoh->th_indtyp);  
141
142                 if (teredo_summary_in_tree) {
143
144                         if (teredoh->th_header!=0) {
145                                 ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset-13, 13,
146                                         "TEREDO with Authentication encapsulation"); 
147                         }
148
149         } else {
150                         ti = proto_tree_add_item(tree, proto_teredo, tvb, offset, 13, FALSE);
151                 }
152         }
153
154         if ( (teredoh->th_header)== 0 ) {
155                 teredoh->th_orgport=tvb_get_ntohs(tvb, offset+2);
156                 tvb_memcpy(tvb, (guint8 *)&teredoh->th_iporgaddr, offset + 4, 4);
157
158                 if (check_col(pinfo->cinfo, COL_INFO))
159                         col_set_str(pinfo->cinfo, COL_INFO,
160                                 "Teredo : Tunneling IPv6 over UDP through NATs");
161
162                 if (tree) {
163                         if (teredo_summary_in_tree) { 
164                                 if (teredoh->th_indtyp==1){
165                                         to = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset-13, 13+8,
166                                                 "TEREDO with Authentication and Origin Indicator encapsulation");  
167                                         teredo_tree = proto_item_add_subtree(to, ett_teredo);
168                                         proto_tree_add_protocol_format(teredo_tree,proto_teredo, tvb,offset-13, 13,
169                                                 "Authentication encapsulation");
170                                         ti = proto_tree_add_protocol_format(teredo_tree, proto_teredo, tvb, offset, 8,
171                                                 "Origin indicator encapsulation")  ;
172                                 } else { 
173                                         ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset, 8,
174                                                 "TEREDO with Origin indicator encapsulation");
175                                 }
176                         } else {
177                                 ti = proto_tree_add_item(tree, proto_teredo, tvb, offset, 8, FALSE);
178                         }
179
180                         teredo_origin_tree = proto_item_add_subtree(ti, ett_teredo);
181
182                         proto_tree_add_uint_format(teredo_origin_tree, hf_teredo_orgheader, tvb, offset, 2,
183                                 teredoh->th_header,
184                                 "Teredo Origin encapsulation header: 0x%04x",
185                                         (teredoh->th_header));
186                         proto_tree_add_uint_format(teredo_origin_tree, hf_teredo_orgport, tvb, offset + 2, 2,
187                                 teredoh->th_orgport,
188                                 "Origin port:  %u",
189                                         ((teredoh->th_orgport)^(0xFFFF)));
190                         proto_tree_add_ipv4_format(teredo_origin_tree, hf_teredo_orgaddr, tvb, offset + 4, 4,
191                                 teredoh->th_iporgaddr,
192                                 "Origin address: %s",
193                                         get_hostname((teredoh->th_iporgaddr)^(0xFFFFFFFF)));
194
195                         proto_tree_add_uint_hidden(teredo_origin_tree, hf_teredo_orgheader, tvb, offset, 2,
196                                 teredoh->th_header);
197                         proto_tree_add_uint_hidden(teredo_origin_tree, hf_teredo_orgport, tvb, offset+2, 2,
198                                 ((teredoh->th_orgport)^(0xFFFF)));
199                         proto_tree_add_ipv4_hidden(teredo_origin_tree, hf_teredo_orgaddr, tvb, offset + 4, 4,
200                                 ((teredoh->th_iporgaddr)^(0xFFFFFFFF)));
201                 };
202
203                 offset+=8; /*Skip over Origin Header*/ 
204         };
205
206         if ( (hi_nibble(teredoh->th_ip_v_hl) == 6)
207                 && ((teredoh->th_indtyp) != 1) ) { /* checking if the first 4 bits = 6 */
208
209                 if (tree) {
210                         if (teredo_summary_in_tree) {
211                                 ti = proto_tree_add_protocol_format(tree, proto_teredo, tvb, offset, 0,"TEREDO simple encapsulation  ");
212                         }
213                 }
214
215                 offset+=0;
216         }
217
218         decode_teredo_ports(tvb, offset, pinfo, tree, teredoh->th_header /* , teredoh->th_orgport*/);
219         tap_queue_packet(teredo_tap, pinfo, teredoh);    
220 }
221
222 void
223 proto_register_teredo(void)
224 {
225         static hf_register_info hf[] = {
226
227                 { &hf_teredo_authheader,
228                 { "Teredo Authentication packet Header","teredo.authheader", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
229
230                 { &hf_teredo_orgheader,
231                 { "Teredo Origin encapsulation header","teredo.orgheader", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
232
233                 { &hf_teredo_orgport,
234                 { "Origin Port",        "teredo.orgport", FT_UINT16, BASE_DEC, NULL, 0x0,"", HFILL }},
235
236                 { &hf_teredo_orgaddr,
237                 { "Origin IPv4 address","teredo.orgaddr", FT_IPv4, BASE_NONE, NULL, 0x0,"", HFILL }},
238
239         };
240
241         static gint *ett[] = {
242                 &ett_teredo,
243         };
244
245         proto_teredo = proto_register_protocol("TEREDO Tunneling IPv6 over UDP through NATs",
246             "TEREDO", "teredo");
247         proto_register_field_array(proto_teredo, hf, array_length(hf));
248         proto_register_subtree_array(ett, array_length(ett));
249
250 /* subdissector code */
251         teredo_dissector_table = register_dissector_table("teredo","TEREDO ", FT_UINT16, BASE_DEC);
252 /*      register_heur_dissector_list("teredo.heur", &heur_subdissector_list); */
253
254 }
255
256 void
257 proto_reg_handoff_teredo(void)
258 {
259         dissector_handle_t teredo_handle;
260
261         teredo_handle = create_dissector_handle(dissect_teredo, proto_teredo);
262         data_handle   = find_dissector("ipv6");
263         teredo_tap    = register_tap("teredo");
264
265         dissector_add("udp.port", UDP_PORT_TERREDO, teredo_handle);
266 }
267