2 * Routines for Babel dissection (RFC 6126)
3 * Copyright 2011 by Juliusz Chroboczek <jch@pps.jussieu.fr>
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.
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
70 #define MESSAGE_HELLO 4
72 #define MESSAGE_ROUTER_ID 6
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"},
87 { MESSAGE_UPDATE
, "update"},
88 { MESSAGE_REQUEST
, "request"},
89 { MESSAGE_MH_REQUEST
, "mh-request"},
93 static const value_string aes
[] = {
97 { 3, "Link-Local IPv6"},
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. */
111 format_address(const unsigned char *prefix
)
115 else if (memcmp(prefix
, v4prefix
, 12) == 0)
116 return ip_to_str(prefix
+ 12);
118 return ip6_to_str((const struct e_in6_addr
*)prefix
);
122 format_prefix(const unsigned char *prefix
, unsigned char plen
)
124 return wmem_strdup_printf(wmem_packet_scope(), "%s/%u", format_address(prefix
), plen
);
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
)
133 unsigned char prefix
[16];
145 memset(prefix
, 0, 16);
150 if (omitted
> 4 || pb
> 4 || (pb
> omitted
&& len
< pb
- omitted
))
152 memcpy(prefix
, v4prefix
, 12);
154 if (dp
== NULL
) return -1;
155 memcpy(prefix
, dp
, 12 + omitted
);
157 if (pb
> omitted
) memcpy(prefix
+ 12 + omitted
, p
, pb
- omitted
);
160 if (omitted
> 16 || (pb
> omitted
&& len
< pb
- omitted
))
163 if (dp
== NULL
) return -1;
164 memcpy(prefix
, dp
, omitted
);
166 if (pb
> omitted
) memcpy(prefix
+ omitted
, p
, pb
- omitted
);
169 if (pb
> 8 && len
< pb
- 8) return -1;
172 if (pb
> 8) memcpy(prefix
+ 8, p
, pb
- 8);
178 memcpy(p_r
, prefix
, 16);
183 network_address(int ae
, const unsigned char *a
, unsigned int len
,
186 return network_prefix(ae
, -1, 0, a
, NULL
, len
, a_r
);
190 dissect_babel(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
193 unsigned char v4_prefix
[16] = {0}, v6_prefix
[16] = {0};
195 proto_tree
*babel_tree
= NULL
;
199 if (tvb_length(tvb
) < 4)
202 if (tvb_get_guint8(tvb
, 0) != 42)
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");
210 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Version %u", version
);
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);
227 while (i
< bodylen
) {
228 guint8 type
, len
= 0, total_length
;
229 proto_tree
*message_tree
= NULL
;
232 type
= tvb_get_guint8(tvb
, message
);
233 if (type
== MESSAGE_PAD1
)
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
,
246 val_to_str_const(type
, messages
, "unknown"),
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
) {
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
) {
280 unsigned char addr_str
[16];
282 network_address(tvb_get_guint8(tvb
, message
+ 2),
283 tvb_get_ptr(tvb
, message
+ 8, len
- 6),
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,
293 format_address(rc
< 0 ?
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
) {
305 unsigned char nh
[16];
307 network_address(tvb_get_guint8(tvb
, message
+ 2),
308 tvb_get_ptr(tvb
, message
+ 4, len
- 2),
311 ti
= proto_tree_add_text(message_tree
,
312 tvb
, message
+ 4, len
- 2,
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
) {
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);
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
,
333 if (rc
>= 0 && (flags
& 0x80)) {
335 memcpy(v4_prefix
, p
, 16);
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,
351 format_prefix(rc
< 0 ? NULL
: p
,
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
) {
365 guint8 plen
= tvb_get_guint8(tvb
, message
+ 3);
367 network_prefix(tvb_get_guint8(tvb
, message
+ 2), plen
,
369 tvb_get_ptr(tvb
, message
+ 4, len
- 2),
372 ti
= proto_tree_add_text(message_tree
,
373 tvb
, message
+ 4, len
- 2,
375 format_prefix(rc
< 0 ? NULL
: p
,
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
) {
387 guint8 plen
= tvb_get_guint8(tvb
, message
+ 3);
389 network_prefix(tvb_get_guint8(tvb
, message
+ 2), plen
,
391 tvb_get_ptr(tvb
, message
+ 16, len
- 14),
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,
403 format_prefix(rc
< 0 ? NULL
: p
,
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
);
420 proto_register_babel(void)
422 static hf_register_info hf
[] = {
424 { "Magic", "babel.magic", FT_UINT8
, BASE_DEC
,
425 NULL
, 0, "Magic value 42", HFILL
}
428 { "Version", "babel.version", FT_UINT8
, BASE_DEC
,
429 NULL
, 0, "Version of the Babel protocol", HFILL
}
432 { "Body Length", "babel.bodylen", FT_UINT16
, BASE_DEC
,
433 NULL
, 0, NULL
, HFILL
}
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
[] = {
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
));
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
);