Zebra dissector highlights wrong byte for version and is missing some fields

Bug: 10809
Change-Id: I916d3ee0644570b689b35575e7277fc7d5ee3396
Reviewed-on: https://code.wireshark.org/review/6081
Petri-Dish: Hadriel Kaplan <hadrielk@yahoo.com>
Reviewed-by: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Hadriel Kaplan <hadrielk@yahoo.com>
Tested-by: Hadriel Kaplan <hadrielk@yahoo.com>
This commit is contained in:
Hadriel Kaplan 2014-12-27 13:29:06 -05:00 committed by Hadriel Kaplan
parent 25c7e0d9df
commit ea6f5a3c7e
1 changed files with 145 additions and 18 deletions

View File

@ -22,6 +22,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* The Zebra Protocol is the protocol used between the Zebra routing daemon and other
* protocol daemons (ones for BGP, OSPF, etc.) within the Zebra and Quagga open-source
* routing suites. Zebra itself (https://www.gnu.org/software/zebra) is discontinued,
* and its successor is Quagga (http://www.nongnu.org/quagga).
*
* Both Zebra and Quagga use a "Zebra Protocol", but starting with Quagga v0.99 the
* Zebra Protocol has changed, with a different header format and more commands/types.
* Quagga 0.99.0 was version 1, and 0.99.20 or so changed it to version 2.
*
* See http://www.nongnu.org/quagga/docs/docs-info.html#Zebra-Protocol for some details.
*/
#include "config.h"
@ -38,7 +51,8 @@ static int hf_zebra_request = -1;
static int hf_zebra_interface = -1;
static int hf_zebra_index = -1;
static int hf_zebra_indexnum = -1;
static int hf_zebra_type = -1;
static int hf_zebra_type_v0 = -1;
static int hf_zebra_type_v1 = -1;
static int hf_zebra_intflags = -1;
static int hf_zebra_rtflags = -1;
static int hf_zebra_distance = -1;
@ -49,6 +63,7 @@ static int hf_zebra_bandwidth = -1;
static int hf_zebra_family = -1;
static int hf_zebra_flags = -1;
static int hf_zebra_message = -1;
static int hf_zebra_route_safi = -1;
static int hf_zebra_msg_nexthop = -1;
static int hf_zebra_msg_index = -1;
static int hf_zebra_msg_distance = -1;
@ -62,10 +77,12 @@ static int hf_zebra_prefixlen = -1;
static int hf_zebra_prefix4 = -1;
static int hf_zebra_prefix6 = -1;
static int hf_zebra_version = -1;
static int hf_zebra_marker = -1;
static int hf_zebra_intstatus = -1;
static int hf_zebra_routeridaddress = -1;
static int hf_zebra_routeridmask = -1;
static int hf_zebra_mac = -1;
static int hf_zebra_redist_default = -1;
static gint ett_zebra = -1;
static gint ett_zebra_request = -1;
@ -96,6 +113,7 @@ static gint ett_message = -1;
#define ZEBRA_ROUTER_ID_ADD 20
#define ZEBRA_ROUTER_ID_DELETE 21
#define ZEBRA_ROUTER_ID_UPDATE 22
#define ZEBRA_HELLO 23
static const value_string messages[] = {
@ -121,6 +139,7 @@ static const value_string messages[] = {
{ ZEBRA_ROUTER_ID_ADD, "Router ID Add" },
{ ZEBRA_ROUTER_ID_DELETE, "Router ID Delete" },
{ ZEBRA_ROUTER_ID_UPDATE, "Router ID Update" },
{ ZEBRA_HELLO, "Hello" },
{ 0, NULL },
};
@ -135,7 +154,7 @@ static const value_string messages[] = {
#define ZEBRA_ROUTE_OSPF6 7
#define ZEBRA_ROUTE_BGP 8
static const value_string routes[] = {
static const value_string routes_v0[] = {
{ ZEBRA_ROUTE_SYSTEM, "System Route" },
{ ZEBRA_ROUTE_KERNEL, "Kernel Route" },
{ ZEBRA_ROUTE_CONNECT, "Connected Route" },
@ -148,6 +167,33 @@ static const value_string routes[] = {
{ 0, NULL },
};
/*
* In Quagga, ISIS is type 8 and BGP is type 9, but Zebra didn't have ISIS...
* so for Zebra BGP is type 8. So we dup the value_string table for quagga.
*/
#define QUAGGA_ROUTE_ISIS 8
#define QUAGGA_ROUTE_BGP 9
#define QUAGGA_ROUTE_HSLS 10
#define QUAGGA_ROUTE_OLSR 11
#define QUAGGA_ROUTE_BABEL 12
static const value_string routes_v1[] = {
{ 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" },
{ QUAGGA_ROUTE_ISIS, "ISIS Route" },
{ QUAGGA_ROUTE_BGP, "BGP Route" },
{ QUAGGA_ROUTE_HSLS, "HSLS Route" },
{ QUAGGA_ROUTE_OLSR, "OLSR Route" },
{ QUAGGA_ROUTE_BABEL, "BABEL Route" },
{ 0, NULL },
};
/* Zebra's family types. */
#define ZEBRA_FAMILY_IPV4 2
#define ZEBRA_FAMILY_IPV6 10
@ -179,6 +225,20 @@ static const value_string families[] = {
#define ZEBRA_NEXTHOP_TYPE_IPV6_IFINDEX 0x07
#define ZEBRA_NEXTHOP_TYPE_IPV6_IFNAME 0x08
/* Subsequent Address Family Identifier. */
#define ZEBRA_SAFI_UNICAST 1
#define ZEBRA_SAFI_MULTICAST 2
#define ZEBRA_SAFI_RESERVED_3 3
#define ZEBRA_SAFI_MPLS_VPN 4
static const value_string safi[] = {
{ ZEBRA_SAFI_UNICAST, "Unicast" },
{ ZEBRA_SAFI_MULTICAST, "Multicast" },
{ ZEBRA_SAFI_RESERVED_3 , "Reserved" },
{ ZEBRA_SAFI_MPLS_VPN, "MPLS VPN" },
{ 0, NULL },
};
#define INTERFACE_NAMSIZ 20
@ -272,13 +332,18 @@ zebra_route_message(proto_tree *tree, tvbuff_t *tvb, int offset)
static int
zebra_route(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 len,
guint8 family)
guint8 family, guint8 version)
{
guint32 prefix4;
guint8 message, prefixlen, buffer6[16];
proto_tree_add_item(tree, hf_zebra_type, tvb,
offset, 1, ENC_BIG_ENDIAN);
if (version == 0) {
proto_tree_add_item(tree, hf_zebra_type_v0, tvb,
offset, 1, ENC_BIG_ENDIAN);
} else {
proto_tree_add_item(tree, hf_zebra_type_v1, tvb,
offset, 1, ENC_BIG_ENDIAN);
}
offset += 1;
proto_tree_add_item(tree, hf_zebra_rtflags, tvb,
@ -288,6 +353,13 @@ zebra_route(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 len,
message = tvb_get_guint8(tvb, offset);
offset = zebra_route_message(tree, tvb, offset);
if (version > 1) {
/* version 2 added safi */
proto_tree_add_item(tree, hf_zebra_route_safi, tvb,
offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
prefixlen = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb,
offset, 1, prefixlen);
@ -469,9 +541,11 @@ dissect_zebra_request(proto_tree *tree, gboolean request, tvbuff_t *tvb,
proto_tree_add_uint(tree, hf_zebra_len, tvb, offset, 2, len);
offset += 2;
if (version != 0) {
proto_tree_add_item(tree, hf_zebra_marker, tvb, offset, 1, ENC_NA);
offset += 1;
proto_tree_add_uint(tree, hf_zebra_version, tvb, offset, 1,
version);
offset += 2;
offset += 1;
proto_tree_add_uint(tree, hf_zebra_command, tvb, offset, 2,
command);
offset += 2;
@ -499,17 +573,22 @@ dissect_zebra_request(proto_tree *tree, gboolean request, tvbuff_t *tvb,
case ZEBRA_IPV4_ROUTE_ADD:
case ZEBRA_IPV4_ROUTE_DELETE:
offset = zebra_route(tree, tvb, offset, len,
ZEBRA_FAMILY_IPV4);
ZEBRA_FAMILY_IPV4, version);
break;
case ZEBRA_IPV6_ROUTE_ADD:
case ZEBRA_IPV6_ROUTE_DELETE:
offset = zebra_route(tree, tvb, offset, len,
ZEBRA_FAMILY_IPV6);
ZEBRA_FAMILY_IPV6, version);
break;
case ZEBRA_REDISTRIBUTE_ADD:
case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
proto_tree_add_item(tree, hf_zebra_type, tvb,
offset, 1, ENC_BIG_ENDIAN);
if (version == 0) {
proto_tree_add_item(tree, hf_zebra_type_v0, tvb,
offset, 1, ENC_BIG_ENDIAN);
} else {
proto_tree_add_item(tree, hf_zebra_type_v1, tvb,
offset, 1, ENC_BIG_ENDIAN);
}
offset = 1;
break;
case ZEBRA_IPV4_IMPORT_LOOKUP:
@ -525,14 +604,44 @@ dissect_zebra_request(proto_tree *tree, gboolean request, tvbuff_t *tvb,
case ZEBRA_ROUTER_ID_UPDATE:
offset = zerba_router_update(tree, tvb, offset);
break;
case ZEBRA_ROUTER_ID_ADD:
case ZEBRA_ROUTER_ID_DELETE:
case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
case ZEBRA_REDISTRIBUTE_DELETE:
/* nothing to do */
break;
case ZEBRA_REDISTRIBUTE_DELETE:
/* in version 1+, there's a route type field */
if (version > 0) {
proto_tree_add_item(tree, hf_zebra_type_v1, tvb,
offset, 1, ENC_BIG_ENDIAN);
}
break;
case ZEBRA_HELLO:
proto_tree_add_item(tree, hf_zebra_redist_default, tvb,
offset, 1, ENC_BIG_ENDIAN);
break;
}
return offset;
}
/*
Zebra Protocol header version 0:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+---------------+
| Length (2) | Command (1) |
+-------------------------------+---------------+
Zebra Protocol header version 1:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-------------------------------+---------------+-------------+
| Length (2) | Marker (1) | Version (1) |
+-------------------------------+---------------+-------------+
| Command (2) |
+-------------------------------+
The Marker is 0xFF to distinguish it from a version 0 header.
*/
static void
dissect_zebra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
@ -548,7 +657,7 @@ dissect_zebra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset = 0;
col_set_str(pinfo->cinfo, COL_INFO,
request? "ZEBRA Request" : "ZEBRA Reply");
request? "Zebra Request" : "Zebra Reply");
if (tree) {
ti = proto_tree_add_item(tree, proto_zebra, tvb, offset, -1,
@ -577,6 +686,8 @@ dissect_zebra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
version = tvb_get_guint8(tvb, offset+3);
command = tvb_get_ntohs(tvb, offset+4);
}
col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
val_to_str(command, messages, "Command Type 0x%02d"));
ti = proto_tree_add_uint(zebra_tree,
hf_zebra_command, tvb,
offset, len, command);
@ -598,23 +709,27 @@ proto_register_zebra(void)
{ &hf_zebra_len,
{ "Length", "zebra.len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of ZEBRA request", HFILL }},
"Length of Zebra request", HFILL }},
{ &hf_zebra_version,
{ "Version", "zebra.version",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Zerbra srv version", HFILL }},
{ &hf_zebra_marker,
{ "Marker", "zebra.marker",
FT_UINT8, BASE_HEX, NULL, 0x0,
"Zerbra srv marker", HFILL }},
{ &hf_zebra_request,
{ "Request", "zebra.request",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"TRUE if ZEBRA request", HFILL }},
"TRUE if Zebra request", HFILL }},
{ &hf_zebra_command,
{ "Command", "zebra.command",
FT_UINT8, BASE_DEC, VALS(messages), 0x0,
"ZEBRA command", HFILL }},
"Zebra command", HFILL }},
{ &hf_zebra_interface,
{ "Interface", "zebra.interface",
FT_STRING, BASE_NONE, NULL, 0x0,
"Interface name of ZEBRA request", HFILL }},
"Interface name of Zebra request", HFILL }},
{ &hf_zebra_index,
{ "Index", "zebra.index",
FT_UINT32, BASE_DEC, NULL, 0x0,
@ -639,6 +754,10 @@ proto_register_zebra(void)
{ "Message", "zebra.message",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Message type of route", HFILL }},
{ &hf_zebra_route_safi,
{ "SAFI", "zebra.safi",
FT_UINT16, BASE_DEC, VALS(safi), 0x0,
"Subsequent Address Family Identifier", HFILL }},
{ &hf_zebra_msg_nexthop,
{ "Message Nexthop", "zebra.message.nexthop",
FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_NEXTHOP,
@ -655,9 +774,13 @@ proto_register_zebra(void)
{ "Message Metric", "zebra.message.metric",
FT_BOOLEAN, 8, NULL, ZEBRA_ZAPI_MESSAGE_METRIC,
"Message contains metric", HFILL }},
{ &hf_zebra_type,
{ &hf_zebra_type_v0,
{ "Type", "zebra.type",
FT_UINT8, BASE_DEC, VALS(routes), 0x0,
FT_UINT8, BASE_DEC, VALS(routes_v0), 0x0,
"Type of route", HFILL }},
{ &hf_zebra_type_v1,
{ "Type", "zebra.type",
FT_UINT8, BASE_DEC, VALS(routes_v1), 0x0,
"Type of route", HFILL }},
{ &hf_zebra_distance,
{ "Distance", "zebra.distance",
@ -731,6 +854,10 @@ proto_register_zebra(void)
{ "MAC address", "zebra.macaddress",
FT_ETHER, BASE_NONE, NULL, 0x0,
"MAC address of interface", HFILL }},
{ &hf_zebra_redist_default,
{ "Redistribute default", "zebra.redist_default",
FT_BOOLEAN, BASE_NONE, NULL, 0x0,
"TRUE if redistribute default", HFILL }}
};
static gint *ett[] = {