Ethereal-dev: [ethereal-dev] zebra dissector
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Jochen Friedrich <jochen@xxxxxxxx>
Date: Fri, 4 Aug 2000 17:31:09 +0200 (CEST)
Hi there, this is a first version of a Zebra protocol dissector. It dissects the protocol internally used by zebra (see http://www.zebra.org) for the communication between the main zebra daemon and the various routing protocol deamons. Nice to have when debugging zebra itself :-) Cheers, Jochen
/* packet-zebra.c
* Routines for zebra packet disassembly
*
* Jochen Friedrich <jochen@xxxxxxxx>
*
* $Id:$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@xxxxxxxx>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <string.h>
#include <ctype.h>
#include <glib.h>
#include "packet.h"
static int proto_zebra = -1;
static int hf_zebra_len = -1;
static int hf_zebra_command = -1;
static int hf_zebra_request = -1;
static int hf_zebra_interface = -1;
static int hf_zebra_index = -1;
static int hf_zebra_type = -1;
static int hf_zebra_flags = -1;
static int hf_zebra_metric = -1;
static int hf_zebra_mtu = -1;
static int hf_zebra_family = -1;
static int hf_zebra_nexthop4 = -1;
static int hf_zebra_nexthop6 = -1;
static int hf_zebra_dest4 = -1;
static int hf_zebra_dest6 = -1;
static int hf_zebra_prefixlen = -1;
static int hf_zebra_prefix4 = -1;
static int hf_zebra_prefix6 = -1;
static gint ett_zebra = -1;
static gint ett_zebra_request = -1;
#define TCP_PORT_ZEBRA 2600
/* Zebra message types. */
#define ZEBRA_INTERFACE_ADD 1
#define ZEBRA_INTERFACE_DELETE 2
#define ZEBRA_INTERFACE_ADDRESS_ADD 3
#define ZEBRA_INTERFACE_ADDRESS_DELETE 4
#define ZEBRA_IPV4_ROUTE_ADD 5
#define ZEBRA_IPV4_ROUTE_DELETE 6
#define ZEBRA_IPV6_ROUTE_ADD 7
#define ZEBRA_IPV6_ROUTE_DELETE 8
#define ZEBRA_REDISTRIBUTE_ADD 9
#define ZEBRA_REDISTRIBUTE_DELETE 10
#define ZEBRA_REDISTRIBUTE_DEFAULT_ADD 11
#define ZEBRA_REDISTRIBUTE_DEFAULT_DELETE 12
/* Is this really correct? */
#define ZEBRA_INTERFACE_UP 11
#define ZEBRA_INTERFACE_DOWN 12
static const value_string messages[] = {
{ ZEBRA_INTERFACE_ADD, "Add Interface" },
{ ZEBRA_INTERFACE_DELETE, "Delete Interface" },
{ ZEBRA_INTERFACE_ADDRESS_ADD, "Add Interface Address" },
{ ZEBRA_INTERFACE_ADDRESS_DELETE, "Delete Interface Address" },
{ ZEBRA_IPV4_ROUTE_ADD, "Add IPv4 Route" },
{ ZEBRA_IPV4_ROUTE_DELETE, "Delete IPv4 Route" },
{ ZEBRA_IPV6_ROUTE_ADD, "Add IPv6 Route" },
{ ZEBRA_IPV6_ROUTE_DELETE, "Delete IPv6 Route" },
{ ZEBRA_REDISTRIBUTE_ADD, "Add Redistribute" },
{ ZEBRA_REDISTRIBUTE_DELETE, "Delete Redistribute" },
{ ZEBRA_REDISTRIBUTE_DEFAULT_ADD, "Add Default Redistribute" },
{ ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, "Delete Default Redistribute" },
{ 0, NULL },
};
/* Zebra route's types. */
#define ZEBRA_ROUTE_SYSTEM 0
#define ZEBRA_ROUTE_KERNEL 1
#define ZEBRA_ROUTE_CONNECT 2
#define ZEBRA_ROUTE_STATIC 3
#define ZEBRA_ROUTE_RIP 4
#define ZEBRA_ROUTE_RIPNG 5
#define ZEBRA_ROUTE_OSPF 6
#define ZEBRA_ROUTE_OSPF6 7
#define ZEBRA_ROUTE_BGP 8
static const value_string routes[] = {
{ ZEBRA_ROUTE_SYSTEM, "System Route" },
{ ZEBRA_ROUTE_KERNEL, "Kernel Route" },
{ ZEBRA_ROUTE_CONNECT, "Connected Route" },
{ ZEBRA_ROUTE_STATIC, "Static Route" },
{ ZEBRA_ROUTE_RIP, "RIP Route" },
{ ZEBRA_ROUTE_RIPNG, "RIPnG Route" },
{ ZEBRA_ROUTE_OSPF, "OSPF Route" },
{ ZEBRA_ROUTE_OSPF6, "OSPF6 Route" },
{ ZEBRA_ROUTE_BGP, "BGP Route" },
{ 0, NULL },
};
/* Zebra's family types. */
#define ZEBRA_FAMILY_IPV4 1
#define ZEBRA_FAMILY_IPV6 2
static const value_string families[] = {
{ ZEBRA_FAMILY_IPV4, "IPv4" },
{ ZEBRA_FAMILY_IPV6, "IPv6" },
{ 0, NULL },
};
/* Error codes of zebra. */
#define ZEBRA_ERR_RTEXIST 1
#define ZEBRA_ERR_RTUNREACH 2
#define ZEBRA_ERR_EPERM 3
#define ZEBRA_ERR_RTNOEXIST 4
static const value_string errors[] = {
{ ZEBRA_ERR_RTEXIST, "Route Exists" },
{ ZEBRA_ERR_RTUNREACH, "Route Unreachable" },
{ ZEBRA_ERR_EPERM, "Permission Denied" },
{ ZEBRA_ERR_RTNOEXIST, "Route Does Not Exist" },
{ 0, NULL },
};
/* Zebra message flags */
#define ZEBRA_FLAG_INTERNAL 0x01
#define ZEBRA_FLAG_SELFROUTE 0x02
#define ZEBRA_FLAG_BLACKHOLE 0x04
/* Subsequent Address Family Identifier. */
#define ZEBRA_SAFI_UNICAST 1
#define ZEBRA_SAFI_MULTICAST 2
#define ZEBRA_SAFI_UNICAST_MULTICAST 3
#define ZEBRA_SAFI_MPLS_VPN 4
static const value_string safis[] = {
{ ZEBRA_SAFI_UNICAST, "Unicast" },
{ ZEBRA_SAFI_MULTICAST, "Multicast" },
{ ZEBRA_SAFI_UNICAST_MULTICAST, "Unicast And Multicast" },
{ ZEBRA_SAFI_MPLS_VPN, "MPLS VPN" },
{ 0, NULL },
};
#define INTERFACE_NAMSIZ 20
#define PSIZE(a) (((a) + 7) / (8))
void
dissect_zebra_request(proto_tree *tree, gboolean request, tvbuff_t *tvb,
int offset, guint16 len, guint8 command)
{
guint32 flags, metric, mtu, prefix4, destination4, nexthop4;
guint16 index, i;
guint8 family, prefixlen, type, buffer6[16];
gpointer prefix6, destination6, nexthop6, prefix, ptr;
proto_tree_add_uint(tree, hf_zebra_len, NullTVB, offset, 2, len);
offset += 2;
if ((command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD) && (!request))
proto_tree_add_string(tree, hf_zebra_command, NullTVB, offset,
1, "Interface Up");
else if ((command == ZEBRA_REDISTRIBUTE_DEFAULT_DELETE) && (!request))
proto_tree_add_string(tree, hf_zebra_command, NullTVB, offset, 1, "Interface Down");
else proto_tree_add_string(tree, hf_zebra_command, NullTVB, offset, 1,
val_to_str(command, messages, "Unknown command: %d"));
offset += 1;
switch(command) {
case ZEBRA_INTERFACE_ADD:
add:
proto_tree_add_string(tree, hf_zebra_interface,
NullTVB, offset, INTERFACE_NAMSIZ,
tvb_get_ptr(tvb, offset, INTERFACE_NAMSIZ));
offset += INTERFACE_NAMSIZ;
index = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_index, NullTVB,
offset, 2, index);
offset += 2;
flags = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_flags, NullTVB,
offset, 4, flags);
offset += 4;
metric = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_metric, NullTVB,
offset, 4, metric);
offset += 4;
mtu = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_mtu, NullTVB,
offset, 4, mtu);
offset += 4;
break;
case ZEBRA_INTERFACE_DELETE:
proto_tree_add_string(tree, hf_zebra_interface,
NullTVB, offset, INTERFACE_NAMSIZ,
tvb_get_ptr(tvb, offset, INTERFACE_NAMSIZ));
offset += INTERFACE_NAMSIZ;
index = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_index, NullTVB,
offset, 2, index);
offset += 2;
break;
case ZEBRA_INTERFACE_ADDRESS_ADD:
case ZEBRA_INTERFACE_ADDRESS_DELETE:
index = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_index, NullTVB,
offset, 2, index);
offset += 2;
family = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_family, NullTVB,
offset, 1, family);
offset += 1;
if (len == 15) { /* IPv4 */
prefix4 = tvb_get_letohl(tvb, offset);
proto_tree_add_ipv4(tree, hf_zebra_prefix4,
NullTVB, offset, 4, prefix4);
offset += 4;
}
else if (len == 39) { /* IPv6 */
prefix6 = tvb_get_ptr(tvb, offset, 16);
proto_tree_add_ipv6(tree, hf_zebra_prefix6,
NullTVB, offset, 16, prefix6);
offset += 16;
}
else break;
prefixlen = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_prefixlen, NullTVB,
offset, 1, prefixlen);
offset += 1;
if (len == 15) { /* IPv4 */
destination4 = tvb_get_letohl(tvb, offset);
proto_tree_add_ipv4(tree, hf_zebra_dest4,
NullTVB, offset, 4, destination4);
offset += 4;
}
else if (len == 39) { /* IPv6 */
destination6 = tvb_get_ptr(tvb, offset, 16);
proto_tree_add_ipv6(tree, hf_zebra_dest6,
NullTVB, offset, 16, destination6);
offset += 16;
}
break;
case ZEBRA_IPV4_ROUTE_ADD:
case ZEBRA_IPV4_ROUTE_DELETE:
type = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_type, NullTVB,
offset, 1, type);
offset += 1;
flags = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_flags, NullTVB,
offset, 1, flags);
offset += 1;
nexthop4 = tvb_get_letohl(tvb, offset);
proto_tree_add_ipv4(tree, hf_zebra_nexthop4,
NullTVB, offset, 4, nexthop4);
offset += 4;
index = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_index, NullTVB,
offset, 4, index);
offset += 4;
prefixlen = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_prefixlen, NullTVB,
offset, 1, prefixlen);
offset += 1;
prefix = tvb_get_ptr(tvb, offset, PSIZE(prefixlen));
prefix4 = 0;
ptr = (gpointer) &prefix4;
for (i=0; i< PSIZE(prefixlen); i++)
*(guint8*)ptr++ = *(guint8*)prefix++;
proto_tree_add_ipv4(tree, hf_zebra_prefix4,
NullTVB, offset, 4, prefix4);
offset += PSIZE(prefixlen);
break;
case ZEBRA_IPV6_ROUTE_ADD:
case ZEBRA_IPV6_ROUTE_DELETE:
type = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_type, NullTVB,
offset, 1, type);
offset += 1;
flags = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_flags, NullTVB,
offset, 1, flags);
offset += 1;
nexthop6 = tvb_get_ptr(tvb, offset, 16);
proto_tree_add_ipv6(tree, hf_zebra_nexthop6,
NullTVB, offset, 16, nexthop6);
offset += 16;
index = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_index, NullTVB,
offset, 4, index);
offset += 4;
prefixlen = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_prefixlen, NullTVB,
offset, 1, prefixlen);
offset += 1;
prefix = tvb_get_ptr(tvb, offset, PSIZE(prefixlen));
for (i=0; i < 16; i++) buffer6[i] = 0;
ptr = (gpointer) buffer6;
for (i=0; i< PSIZE(prefixlen); i++)
*(guint8*)ptr++ = *(guint8*)prefix++;
proto_tree_add_ipv6(tree, hf_zebra_prefix6,
NullTVB, offset, 16, prefix6);
offset += PSIZE(prefixlen);
break;
case ZEBRA_REDISTRIBUTE_ADD:
case ZEBRA_REDISTRIBUTE_DELETE:
type = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_type, NullTVB,
offset, 1, type);
offset += 1;
case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
if (!request) goto add; /* IF Up / IF Down */
break;
}
}
void
dissect_zebra(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
{
proto_item *ti;
proto_tree *zebra_tree;
tvbuff_t *tvb;
gboolean request;
int left;
if (check_col(fd, COL_PROTOCOL))
col_add_str(fd, COL_PROTOCOL, "ZEBRA");
tvb = tvb_create_from_top(0);
request = (pi.destport == TCP_PORT_ZEBRA);
left = tvb_reported_length(tvb) - offset;
if (check_col(fd, COL_INFO)) {
col_add_str(fd, COL_INFO,
request? "ZEBRA Request" : "ZEBRA Reply");
}
if (tree) {
ti = proto_tree_add_boolean_hidden(tree, hf_zebra_request,
NullTVB, offset, END_OF_FRAME, request);
ti = proto_tree_add_item(tree, proto_zebra, NullTVB, offset,
END_OF_FRAME, FALSE);
zebra_tree = proto_item_add_subtree(ti, ett_zebra);
for (;;) {
guint8 command;
guint16 len;
proto_tree *zebra_request_tree;
if (left < 3) break;
len = tvb_get_ntohs(tvb, offset);
if (len < 3) break;
command = tvb_get_guint8(tvb, offset+2);
if ((command == ZEBRA_REDISTRIBUTE_DEFAULT_ADD)
&& (!request))
ti = proto_tree_add_string(zebra_tree,
hf_zebra_command, NullTVB, offset, len,
"Interface Up");
else if ((command == ZEBRA_REDISTRIBUTE_DEFAULT_DELETE)
&& (!request))
ti = proto_tree_add_string(zebra_tree,
hf_zebra_command, NullTVB, offset, len,
"Interface Down");
else ti = proto_tree_add_string(zebra_tree,
hf_zebra_command, NullTVB, offset, len,
val_to_str(command,
messages, "Unknown command: %d"));
zebra_request_tree = proto_item_add_subtree(ti,
ett_zebra_request);
dissect_zebra_request(zebra_request_tree, request, tvb,
offset, len, command);
offset += len;
left -= len;
}
}
}
void
proto_register_zebra(void)
{
static hf_register_info hf[] = {
{ &hf_zebra_len,
{ "Length", "zebra.len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of ZEBRA request" }},
{ &hf_zebra_request,
{ "Request", "zebra.request",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"TRUE if ZEBRA request" }},
{ &hf_zebra_command,
{ "Command", "zebra.command",
FT_STRING, BASE_NONE, NULL, 0x0,
"ZEBRA command" }},
{ &hf_zebra_interface,
{ "Interface", "zebra.interface",
FT_STRING, BASE_NONE, NULL, 0x0,
"Interface name of ZEBRA request" }},
{ &hf_zebra_index,
{ "Index", "zebra.index",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Index of interface" }},
{ &hf_zebra_flags,
{ "Flags", "zebra.flags",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Flags of interface" }},
{ &hf_zebra_type,
{ "Type", "zebra.type",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Type of route" }},
{ &hf_zebra_metric,
{ "Metric", "zebra.metric",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Metric of interface" }},
{ &hf_zebra_mtu,
{ "MTU", "zebra.mtu",
FT_UINT32, BASE_DEC, NULL, 0x0,
"MTU of interface" }},
{ &hf_zebra_family,
{ "Family", "zebra.family",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Family of IP address" }},
{ &hf_zebra_dest4,
{ "Destination", "zebra.dest4",
FT_IPv4, BASE_NONE, NULL, 0x0,
"Destination IPv4 field" }},
{ &hf_zebra_dest6,
{ "Destination", "zebra.dest6",
FT_IPv6, BASE_NONE, NULL, 0x0,
"Destination IPv6 field" }},
{ &hf_zebra_nexthop4,
{ "Nexthop", "zebra.nexthop4",
FT_IPv4, BASE_NONE, NULL, 0x0,
"Nethop IPv4 field of route" }},
{ &hf_zebra_nexthop6,
{ "Nexthop", "zebra.nexthop6",
FT_IPv6, BASE_NONE, NULL, 0x0,
"Nethop IPv6 field of route" }},
{ &hf_zebra_prefixlen,
{ "Prefix length", "zebra.prefixlen",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Prefix length" }},
{ &hf_zebra_prefix4,
{ "Prefix", "zebra.prefix4",
FT_IPv4, BASE_NONE, NULL, 0x0,
"Prefix IPv4" }},
{ &hf_zebra_prefix6,
{ "Prefix", "zebra.prefix6",
FT_IPv6, BASE_NONE, NULL, 0x0,
"Prefix IPv6" }},
};
static gint *ett[] = {
&ett_zebra,
&ett_zebra_request,
};
proto_zebra = proto_register_protocol("Zebra Protocol", "zebra");
proto_register_field_array(proto_zebra, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_zebra(void)
{
dissector_add("tcp.port", TCP_PORT_ZEBRA, dissect_zebra);
}
- Prev by Date: RE: [ethereal-dev] 0.8.11 on Win32?
- Next by Date: Re: [ethereal-dev] zebra dissector
- Previous by thread: [ethereal-dev] IP checksum
- Next by thread: Re: [ethereal-dev] zebra dissector
- Index(es):





