2 * Routines for zebra packet disassembly
4 * Jochen Friedrich <jochen@scram.de>
6 * $Id: packet-zebra.c,v 1.24 2003/07/09 05:42:23 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include <epan/packet.h>
37 static int proto_zebra = -1;
38 static int hf_zebra_len = -1;
39 static int hf_zebra_command = -1;
40 static int hf_zebra_request = -1;
41 static int hf_zebra_interface = -1;
42 static int hf_zebra_index = -1;
43 static int hf_zebra_indexnum = -1;
44 static int hf_zebra_type = -1;
45 static int hf_zebra_intflags = -1;
46 static int hf_zebra_rtflags = -1;
47 static int hf_zebra_distance = -1;
48 static int hf_zebra_metric = -1;
49 static int hf_zebra_mtu = -1;
50 static int hf_zebra_bandwidth = -1;
51 static int hf_zebra_family = -1;
52 static int hf_zebra_message = -1;
53 static int hf_zebra_msg_nexthop = -1;
54 static int hf_zebra_msg_index = -1;
55 static int hf_zebra_msg_distance = -1;
56 static int hf_zebra_msg_metric = -1;
57 static int hf_zebra_nexthopnum = -1;
58 static int hf_zebra_nexthop4 = -1;
59 static int hf_zebra_nexthop6 = -1;
60 static int hf_zebra_dest4 = -1;
61 static int hf_zebra_dest6 = -1;
62 static int hf_zebra_prefixlen = -1;
63 static int hf_zebra_prefix4 = -1;
64 static int hf_zebra_prefix6 = -1;
66 static gint ett_zebra = -1;
67 static gint ett_zebra_request = -1;
68 static gint ett_message = -1;
70 #define TCP_PORT_ZEBRA 2600
72 /* Zebra message types. */
73 #define ZEBRA_INTERFACE_ADD 1
74 #define ZEBRA_INTERFACE_DELETE 2
75 #define ZEBRA_INTERFACE_ADDRESS_ADD 3
76 #define ZEBRA_INTERFACE_ADDRESS_DELETE 4
77 #define ZEBRA_INTERFACE_UP 5
78 #define ZEBRA_INTERFACE_DOWN 6
79 #define ZEBRA_IPV4_ROUTE_ADD 7
80 #define ZEBRA_IPV4_ROUTE_DELETE 8
81 #define ZEBRA_IPV6_ROUTE_ADD 9
82 #define ZEBRA_IPV6_ROUTE_DELETE 10
83 #define ZEBRA_REDISTRIBUTE_ADD 11
84 #define ZEBRA_REDISTRIBUTE_DELETE 12
85 #define ZEBRA_REDISTRIBUTE_DEFAULT_ADD 13
86 #define ZEBRA_REDISTRIBUTE_DEFAULT_DELETE 14
87 #define ZEBRA_IPV4_NEXTHOP_LOOKUP 15
88 #define ZEBRA_IPV6_NEXTHOP_LOOKUP 16
90 static const value_string messages[] = {
91 { ZEBRA_INTERFACE_ADD, "Add Interface" },
92 { ZEBRA_INTERFACE_DELETE, "Delete Interface" },
93 { ZEBRA_INTERFACE_ADDRESS_ADD, "Add Interface Address" },
94 { ZEBRA_INTERFACE_ADDRESS_DELETE, "Delete Interface Address" },
95 { ZEBRA_INTERFACE_UP, "Interface Up" },
96 { ZEBRA_INTERFACE_DOWN, "Interface Down" },
97 { ZEBRA_IPV4_ROUTE_ADD, "Add IPv4 Route" },
98 { ZEBRA_IPV4_ROUTE_DELETE, "Delete IPv4 Route" },
99 { ZEBRA_IPV6_ROUTE_ADD, "Add IPv6 Route" },
100 { ZEBRA_IPV6_ROUTE_DELETE, "Delete IPv6 Route" },
101 { ZEBRA_REDISTRIBUTE_ADD, "Add Redistribute" },
102 { ZEBRA_REDISTRIBUTE_DELETE, "Delete Redistribute" },
103 { ZEBRA_REDISTRIBUTE_DEFAULT_ADD, "Add Default Redistribute" },
104 { ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, "Delete Default Redistribute" },
105 { ZEBRA_IPV4_NEXTHOP_LOOKUP, "IPv4 Nexthop Lookup" },
106 { ZEBRA_IPV6_NEXTHOP_LOOKUP, "IPv6 Nexthop Lookup" },
110 /* Zebra route's types. */
111 #define ZEBRA_ROUTE_SYSTEM 0
112 #define ZEBRA_ROUTE_KERNEL 1
113 #define ZEBRA_ROUTE_CONNECT 2
114 #define ZEBRA_ROUTE_STATIC 3
115 #define ZEBRA_ROUTE_RIP 4
116 #define ZEBRA_ROUTE_RIPNG 5
117 #define ZEBRA_ROUTE_OSPF 6
118 #define ZEBRA_ROUTE_OSPF6 7
119 #define ZEBRA_ROUTE_BGP 8
121 static const value_string routes[] = {
122 { ZEBRA_ROUTE_SYSTEM, "System Route" },
123 { ZEBRA_ROUTE_KERNEL, "Kernel Route" },
124 { ZEBRA_ROUTE_CONNECT, "Connected Route" },
125 { ZEBRA_ROUTE_STATIC, "Static Route" },
126 { ZEBRA_ROUTE_RIP, "RIP Route" },
127 { ZEBRA_ROUTE_RIPNG, "RIPnG Route" },
128 { ZEBRA_ROUTE_OSPF, "OSPF Route" },
129 { ZEBRA_ROUTE_OSPF6, "OSPF6 Route" },
130 { ZEBRA_ROUTE_BGP, "BGP Route" },
134 /* Zebra's family types. */
135 #define ZEBRA_FAMILY_IPV4 1
136 #define ZEBRA_FAMILY_IPV6 2
138 static const value_string families[] = {
139 { ZEBRA_FAMILY_IPV4, "IPv4" },
140 { ZEBRA_FAMILY_IPV6, "IPv6" },
144 /* Zebra message flags */
145 #define ZEBRA_FLAG_INTERNAL 0x01
146 #define ZEBRA_FLAG_SELFROUTE 0x02
147 #define ZEBRA_FLAG_BLACKHOLE 0x04
149 /* Zebra API message flag. */
150 #define ZEBRA_ZAPI_MESSAGE_NEXTHOP 0x01
151 #define ZEBRA_ZAPI_MESSAGE_IFINDEX 0x02
152 #define ZEBRA_ZAPI_MESSAGE_DISTANCE 0x04
153 #define ZEBRA_ZAPI_MESSAGE_METRIC 0x08
155 #define INTERFACE_NAMSIZ 20
157 #define PSIZE(a) (((a) + 7) / (8))
160 dissect_zebra_request(proto_tree *tree, gboolean request, tvbuff_t *tvb,
161 int offset, guint16 len, guint8 command)
165 guint8 buffer6[16], prefixlen, message;
167 proto_tree *msg_tree;
169 proto_tree_add_uint(tree, hf_zebra_len, tvb, offset, 2, len);
171 proto_tree_add_uint(tree, hf_zebra_command, tvb, offset, 1,
175 case ZEBRA_INTERFACE_ADD:
176 case ZEBRA_INTERFACE_UP:
177 case ZEBRA_INTERFACE_DOWN:
179 /* Request just subscribes to messages */
181 proto_tree_add_item(tree, hf_zebra_interface,
182 tvb, offset, INTERFACE_NAMSIZ, FALSE);
183 offset += INTERFACE_NAMSIZ;
185 proto_tree_add_item(tree, hf_zebra_index, tvb,
189 proto_tree_add_item(tree, hf_zebra_intflags, tvb,
193 proto_tree_add_item(tree, hf_zebra_metric, tvb,
197 proto_tree_add_item(tree, hf_zebra_mtu, tvb,
201 proto_tree_add_item(tree, hf_zebra_bandwidth, tvb,
206 case ZEBRA_INTERFACE_DELETE:
207 proto_tree_add_item(tree, hf_zebra_interface,
208 tvb, offset, INTERFACE_NAMSIZ, FALSE);
209 offset += INTERFACE_NAMSIZ;
211 proto_tree_add_item(tree, hf_zebra_index, tvb,
215 case ZEBRA_INTERFACE_ADDRESS_ADD:
216 case ZEBRA_INTERFACE_ADDRESS_DELETE:
217 proto_tree_add_item(tree, hf_zebra_index, tvb,
221 proto_tree_add_item(tree, hf_zebra_family, tvb,
225 /* XXX - switch on the address family here, instead? */
226 if (len == 17) { /* IPv4 */
227 proto_tree_add_item(tree, hf_zebra_prefix4,
228 tvb, offset, 4, FALSE);
231 else if (len == 41) { /* IPv6 */
232 proto_tree_add_item(tree, hf_zebra_prefix6,
233 tvb, offset, 16, FALSE);
238 proto_tree_add_item(tree, hf_zebra_prefixlen, tvb,
242 if (len == 17) { /* IPv4 */
243 proto_tree_add_item(tree, hf_zebra_dest4,
244 tvb, offset, 4, FALSE);
247 else if (len == 41) { /* IPv6 */
248 proto_tree_add_item(tree, hf_zebra_dest6,
249 tvb, offset, 16, FALSE);
254 case ZEBRA_IPV4_ROUTE_ADD:
255 case ZEBRA_IPV4_ROUTE_DELETE:
256 proto_tree_add_item(tree, hf_zebra_type, tvb,
260 proto_tree_add_item(tree, hf_zebra_rtflags, tvb,
264 message = tvb_get_guint8(tvb, offset);
265 ti = proto_tree_add_uint(tree, hf_zebra_message, tvb,
267 msg_tree = proto_item_add_subtree(ti, ett_message);
268 proto_tree_add_boolean(msg_tree, hf_zebra_msg_nexthop,
269 tvb, offset, 1, message);
270 proto_tree_add_boolean(msg_tree, hf_zebra_msg_index,
271 tvb, offset, 1, message);
272 proto_tree_add_boolean(msg_tree, hf_zebra_msg_distance,
273 tvb, offset, 1, message);
274 proto_tree_add_boolean(msg_tree, hf_zebra_msg_metric,
275 tvb, offset, 1, message);
278 prefixlen = tvb_get_guint8(tvb, offset);
279 proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb,
280 offset, 1, prefixlen);
284 tvb_memcpy(tvb, (guint8 *)&prefix4, offset,
285 MIN((unsigned) PSIZE(prefixlen), sizeof prefix4));
286 proto_tree_add_ipv4(tree, hf_zebra_prefix4,
287 tvb, offset, PSIZE(prefixlen), prefix4);
288 offset += PSIZE(prefixlen);
290 if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) {
291 i = tvb_get_guint8(tvb, offset);
292 proto_tree_add_uint(tree, hf_zebra_nexthopnum,
296 if (i>len) break; /* Sanity */
299 proto_tree_add_item(tree,
300 hf_zebra_nexthop4, tvb,
305 if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) {
306 i = tvb_get_guint8(tvb, offset);
307 proto_tree_add_uint(tree, hf_zebra_indexnum,
311 if (i>len) break; /* Sanity */
314 proto_tree_add_item(tree,
320 if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) {
321 proto_tree_add_item(tree, hf_zebra_distance,
322 tvb, offset, 1, FALSE);
325 if (message & ZEBRA_ZAPI_MESSAGE_METRIC) {
326 proto_tree_add_item(tree, hf_zebra_metric,
327 tvb, offset, 4, FALSE);
331 case ZEBRA_IPV6_ROUTE_ADD:
332 case ZEBRA_IPV6_ROUTE_DELETE:
333 proto_tree_add_item(tree, hf_zebra_type, tvb,
337 proto_tree_add_item(tree, hf_zebra_rtflags, tvb,
341 message = tvb_get_guint8(tvb, offset);
342 ti = proto_tree_add_uint(tree, hf_zebra_message, tvb,
344 msg_tree = proto_item_add_subtree(ti, ett_message);
345 proto_tree_add_boolean(msg_tree, hf_zebra_msg_nexthop,
346 tvb, offset, 1, message);
347 proto_tree_add_boolean(msg_tree, hf_zebra_msg_index,
348 tvb, offset, 1, message);
349 proto_tree_add_boolean(msg_tree, hf_zebra_msg_distance,
350 tvb, offset, 1, message);
351 proto_tree_add_boolean(msg_tree, hf_zebra_msg_metric,
352 tvb, offset, 1, message);
355 prefixlen = tvb_get_guint8(tvb, offset);
356 proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb,
357 offset, 1, prefixlen);
360 memset(buffer6, '\0', sizeof buffer6);
361 tvb_memcpy(tvb, buffer6, offset,
362 MIN((unsigned) PSIZE(prefixlen), sizeof buffer6));
363 proto_tree_add_ipv6(tree, hf_zebra_prefix6,
364 tvb, offset, PSIZE(prefixlen), buffer6);
365 offset += PSIZE(prefixlen);
367 if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) {
368 i = tvb_get_guint8(tvb, offset);
369 proto_tree_add_uint(tree, hf_zebra_nexthopnum,
373 if (i>len) break; /* Sanity */
376 proto_tree_add_item(tree,
377 hf_zebra_nexthop6, tvb,
382 if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) {
383 i = tvb_get_guint8(tvb, offset);
384 proto_tree_add_uint(tree, hf_zebra_indexnum,
388 if (i>len) break; /* Sanity */
391 proto_tree_add_item(tree,
397 if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) {
398 proto_tree_add_item(tree, hf_zebra_distance,
399 tvb, offset, 1, FALSE);
402 if (message & ZEBRA_ZAPI_MESSAGE_METRIC) {
403 proto_tree_add_item(tree, hf_zebra_metric,
404 tvb, offset, 4, FALSE);
408 case ZEBRA_REDISTRIBUTE_ADD:
409 case ZEBRA_REDISTRIBUTE_DELETE:
410 proto_tree_add_item(tree, hf_zebra_type, tvb,
414 case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
415 case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
417 case ZEBRA_IPV4_NEXTHOP_LOOKUP:
418 proto_tree_add_item(tree, hf_zebra_nexthop4,
419 tvb, offset, 4, FALSE);
422 proto_tree_add_item(tree, hf_zebra_metric,
423 tvb, offset, 4, FALSE);
426 case ZEBRA_IPV6_NEXTHOP_LOOKUP:
427 /* Not yet implemeted in ZEBRA */
433 dissect_zebra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
436 proto_tree *zebra_tree;
440 if (check_col(pinfo->cinfo, COL_PROTOCOL))
441 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ZEBRA");
443 request = (pinfo->destport == pinfo->match_port);
444 left = tvb_reported_length(tvb);
447 if (check_col(pinfo->cinfo, COL_INFO)) {
448 col_set_str(pinfo->cinfo, COL_INFO,
449 request? "ZEBRA Request" : "ZEBRA Reply");
452 ti = proto_tree_add_item(tree, proto_zebra, tvb, offset, -1,
454 zebra_tree = proto_item_add_subtree(ti, ett_zebra);
455 proto_tree_add_boolean_hidden(zebra_tree, hf_zebra_request,
456 tvb, offset, 0, request);
461 proto_tree *zebra_request_tree;
465 len = tvb_get_ntohs(tvb, offset);
468 command = tvb_get_guint8(tvb, offset+2);
470 ti = proto_tree_add_uint(zebra_tree,
471 hf_zebra_command, tvb, offset, len,
473 zebra_request_tree = proto_item_add_subtree(ti,
475 dissect_zebra_request(zebra_request_tree, request, tvb,
476 offset, len, command);
485 proto_register_zebra(void)
488 static hf_register_info hf[] = {
490 { "Length", "zebra.len",
491 FT_UINT16, BASE_DEC, NULL, 0x0,
492 "Length of ZEBRA request", HFILL }},
494 { "Request", "zebra.request",
495 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
496 "TRUE if ZEBRA request", HFILL }},
498 { "Command", "zebra.command",
499 FT_UINT8, BASE_DEC, VALS(messages), 0x0,
500 "ZEBRA command", HFILL }},
501 { &hf_zebra_interface,
502 { "Interface", "zebra.interface",
503 FT_STRING, BASE_NONE, NULL, 0x0,
504 "Interface name of ZEBRA request", HFILL }},
506 { "Index", "zebra.index",
507 FT_UINT32, BASE_DEC, NULL, 0x0,
508 "Index of interface", HFILL }},
509 { &hf_zebra_indexnum,
510 { "Index Number", "zebra.indexnum",
511 FT_UINT8, BASE_DEC, NULL, 0x0,
512 "Number of indices for route", HFILL }},
513 { &hf_zebra_intflags,
514 { "Flags", "zebra.intflags",
515 FT_UINT32, BASE_DEC, NULL, 0x0,
516 "Flags of interface", HFILL }},
518 { "Flags", "zebra.rtflags",
519 FT_UINT8, BASE_DEC, NULL, 0x0,
520 "Flags of route", HFILL }},
522 { "Message", "zebra.message",
523 FT_UINT8, BASE_DEC, NULL, 0x0,
524 "Message type of route", HFILL }},
525 { &hf_zebra_msg_nexthop,
526 { "Message Nexthop", "zebra.message.nexthop",
527 FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_NEXTHOP,
528 "Message contains nexthop", HFILL }},
529 { &hf_zebra_msg_index,
530 { "Message Index", "zebra.message.index",
531 FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_IFINDEX,
532 "Message contains index", HFILL }},
533 { &hf_zebra_msg_distance,
534 { "Message Distance", "zebra.message.distance",
535 FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_DISTANCE,
536 "Message contains distance", HFILL }},
537 { &hf_zebra_msg_metric,
538 { "Message Metric", "zebra.message.metric",
539 FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_METRIC,
540 "Message contains metric", HFILL }},
542 { "Type", "zebra.type",
543 FT_UINT8, BASE_DEC, VALS(routes), 0x0,
544 "Type of route", HFILL }},
545 { &hf_zebra_distance,
546 { "Distance", "zebra.distance",
547 FT_UINT8, BASE_DEC, NULL, 0x0,
548 "Distance of route", HFILL }},
550 { "Metric", "zebra.metric",
551 FT_UINT32, BASE_DEC, NULL, 0x0,
552 "Metric of interface or route", HFILL }},
554 { "MTU", "zebra.mtu",
555 FT_UINT32, BASE_DEC, NULL, 0x0,
556 "MTU of interface", HFILL }},
557 { &hf_zebra_bandwidth,
558 { "Bandwidth", "zebra.bandwidth",
559 FT_UINT32, BASE_DEC, NULL, 0x0,
560 "Bandwidth of interface", HFILL }},
562 { "Family", "zebra.family",
563 FT_UINT32, BASE_DEC, VALS(families), 0x0,
564 "Family of IP address", HFILL }},
566 { "Destination", "zebra.dest4",
567 FT_IPv4, BASE_NONE, NULL, 0x0,
568 "Destination IPv4 field", HFILL }},
570 { "Destination", "zebra.dest6",
571 FT_IPv6, BASE_NONE, NULL, 0x0,
572 "Destination IPv6 field", HFILL }},
573 { &hf_zebra_nexthopnum,
574 { "Nexthop Number", "zebra.nexthopnum",
575 FT_UINT8, BASE_DEC, NULL, 0x0,
576 "Number of nexthops in route", HFILL }},
577 { &hf_zebra_nexthop4,
578 { "Nexthop", "zebra.nexthop4",
579 FT_IPv4, BASE_NONE, NULL, 0x0,
580 "Nethop IPv4 field of route", HFILL }},
581 { &hf_zebra_nexthop6,
582 { "Nexthop", "zebra.nexthop6",
583 FT_IPv6, BASE_NONE, NULL, 0x0,
584 "Nethop IPv6 field of route", HFILL }},
585 { &hf_zebra_prefixlen,
586 { "Prefix length", "zebra.prefixlen",
587 FT_UINT32, BASE_DEC, NULL, 0x0,
588 "Prefix length", HFILL }},
590 { "Prefix", "zebra.prefix4",
591 FT_IPv4, BASE_NONE, NULL, 0x0,
592 "Prefix IPv4", HFILL }},
594 { "Prefix", "zebra.prefix6",
595 FT_IPv6, BASE_NONE, NULL, 0x0,
596 "Prefix IPv6", HFILL }},
599 static gint *ett[] = {
605 proto_zebra = proto_register_protocol("Zebra Protocol", "ZEBRA", "zebra");
606 proto_register_field_array(proto_zebra, hf, array_length(hf));
607 proto_register_subtree_array(ett, array_length(ett));
611 proto_reg_handoff_zebra(void)
613 dissector_handle_t zebra_handle;
615 zebra_handle = create_dissector_handle(dissect_zebra, proto_zebra);
616 dissector_add("tcp.port", TCP_PORT_ZEBRA, zebra_handle);