forked from osmocom/wireshark
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:
parent
25c7e0d9df
commit
ea6f5a3c7e
|
@ -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[] = {
|
||||
|
|
Loading…
Reference in New Issue