HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-babel.c
blobd9818ccdd7ab42f8cba4b223bfc53728287c0ff0
1 /* packet-babel.c
2 * Routines for Babel dissection (RFC 6126)
3 * Copyright 2011 by Juliusz Chroboczek <jch@pps.jussieu.fr>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/to_str.h>
32 #include <epan/wmem/wmem.h>
34 void proto_register_babel(void);
35 void proto_reg_handoff_babel(void);
37 static int proto_babel = -1;
39 static gint ett_babel = -1;
40 static int hf_babel_magic = -1;
41 static int hf_babel_version = -1;
42 static int hf_babel_bodylen = -1;
44 static int hf_babel_message = -1;
45 static gint ett_message = -1;
46 static int hf_babel_message_type = -1;
47 static int hf_babel_message_length = -1;
48 static int hf_babel_message_nonce = -1;
49 static int hf_babel_message_interval = -1;
50 static int hf_babel_message_seqno = -1;
51 static int hf_babel_message_ae = -1;
52 static int hf_babel_message_prefix = -1;
53 static int hf_babel_message_rxcost = -1;
54 static int hf_babel_message_routerid = -1;
55 static int hf_babel_message_flags = -1;
56 static int hf_babel_message_plen = -1;
57 static int hf_babel_message_omitted = -1;
58 static int hf_babel_message_metric = -1;
59 static int hf_babel_message_hopcount = -1;
61 static gint ett_subtree = -1;
63 #define UDP_PORT_BABEL 6696
64 #define UDP_PORT_BABEL_OLD 6697
66 #define MESSAGE_PAD1 0
67 #define MESSAGE_PADN 1
68 #define MESSAGE_ACK_REQ 2
69 #define MESSAGE_ACK 3
70 #define MESSAGE_HELLO 4
71 #define MESSAGE_IHU 5
72 #define MESSAGE_ROUTER_ID 6
73 #define MESSAGE_NH 7
74 #define MESSAGE_UPDATE 8
75 #define MESSAGE_REQUEST 9
76 #define MESSAGE_MH_REQUEST 10
78 static const value_string messages[] = {
79 { MESSAGE_PAD1, "pad1"},
80 { MESSAGE_PADN, "padn"},
81 { MESSAGE_ACK_REQ, "ack-req"},
82 { MESSAGE_ACK, "ack"},
83 { MESSAGE_HELLO, "hello"},
84 { MESSAGE_IHU, "ihu"},
85 { MESSAGE_ROUTER_ID, "router-id"},
86 { MESSAGE_NH, "nh"},
87 { MESSAGE_UPDATE, "update"},
88 { MESSAGE_REQUEST, "request"},
89 { MESSAGE_MH_REQUEST, "mh-request"},
90 { 0, NULL}
93 static const value_string aes[] = {
94 { 0, "Wildcard" },
95 { 1, "IPv4" },
96 { 2, "IPv6" },
97 { 3, "Link-Local IPv6"},
98 { 0, NULL }
101 /* The prefix for v6-mapped IPv4 addresses. Format_address below
102 returns IPv4 addresses in that format. */
104 static const unsigned char v4prefix[16] =
105 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
107 /* The following two functions return ephemeral or constant strings, no
108 need to call free. */
110 static const char *
111 format_address(const unsigned char *prefix)
113 if (prefix == NULL)
114 return "corrupt";
115 else if (memcmp(prefix, v4prefix, 12) == 0)
116 return ip_to_str(prefix + 12);
117 else
118 return ip6_to_str((const struct e_in6_addr*)prefix);
121 static const char *
122 format_prefix(const unsigned char *prefix, unsigned char plen)
124 return wmem_strdup_printf(wmem_packet_scope(), "%s/%u", format_address(prefix), plen);
127 static int
128 network_prefix(int ae, int plen, unsigned int omitted,
129 const unsigned char *p, const unsigned char *dp,
130 unsigned int len, unsigned char *p_r)
132 guint pb;
133 unsigned char prefix[16];
135 if (plen >= 0)
136 pb = (plen + 7) / 8;
137 else if (ae == 1)
138 pb = 4;
139 else
140 pb = 16;
142 if (pb > 16)
143 return -1;
145 memset(prefix, 0, 16);
147 switch(ae) {
148 case 0: break;
149 case 1:
150 if (omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
151 return -1;
152 memcpy(prefix, v4prefix, 12);
153 if (omitted) {
154 if (dp == NULL) return -1;
155 memcpy(prefix, dp, 12 + omitted);
157 if (pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
158 break;
159 case 2:
160 if (omitted > 16 || (pb > omitted && len < pb - omitted))
161 return -1;
162 if (omitted) {
163 if (dp == NULL) return -1;
164 memcpy(prefix, dp, omitted);
166 if (pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
167 break;
168 case 3:
169 if (pb > 8 && len < pb - 8) return -1;
170 prefix[0] = 0xfe;
171 prefix[1] = 0x80;
172 if (pb > 8) memcpy(prefix + 8, p, pb - 8);
173 break;
174 default:
175 return -1;
178 memcpy(p_r, prefix, 16);
179 return 1;
182 static int
183 network_address(int ae, const unsigned char *a, unsigned int len,
184 unsigned char *a_r)
186 return network_prefix(ae, -1, 0, a, NULL, len, a_r);
189 static int
190 dissect_babel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
192 proto_item *ti;
193 unsigned char v4_prefix[16] = {0}, v6_prefix[16] = {0};
194 int i;
195 proto_tree *babel_tree = NULL;
196 guint8 version;
197 guint16 bodylen;
199 if (tvb_length(tvb) < 4)
200 return 0;
202 if (tvb_get_guint8(tvb, 0) != 42)
203 return 0;
204 version = tvb_get_guint8(tvb, 1);
206 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Babel");
207 col_set_str(pinfo->cinfo, COL_INFO, "Babel");
209 if (version != 2) {
210 col_add_fstr(pinfo->cinfo, COL_INFO, "Version %u", version);
211 return 2;
214 if (tree) {
215 ti = proto_tree_add_item(tree, proto_babel, tvb, 0, -1, ENC_NA);
216 babel_tree = proto_item_add_subtree(ti, ett_babel);
218 proto_tree_add_item(babel_tree, hf_babel_magic, tvb, 0, 1, ENC_NA);
219 proto_tree_add_item(babel_tree, hf_babel_version, tvb, 1, 1, ENC_NA);
220 proto_tree_add_item(babel_tree, hf_babel_bodylen,
221 tvb, 2, 2, ENC_BIG_ENDIAN);
224 bodylen = tvb_get_ntohs(tvb, 2);
226 i = 0;
227 while (i < bodylen) {
228 guint8 type, len = 0, total_length;
229 proto_tree *message_tree = NULL;
230 int message = 4 + i;
232 type = tvb_get_guint8(tvb, message);
233 if (type == MESSAGE_PAD1)
234 total_length = 1;
235 else {
236 len = tvb_get_guint8(tvb, message + 1);
237 total_length = len + 2;
240 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
241 val_to_str_const(type, messages, "unknown"));
243 ti = proto_tree_add_uint_format(babel_tree, hf_babel_message,
244 tvb, message, total_length, type,
245 "Message %s (%u)",
246 val_to_str_const(type, messages, "unknown"),
247 type);
249 if (tree) {
250 message_tree = proto_item_add_subtree(ti, ett_message);
251 proto_tree_add_item(message_tree, hf_babel_message_type,
252 tvb, message, 1, ENC_NA);
255 if (type == MESSAGE_PAD1) {
256 i++;
257 continue;
260 if (tree) {
261 proto_tree_add_item(message_tree, hf_babel_message_length,
262 tvb, message + 1, 1, ENC_BIG_ENDIAN);
264 if (type == MESSAGE_PADN) {
265 } else if (type == MESSAGE_ACK_REQ) {
266 proto_tree_add_item(message_tree, hf_babel_message_nonce,
267 tvb, message + 4, 2, ENC_BIG_ENDIAN);
268 proto_tree_add_item(message_tree, hf_babel_message_interval,
269 tvb, message + 6, 2, ENC_BIG_ENDIAN);
270 } else if (type == MESSAGE_ACK) {
271 proto_tree_add_item(message_tree, hf_babel_message_nonce,
272 tvb, message + 2, 2, ENC_BIG_ENDIAN);
273 } else if (type == MESSAGE_HELLO) {
274 proto_tree_add_item(message_tree, hf_babel_message_seqno,
275 tvb, message + 4, 2, ENC_BIG_ENDIAN);
276 proto_tree_add_item(message_tree, hf_babel_message_interval,
277 tvb, message + 6, 2, ENC_BIG_ENDIAN);
278 } else if (type == MESSAGE_IHU) {
279 proto_tree *subtree;
280 unsigned char addr_str[16];
281 int rc =
282 network_address(tvb_get_guint8(tvb, message + 2),
283 tvb_get_ptr(tvb, message + 8, len - 6),
284 len - 6,
285 addr_str);
286 proto_tree_add_item(message_tree, hf_babel_message_rxcost,
287 tvb, message + 4, 2, ENC_BIG_ENDIAN);
288 proto_tree_add_item(message_tree, hf_babel_message_interval,
289 tvb, message + 6, 2, ENC_BIG_ENDIAN);
290 ti = proto_tree_add_text(message_tree,
291 tvb, message + 4, len - 2,
292 "Address: %s",
293 format_address(rc < 0 ?
294 NULL : addr_str));
295 subtree = proto_item_add_subtree(ti, ett_subtree);
296 proto_tree_add_item(subtree, hf_babel_message_ae,
297 tvb, message + 2, 1, ENC_NA);
298 proto_tree_add_item(subtree, hf_babel_message_prefix,
299 tvb, message + 4, len - 2, ENC_NA);
300 } else if (type == MESSAGE_ROUTER_ID) {
301 proto_tree_add_item(message_tree, hf_babel_message_routerid,
302 tvb, message + 4, 8, ENC_NA);
303 } else if (type == MESSAGE_NH) {
304 proto_tree *subtree;
305 unsigned char nh[16];
306 int rc =
307 network_address(tvb_get_guint8(tvb, message + 2),
308 tvb_get_ptr(tvb, message + 4, len - 2),
309 len - 2,
310 nh);
311 ti = proto_tree_add_text(message_tree,
312 tvb, message + 4, len - 2,
313 "NH: %s",
314 format_address(rc < 0 ? NULL : nh));
315 subtree = proto_item_add_subtree(ti, ett_subtree);
316 proto_tree_add_item(subtree, hf_babel_message_ae,
317 tvb, message + 2, 1, ENC_NA);
318 proto_tree_add_item(subtree, hf_babel_message_prefix,
319 tvb, message + 4, len - 2, ENC_NA);
320 } else if (type == MESSAGE_UPDATE) {
322 proto_tree *subtree;
323 unsigned char p[16];
324 guint8 ae = tvb_get_guint8(tvb, message + 2);
325 guint8 flags = tvb_get_guint8(tvb, message + 3);
326 guint8 plen = tvb_get_guint8(tvb, message + 4);
327 int rc =
328 network_prefix(ae, plen,
329 tvb_get_guint8(tvb, message + 5),
330 tvb_get_ptr(tvb, message + 12, len - 10),
331 ae == 1 ? v4_prefix : v6_prefix,
332 len - 10, p);
333 if (rc >= 0 && (flags & 0x80)) {
334 if (ae == 1)
335 memcpy(v4_prefix, p, 16);
336 else
337 memcpy(v6_prefix, p, 16);
340 proto_tree_add_item(message_tree, hf_babel_message_flags,
341 tvb, message + 3, 1, ENC_NA);
342 proto_tree_add_item(message_tree, hf_babel_message_interval,
343 tvb, message + 6, 2, ENC_BIG_ENDIAN);
344 proto_tree_add_item(message_tree, hf_babel_message_seqno,
345 tvb, message + 8, 2, ENC_BIG_ENDIAN);
346 proto_tree_add_item(message_tree, hf_babel_message_metric,
347 tvb, message + 10, 2, ENC_BIG_ENDIAN);
348 ti = proto_tree_add_text(message_tree,
349 tvb, message + 12, len - 10,
350 "Prefix: %s",
351 format_prefix(rc < 0 ? NULL : p,
352 plen));
353 subtree = proto_item_add_subtree(ti, ett_subtree);
354 proto_tree_add_item(subtree, hf_babel_message_ae,
355 tvb, message + 2, 1, ENC_NA);
356 proto_tree_add_item(subtree, hf_babel_message_plen,
357 tvb, message + 4, 1, ENC_NA);
358 proto_tree_add_item(subtree, hf_babel_message_omitted,
359 tvb, message + 5, 1, ENC_NA);
360 proto_tree_add_item(subtree, hf_babel_message_prefix,
361 tvb, message + 12, len - 10, ENC_NA);
362 } else if (type == MESSAGE_REQUEST) {
363 proto_tree *subtree;
364 unsigned char p[16];
365 guint8 plen = tvb_get_guint8(tvb, message + 3);
366 int rc =
367 network_prefix(tvb_get_guint8(tvb, message + 2), plen,
369 tvb_get_ptr(tvb, message + 4, len - 2),
370 NULL,
371 len - 2, p);
372 ti = proto_tree_add_text(message_tree,
373 tvb, message + 4, len - 2,
374 "Prefix: %s",
375 format_prefix(rc < 0 ? NULL : p,
376 plen));
377 subtree = proto_item_add_subtree(ti, ett_subtree);
378 proto_tree_add_item(subtree, hf_babel_message_ae,
379 tvb, message + 2, 1, ENC_NA);
380 proto_tree_add_item(subtree, hf_babel_message_plen,
381 tvb, message + 3, 1, ENC_NA);
382 proto_tree_add_item(subtree, hf_babel_message_prefix,
383 tvb, message + 4, len - 2, ENC_NA);
384 } else if (type == MESSAGE_MH_REQUEST) {
385 proto_tree *subtree;
386 unsigned char p[16];
387 guint8 plen = tvb_get_guint8(tvb, message + 3);
388 int rc =
389 network_prefix(tvb_get_guint8(tvb, message + 2), plen,
391 tvb_get_ptr(tvb, message + 16, len - 14),
392 NULL,
393 len - 14, p);
394 proto_tree_add_item(message_tree, hf_babel_message_seqno,
395 tvb, message + 4, 2, ENC_BIG_ENDIAN);
396 proto_tree_add_item(message_tree, hf_babel_message_hopcount,
397 tvb, message + 6, 1, ENC_NA);
398 proto_tree_add_item(message_tree, hf_babel_message_routerid,
399 tvb, message + 8, 8, ENC_NA);
400 ti = proto_tree_add_text(message_tree,
401 tvb, message + 16, len - 14,
402 "Prefix: %s",
403 format_prefix(rc < 0 ? NULL : p,
404 plen));
405 subtree = proto_item_add_subtree(ti, ett_subtree);
406 proto_tree_add_item(subtree, hf_babel_message_ae,
407 tvb, message + 2, 1, ENC_NA);
408 proto_tree_add_item(subtree, hf_babel_message_plen,
409 tvb, message + 3, 1, ENC_NA);
410 proto_tree_add_item(subtree, hf_babel_message_prefix,
411 tvb, message + 16, len - 14, ENC_NA);
414 i += len + 2;
416 return i;
419 void
420 proto_register_babel(void)
422 static hf_register_info hf[] = {
423 { &hf_babel_magic,
424 { "Magic", "babel.magic", FT_UINT8, BASE_DEC,
425 NULL, 0, "Magic value 42", HFILL }
427 { &hf_babel_version,
428 { "Version", "babel.version", FT_UINT8, BASE_DEC,
429 NULL, 0, "Version of the Babel protocol", HFILL }
431 { &hf_babel_bodylen,
432 { "Body Length", "babel.bodylen", FT_UINT16, BASE_DEC,
433 NULL, 0, NULL, HFILL }
435 { &hf_babel_message,
436 { "Message", "babel.message", FT_UINT8, BASE_DEC,
437 NULL, 0, "Babel Message", HFILL }
439 { &hf_babel_message_type,
440 { "Message Type", "babel.message.type", FT_UINT8, BASE_DEC,
441 VALS(messages), 0, NULL, HFILL }
443 { &hf_babel_message_length,
444 { "Message Length", "babel.message.length", FT_UINT8, BASE_DEC,
445 NULL, 0, NULL, HFILL }
447 { &hf_babel_message_nonce,
448 { "Nonce", "babel.message.nonce", FT_UINT16, BASE_HEX,
449 NULL, 0, NULL, HFILL }
451 { &hf_babel_message_interval,
452 { "Interval", "babel.message.interval", FT_UINT16, BASE_DEC,
453 NULL, 0, "Interval (in centiseconds)", HFILL }
455 { &hf_babel_message_seqno,
456 { "Seqno", "babel.message.seqno", FT_UINT16, BASE_HEX,
457 NULL, 0, NULL, HFILL }
459 { &hf_babel_message_ae,
460 { "Address Encoding", "babel.message.ae", FT_UINT8, BASE_DEC,
461 VALS(aes), 0, NULL, HFILL }
463 { &hf_babel_message_prefix,
464 { "Raw Prefix", "babel.message.prefix", FT_BYTES, BASE_NONE,
465 NULL, 0, NULL, HFILL }
467 { &hf_babel_message_rxcost,
468 { "Rxcost", "babel.message.rxcost", FT_UINT16, BASE_HEX,
469 NULL, 0, "Rxcost (from the point of vue of the sender)", HFILL }
471 { &hf_babel_message_routerid,
472 { "Router ID", "babel.message.routerid", FT_BYTES, BASE_NONE,
473 NULL, 0, NULL, HFILL }
475 { &hf_babel_message_flags,
476 { "Flags", "babel.message.flags", FT_UINT8, BASE_HEX,
477 NULL, 0, NULL, HFILL }
479 { &hf_babel_message_plen,
480 { "Prefix Length", "babel.message.plen", FT_UINT8, BASE_DEC,
481 NULL, 0, NULL, HFILL }
483 { &hf_babel_message_omitted,
484 { "Omitted Bytes", "babel.message.omitted", FT_UINT8, BASE_DEC,
485 NULL, 0, "Number of bytes omitted from the prefix", HFILL }
487 { &hf_babel_message_metric,
488 { "Metric", "babel.message.metric", FT_UINT16, BASE_DEC,
489 NULL, 0, NULL, HFILL }
491 { &hf_babel_message_hopcount,
492 { "Hop Count", "babel.message.hopcount", FT_UINT8, BASE_DEC,
493 NULL, 0, NULL, HFILL }
497 static gint *ett[] = {
498 &ett_babel,
499 &ett_message,
500 &ett_subtree,
503 proto_babel =
504 proto_register_protocol("Babel Routing Protocol", "Babel", "babel");
506 proto_register_field_array(proto_babel, hf, array_length(hf));
507 proto_register_subtree_array(ett, array_length(ett));
510 void
511 proto_reg_handoff_babel(void)
513 dissector_handle_t babel_handle;
515 babel_handle = new_create_dissector_handle(dissect_babel, proto_babel);
516 dissector_add_uint("udp.port", UDP_PORT_BABEL, babel_handle);
517 dissector_add_uint("udp.port", UDP_PORT_BABEL_OLD, babel_handle);