Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-teredo.c
blob353181bef81e8daf6e90ae53677739c077541701
1 /* packet-teredo.c v.1.0
2 * Routines for Teredo packets disassembly
3 * draft-huitema-v6ops-teredo-02.txt
5 * Copyright 2003, Ragi BEJJANI - 6WIND - <ragi.bejjani@6wind.com>
6 * Copyright 2003, Vincent JARDIN - 6WIND - <vincent.jardin@6wind.com>
7 * Copyright 2004, Remi DENIS-COURMONT
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "config.h"
18 #include <epan/packet.h>
19 #include <epan/prefs.h>
21 #include <epan/tap.h>
23 #define UDP_PORT_TEREDO 3544
25 void proto_reg_handoff_teredo(void);
26 void proto_register_teredo(void);
28 static int teredo_tap;
30 static int proto_teredo;
32 static int hf_teredo_auth;
33 static int hf_teredo_auth_idlen;
34 static int hf_teredo_auth_aulen;
35 static int hf_teredo_auth_id;
36 static int hf_teredo_auth_value;
37 static int hf_teredo_auth_nonce;
38 static int hf_teredo_auth_conf;
39 static int hf_teredo_orig;
40 static int hf_teredo_orig_port;
41 static int hf_teredo_orig_addr;
43 static int ett_teredo;
44 static int ett_teredo_auth;
45 static int ett_teredo_orig;
47 typedef struct {
48 uint16_t th_indtyp;
49 uint8_t th_cidlen;
50 uint8_t th_authdlen;
51 uint8_t th_nonce[8];
52 uint8_t th_conf;
54 uint8_t th_ip_v_hl;
55 uint16_t th_header;
56 uint16_t th_orgport;
57 uint32_t th_iporgaddr;
58 } e_teredohdr;
60 static dissector_table_t teredo_dissector_table;
61 /*static heur_dissector_list_t heur_subdissector_list;*/
62 static dissector_handle_t teredo_handle;
63 static dissector_handle_t data_handle;
65 static int
66 parse_teredo_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
67 int offset, e_teredohdr *teredoh)
69 unsigned idlen, aulen;
71 col_append_sep_str (pinfo->cinfo, COL_INFO, ", ",
72 "Authentication header");
74 teredoh->th_indtyp = 1;
75 offset += 2;
77 idlen = tvb_get_uint8(tvb, offset);
78 teredoh->th_cidlen = idlen;
79 offset++;
81 aulen = tvb_get_uint8(tvb, offset);
82 teredoh->th_authdlen = aulen;
83 offset++;
85 if (tree) {
86 proto_item *ti;
88 ti = proto_tree_add_item(tree, hf_teredo_auth, tvb, offset-4,
89 13 + idlen + aulen, ENC_NA);
90 tree = proto_item_add_subtree(ti, ett_teredo_auth);
92 proto_tree_add_item(tree, hf_teredo_auth_idlen, tvb,
93 offset - 2, 1, ENC_BIG_ENDIAN);
94 proto_tree_add_item(tree, hf_teredo_auth_aulen, tvb,
95 offset - 1, 1, ENC_BIG_ENDIAN);
97 /* idlen is usually zero */
98 if (idlen) {
99 proto_tree_add_item(tree, hf_teredo_auth_id, tvb,
100 offset, idlen, ENC_NA);
101 offset += idlen;
104 /* aulen is usually zero */
105 if (aulen) {
106 proto_tree_add_item(tree, hf_teredo_auth_value, tvb,
107 offset, aulen, ENC_NA);
108 offset += aulen;
111 proto_tree_add_item(tree, hf_teredo_auth_nonce, tvb,
112 offset, 8, ENC_NA);
113 offset += 8;
115 proto_tree_add_item(tree, hf_teredo_auth_conf, tvb,
116 offset, 1, ENC_NA);
117 offset++;
119 else
120 offset += idlen + aulen + 9;
122 tvb_memcpy(tvb, teredoh->th_nonce, offset - 9, 8);
123 teredoh->th_conf = tvb_get_uint8(tvb, offset - 1);
125 return offset;
129 static int
130 parse_teredo_orig(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
131 int offset, e_teredohdr *teredoh)
133 proto_item *ti = NULL;
135 col_append_sep_str (pinfo->cinfo, COL_INFO, ", ",
136 "Origin indication");
138 if (tree) {
139 ti = proto_tree_add_item(tree, hf_teredo_orig, tvb, offset,
140 8, ENC_NA);
141 tree = proto_item_add_subtree(ti, ett_teredo_orig);
143 offset += 2;
145 teredoh->th_orgport = tvb_get_ntohs(tvb, offset);
146 if (tree) {
148 * The "usual arithmetic conversions" will convert
149 * "teredoh->th_orgport" to an "int" (because all
150 * "unsigned short" values will fit in an "int"),
151 * which will zero-extend it. This means that
152 * complementing it will turn all the zeroes in
153 * the upper 16 bits into ones; we just want the
154 * lower 16 bits (containing the port number)
155 * complemented, with the result zero-extended.
157 * That's what the cast is for.
159 proto_tree_add_uint(tree, hf_teredo_orig_port, tvb,
160 offset, 2,
161 (uint16_t)~teredoh->th_orgport);
163 offset += 2;
165 teredoh->th_iporgaddr = tvb_get_ipv4(tvb, offset);
166 if (tree) {
167 proto_tree_add_ipv4(tree, hf_teredo_orig_addr, tvb,
168 offset, 4, ~teredoh->th_iporgaddr);
170 offset += 4;
172 return offset;
176 /* Determine if there is a sub-dissector and call it. This has been */
177 /* separated into a stand alone routine to other protocol dissectors */
178 /* can call to it, ie. socks */
181 static void
182 decode_teredo_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,proto_tree *tree, int th_header)
184 tvbuff_t *next_tvb;
186 next_tvb = tvb_new_subset_remaining(tvb, offset);
188 if (dissector_try_uint(teredo_dissector_table, th_header, next_tvb, pinfo, tree))
189 return;
191 call_dissector(data_handle,next_tvb, pinfo, tree);
194 static int
195 dissect_teredo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
197 proto_tree *teredo_tree;
198 proto_item *ti;
199 int offset = 0;
200 static e_teredohdr teredohstruct[4], *teredoh;
201 static int teredoh_count = 0;
203 teredoh_count++;
204 if(teredoh_count>=4){
205 teredoh_count=0;
207 teredoh = &teredohstruct[teredoh_count];
209 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Teredo");
210 col_clear(pinfo->cinfo, COL_INFO);
212 ti = proto_tree_add_item(tree, proto_teredo, tvb, 0, -1, ENC_NA);
213 teredo_tree = proto_item_add_subtree(ti, ett_teredo);
215 teredoh->th_header = tvb_get_ntohs(tvb, offset);
217 if (teredoh->th_header == 1) {
218 offset = parse_teredo_auth(tvb, pinfo, teredo_tree,
219 offset, teredoh);
220 teredoh->th_header = tvb_get_ntohs(tvb, offset);
222 else
223 teredoh->th_indtyp = 0;
225 if ( teredoh->th_header == 0 ) {
226 offset = parse_teredo_orig(tvb, pinfo, teredo_tree,
227 offset, teredoh);
230 teredoh->th_ip_v_hl = tvb_get_uint8(tvb, offset);
232 decode_teredo_ports(tvb, offset, pinfo, tree, teredoh->th_header /* , teredoh->th_orgport*/);
233 tap_queue_packet(teredo_tap, pinfo, teredoh);
234 return tvb_captured_length(tvb);
238 static bool
239 dissect_teredo_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
241 uint16_t val;
242 int offset = 0;
244 if (tvb_captured_length_remaining(tvb, offset) < 40)
245 return false;
247 val = tvb_get_ntohs(tvb, offset);
249 if (val == 1) /* possible auth header */
251 uint8_t idlen, aulen;
253 offset += 2;
255 idlen = tvb_get_uint8(tvb, offset);
256 offset++;
258 aulen = tvb_get_uint8(tvb, offset);
259 offset += 10;
261 if (tvb_captured_length_remaining(tvb, offset) < idlen + aulen + 40)
262 return false;
264 offset += idlen + aulen;
266 val = tvb_get_ntohs(tvb, offset);
269 if (val == 0) /* origin indication */
271 offset += 8;
273 if (tvb_captured_length_remaining(tvb, offset) < 40)
274 return false;
276 val = tvb_get_ntohs(tvb, offset);
280 * We have to check upper-layer packet a little bit otherwise we will
281 * match -almost- *ANY* packet.
282 * These checks are in the Teredo specification by the way.
283 * Unfortunately, that will cause false-negative if the snaplen is too
284 * short to get the packet entirely.
286 if ((val >> 12) == 6) /* IPv6 header */
288 /* checks IPv6 payload length */
289 val = tvb_get_ntohs(tvb, offset + 4);
290 offset += 40;
292 if (val > 65467)
293 return false; /* length too big for Teredo */
295 if (tvb_reported_length_remaining(tvb, offset) != val)
296 return false; /* length mismatch */
298 dissect_teredo (tvb, pinfo, tree, data);
299 return true;
302 return false; /* not an IPv6 packet */
306 void
307 proto_register_teredo(void)
309 static hf_register_info hf[] = {
310 /* Authentication header */
311 { &hf_teredo_auth,
312 { "Teredo Authentication header", "teredo.auth",
313 FT_NONE, BASE_NONE, NULL, 0x0,
314 NULL, HFILL }},
316 { &hf_teredo_auth_idlen,
317 { "Client identifier length", "teredo.auth.idlen",
318 FT_UINT8, BASE_DEC, NULL, 0x0,
319 "Client identifier length (ID-len)", HFILL }},
321 { &hf_teredo_auth_aulen,
322 { "Authentication value length", "teredo.auth.aulen",
323 FT_UINT8, BASE_DEC, NULL, 0x0,
324 "Authentication value length (AU-len)", HFILL }},
326 { &hf_teredo_auth_id,
327 { "Client identifier", "teredo.auth.id",
328 FT_BYTES, BASE_NONE, NULL, 0x0,
329 "Client identifier (ID)", HFILL }},
331 { &hf_teredo_auth_value,
332 { "Authentication value", "teredo.auth.value",
333 FT_BYTES, BASE_NONE, NULL, 0x0,
334 "Authentication value (hash)", HFILL }},
336 { &hf_teredo_auth_nonce,
337 { "Nonce value", "teredo.auth.nonce",
338 FT_BYTES, BASE_NONE, NULL, 0x0,
339 "Nonce value prevents spoofing Teredo server.",
340 HFILL }},
342 { &hf_teredo_auth_conf,
343 { "Confirmation byte", "teredo.auth.conf",
344 FT_BYTES, BASE_NONE, NULL, 0x0,
345 "Confirmation byte is zero upon successful authentication.",
346 HFILL }},
348 /* Origin indication */
349 { &hf_teredo_orig,
350 { "Teredo Origin Indication header", "teredo.orig",
351 FT_NONE, BASE_NONE, NULL, 0x0,
352 NULL, HFILL }},
354 { &hf_teredo_orig_port,
355 { "Origin UDP port", "teredo.orig.port",
356 FT_UINT16, BASE_DEC, NULL, 0x0,
357 NULL, HFILL }},
359 { &hf_teredo_orig_addr,
360 { "Origin IPv4 address", "teredo.orig.addr",
361 FT_IPv4, BASE_NONE, NULL, 0x0,
362 NULL, HFILL }},
365 static int *ett[] = {
366 &ett_teredo, &ett_teredo_auth, &ett_teredo_orig
369 module_t *teredo_module;
371 proto_teredo = proto_register_protocol("Teredo IPv6 over UDP tunneling", "Teredo", "teredo");
372 proto_register_field_array(proto_teredo, hf, array_length(hf));
373 proto_register_subtree_array(ett, array_length(ett));
374 teredo_handle = register_dissector("teredo", dissect_teredo, proto_teredo);
376 /* subdissector code */
377 teredo_dissector_table = register_dissector_table("teredo", "Teredo", proto_teredo, FT_UINT16, BASE_DEC);
379 teredo_module = prefs_register_protocol(proto_teredo, NULL);
381 prefs_register_obsolete_preference(teredo_module, "heuristic_teredo");
383 teredo_tap = register_tap("teredo");
386 void
387 proto_reg_handoff_teredo(void)
389 data_handle = find_dissector("ipv6");
391 dissector_add_uint_with_preference("udp.port", UDP_PORT_TEREDO, teredo_handle);
392 heur_dissector_add("udp", dissect_teredo_heur, "Teredo over UDP", "teredo_udp", proto_teredo, HEURISTIC_DISABLE);
396 * Editor modelines - https://www.wireshark.org/tools/modelines.html
398 * Local variables:
399 * c-basic-offset: 8
400 * tab-width: 8
401 * indent-tabs-mode: t
402 * End:
404 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
405 * :indentSize=8:tabSize=8:noTabs=false: