141c99275SPeter Avalos /*
2ea7b4bf5SPeter Avalos * Copyright (c) 1998-2006 The TCPDUMP project
341c99275SPeter Avalos *
441c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
541c99275SPeter Avalos * modification, are permitted provided that: (1) source code
641c99275SPeter Avalos * distributions retain the above copyright notice and this paragraph
741c99275SPeter Avalos * in its entirety, and (2) distributions including binary code include
841c99275SPeter Avalos * the above copyright notice and this paragraph in its entirety in
941c99275SPeter Avalos * the documentation or other materials provided with the distribution.
1041c99275SPeter Avalos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
1141c99275SPeter Avalos * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
1241c99275SPeter Avalos * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1341c99275SPeter Avalos * FOR A PARTICULAR PURPOSE.
1441c99275SPeter Avalos *
1541c99275SPeter Avalos * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
16ea7b4bf5SPeter Avalos * OAM as per 802.3ah
1741c99275SPeter Avalos *
18411677aeSAaron LI * Original code by Hannes Gredler (hannes@gredler.at)
1941c99275SPeter Avalos */
2041c99275SPeter Avalos
21411677aeSAaron LI /* \summary: IEEE "slow protocols" (802.3ad/802.3ah) printer */
2241c99275SPeter Avalos
2341c99275SPeter Avalos #ifdef HAVE_CONFIG_H
24*ed775ee7SAntonio Huete Jimenez #include <config.h>
2541c99275SPeter Avalos #endif
2641c99275SPeter Avalos
27*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
2841c99275SPeter Avalos
29*ed775ee7SAntonio Huete Jimenez #define ND_LONGJMP_FROM_TCHECK
30411677aeSAaron LI #include "netdissect.h"
3141c99275SPeter Avalos #include "extract.h"
3241c99275SPeter Avalos #include "addrtoname.h"
33ea7b4bf5SPeter Avalos #include "oui.h"
3441c99275SPeter Avalos
35*ed775ee7SAntonio Huete Jimenez
3641c99275SPeter Avalos #define SLOW_PROTO_LACP 1
3741c99275SPeter Avalos #define SLOW_PROTO_MARKER 2
38ea7b4bf5SPeter Avalos #define SLOW_PROTO_OAM 3
3941c99275SPeter Avalos
4041c99275SPeter Avalos #define LACP_VERSION 1
4141c99275SPeter Avalos #define MARKER_VERSION 1
4241c99275SPeter Avalos
4341c99275SPeter Avalos static const struct tok slow_proto_values[] = {
4441c99275SPeter Avalos { SLOW_PROTO_LACP, "LACP" },
4541c99275SPeter Avalos { SLOW_PROTO_MARKER, "MARKER" },
46ea7b4bf5SPeter Avalos { SLOW_PROTO_OAM, "OAM" },
47ea7b4bf5SPeter Avalos { 0, NULL}
48ea7b4bf5SPeter Avalos };
49ea7b4bf5SPeter Avalos
50ea7b4bf5SPeter Avalos static const struct tok slow_oam_flag_values[] = {
51ea7b4bf5SPeter Avalos { 0x0001, "Link Fault" },
52ea7b4bf5SPeter Avalos { 0x0002, "Dying Gasp" },
53ea7b4bf5SPeter Avalos { 0x0004, "Critical Event" },
54ea7b4bf5SPeter Avalos { 0x0008, "Local Evaluating" },
55ea7b4bf5SPeter Avalos { 0x0010, "Local Stable" },
56ea7b4bf5SPeter Avalos { 0x0020, "Remote Evaluating" },
57ea7b4bf5SPeter Avalos { 0x0040, "Remote Stable" },
58ea7b4bf5SPeter Avalos { 0, NULL}
59ea7b4bf5SPeter Avalos };
60ea7b4bf5SPeter Avalos
61ea7b4bf5SPeter Avalos #define SLOW_OAM_CODE_INFO 0x00
62ea7b4bf5SPeter Avalos #define SLOW_OAM_CODE_EVENT_NOTIF 0x01
63ea7b4bf5SPeter Avalos #define SLOW_OAM_CODE_VAR_REQUEST 0x02
64ea7b4bf5SPeter Avalos #define SLOW_OAM_CODE_VAR_RESPONSE 0x03
65ea7b4bf5SPeter Avalos #define SLOW_OAM_CODE_LOOPBACK_CTRL 0x04
66ea7b4bf5SPeter Avalos #define SLOW_OAM_CODE_PRIVATE 0xfe
67ea7b4bf5SPeter Avalos
68ea7b4bf5SPeter Avalos static const struct tok slow_oam_code_values[] = {
69ea7b4bf5SPeter Avalos { SLOW_OAM_CODE_INFO, "Information" },
70ea7b4bf5SPeter Avalos { SLOW_OAM_CODE_EVENT_NOTIF, "Event Notification" },
71ea7b4bf5SPeter Avalos { SLOW_OAM_CODE_VAR_REQUEST, "Variable Request" },
72ea7b4bf5SPeter Avalos { SLOW_OAM_CODE_VAR_RESPONSE, "Variable Response" },
73ea7b4bf5SPeter Avalos { SLOW_OAM_CODE_LOOPBACK_CTRL, "Loopback Control" },
74ea7b4bf5SPeter Avalos { SLOW_OAM_CODE_PRIVATE, "Vendor Private" },
75ea7b4bf5SPeter Avalos { 0, NULL}
76ea7b4bf5SPeter Avalos };
77ea7b4bf5SPeter Avalos
78ea7b4bf5SPeter Avalos struct slow_oam_info_t {
79*ed775ee7SAntonio Huete Jimenez nd_uint8_t info_type;
80*ed775ee7SAntonio Huete Jimenez nd_uint8_t info_length;
81*ed775ee7SAntonio Huete Jimenez nd_uint8_t oam_version;
82*ed775ee7SAntonio Huete Jimenez nd_uint16_t revision;
83*ed775ee7SAntonio Huete Jimenez nd_uint8_t state;
84*ed775ee7SAntonio Huete Jimenez nd_uint8_t oam_config;
85*ed775ee7SAntonio Huete Jimenez nd_uint16_t oam_pdu_config;
86*ed775ee7SAntonio Huete Jimenez nd_uint24_t oui;
87*ed775ee7SAntonio Huete Jimenez nd_uint32_t vendor_private;
88ea7b4bf5SPeter Avalos };
89ea7b4bf5SPeter Avalos
90ea7b4bf5SPeter Avalos #define SLOW_OAM_INFO_TYPE_END_OF_TLV 0x00
91ea7b4bf5SPeter Avalos #define SLOW_OAM_INFO_TYPE_LOCAL 0x01
92ea7b4bf5SPeter Avalos #define SLOW_OAM_INFO_TYPE_REMOTE 0x02
93ea7b4bf5SPeter Avalos #define SLOW_OAM_INFO_TYPE_ORG_SPECIFIC 0xfe
94ea7b4bf5SPeter Avalos
95ea7b4bf5SPeter Avalos static const struct tok slow_oam_info_type_values[] = {
96ea7b4bf5SPeter Avalos { SLOW_OAM_INFO_TYPE_END_OF_TLV, "End of TLV marker" },
97ea7b4bf5SPeter Avalos { SLOW_OAM_INFO_TYPE_LOCAL, "Local" },
98ea7b4bf5SPeter Avalos { SLOW_OAM_INFO_TYPE_REMOTE, "Remote" },
99ea7b4bf5SPeter Avalos { SLOW_OAM_INFO_TYPE_ORG_SPECIFIC, "Organization specific" },
100ea7b4bf5SPeter Avalos { 0, NULL}
101ea7b4bf5SPeter Avalos };
102ea7b4bf5SPeter Avalos
103ea7b4bf5SPeter Avalos #define OAM_INFO_TYPE_PARSER_MASK 0x3
104ea7b4bf5SPeter Avalos static const struct tok slow_oam_info_type_state_parser_values[] = {
105ea7b4bf5SPeter Avalos { 0x00, "forwarding" },
106ea7b4bf5SPeter Avalos { 0x01, "looping back" },
107ea7b4bf5SPeter Avalos { 0x02, "discarding" },
108ea7b4bf5SPeter Avalos { 0x03, "reserved" },
109ea7b4bf5SPeter Avalos { 0, NULL}
110ea7b4bf5SPeter Avalos };
111ea7b4bf5SPeter Avalos
112ea7b4bf5SPeter Avalos #define OAM_INFO_TYPE_MUX_MASK 0x4
113ea7b4bf5SPeter Avalos static const struct tok slow_oam_info_type_state_mux_values[] = {
114ea7b4bf5SPeter Avalos { 0x00, "forwarding" },
115ea7b4bf5SPeter Avalos { 0x04, "discarding" },
116ea7b4bf5SPeter Avalos { 0, NULL}
117ea7b4bf5SPeter Avalos };
118ea7b4bf5SPeter Avalos
119ea7b4bf5SPeter Avalos static const struct tok slow_oam_info_type_oam_config_values[] = {
120ea7b4bf5SPeter Avalos { 0x01, "Active" },
121ea7b4bf5SPeter Avalos { 0x02, "Unidirectional" },
122ea7b4bf5SPeter Avalos { 0x04, "Remote-Loopback" },
123ea7b4bf5SPeter Avalos { 0x08, "Link-Events" },
124ea7b4bf5SPeter Avalos { 0x10, "Variable-Retrieval" },
125ea7b4bf5SPeter Avalos { 0, NULL}
126ea7b4bf5SPeter Avalos };
127ea7b4bf5SPeter Avalos
128ea7b4bf5SPeter Avalos /* 11 Bits */
129ea7b4bf5SPeter Avalos #define OAM_INFO_TYPE_PDU_SIZE_MASK 0x7ff
130ea7b4bf5SPeter Avalos
131ea7b4bf5SPeter Avalos #define SLOW_OAM_LINK_EVENT_END_OF_TLV 0x00
132ea7b4bf5SPeter Avalos #define SLOW_OAM_LINK_EVENT_ERR_SYM_PER 0x01
133ea7b4bf5SPeter Avalos #define SLOW_OAM_LINK_EVENT_ERR_FRM 0x02
134ea7b4bf5SPeter Avalos #define SLOW_OAM_LINK_EVENT_ERR_FRM_PER 0x03
135ea7b4bf5SPeter Avalos #define SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM 0x04
136ea7b4bf5SPeter Avalos #define SLOW_OAM_LINK_EVENT_ORG_SPECIFIC 0xfe
137ea7b4bf5SPeter Avalos
138ea7b4bf5SPeter Avalos static const struct tok slow_oam_link_event_values[] = {
139ea7b4bf5SPeter Avalos { SLOW_OAM_LINK_EVENT_END_OF_TLV, "End of TLV marker" },
140ea7b4bf5SPeter Avalos { SLOW_OAM_LINK_EVENT_ERR_SYM_PER, "Errored Symbol Period Event" },
141ea7b4bf5SPeter Avalos { SLOW_OAM_LINK_EVENT_ERR_FRM, "Errored Frame Event" },
142ea7b4bf5SPeter Avalos { SLOW_OAM_LINK_EVENT_ERR_FRM_PER, "Errored Frame Period Event" },
143ea7b4bf5SPeter Avalos { SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM, "Errored Frame Seconds Summary Event" },
144ea7b4bf5SPeter Avalos { SLOW_OAM_LINK_EVENT_ORG_SPECIFIC, "Organization specific" },
145ea7b4bf5SPeter Avalos { 0, NULL}
146ea7b4bf5SPeter Avalos };
147ea7b4bf5SPeter Avalos
148ea7b4bf5SPeter Avalos struct slow_oam_link_event_t {
149*ed775ee7SAntonio Huete Jimenez nd_uint8_t event_type;
150*ed775ee7SAntonio Huete Jimenez nd_uint8_t event_length;
151*ed775ee7SAntonio Huete Jimenez nd_uint16_t time_stamp;
152*ed775ee7SAntonio Huete Jimenez nd_uint64_t window;
153*ed775ee7SAntonio Huete Jimenez nd_uint64_t threshold;
154*ed775ee7SAntonio Huete Jimenez nd_uint64_t errors;
155*ed775ee7SAntonio Huete Jimenez nd_uint64_t errors_running_total;
156*ed775ee7SAntonio Huete Jimenez nd_uint32_t event_running_total;
157ea7b4bf5SPeter Avalos };
158ea7b4bf5SPeter Avalos
159ea7b4bf5SPeter Avalos struct slow_oam_variablerequest_t {
160*ed775ee7SAntonio Huete Jimenez nd_uint8_t branch;
161*ed775ee7SAntonio Huete Jimenez nd_uint16_t leaf;
162ea7b4bf5SPeter Avalos };
163ea7b4bf5SPeter Avalos
164ea7b4bf5SPeter Avalos struct slow_oam_variableresponse_t {
165*ed775ee7SAntonio Huete Jimenez nd_uint8_t branch;
166*ed775ee7SAntonio Huete Jimenez nd_uint16_t leaf;
167*ed775ee7SAntonio Huete Jimenez nd_uint8_t length;
168ea7b4bf5SPeter Avalos };
169ea7b4bf5SPeter Avalos
170ea7b4bf5SPeter Avalos struct slow_oam_loopbackctrl_t {
171*ed775ee7SAntonio Huete Jimenez nd_uint8_t command;
172ea7b4bf5SPeter Avalos };
173ea7b4bf5SPeter Avalos
174ea7b4bf5SPeter Avalos static const struct tok slow_oam_loopbackctrl_cmd_values[] = {
175ea7b4bf5SPeter Avalos { 0x01, "Enable OAM Remote Loopback" },
176ea7b4bf5SPeter Avalos { 0x02, "Disable OAM Remote Loopback" },
17741c99275SPeter Avalos { 0, NULL}
17841c99275SPeter Avalos };
17941c99275SPeter Avalos
18041c99275SPeter Avalos struct tlv_header_t {
181*ed775ee7SAntonio Huete Jimenez nd_uint8_t type;
182*ed775ee7SAntonio Huete Jimenez nd_uint8_t length;
18341c99275SPeter Avalos };
18441c99275SPeter Avalos
185411677aeSAaron LI #define LACP_MARKER_TLV_TERMINATOR 0x00 /* same code for LACP and Marker */
186411677aeSAaron LI
18741c99275SPeter Avalos #define LACP_TLV_ACTOR_INFO 0x01
18841c99275SPeter Avalos #define LACP_TLV_PARTNER_INFO 0x02
18941c99275SPeter Avalos #define LACP_TLV_COLLECTOR_INFO 0x03
19041c99275SPeter Avalos
19141c99275SPeter Avalos #define MARKER_TLV_MARKER_INFO 0x01
19241c99275SPeter Avalos
19341c99275SPeter Avalos static const struct tok slow_tlv_values[] = {
194411677aeSAaron LI { (SLOW_PROTO_LACP << 8) + LACP_MARKER_TLV_TERMINATOR, "Terminator"},
19541c99275SPeter Avalos { (SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO, "Actor Information"},
19641c99275SPeter Avalos { (SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO, "Partner Information"},
19741c99275SPeter Avalos { (SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO, "Collector Information"},
19841c99275SPeter Avalos
199411677aeSAaron LI { (SLOW_PROTO_MARKER << 8) + LACP_MARKER_TLV_TERMINATOR, "Terminator"},
20041c99275SPeter Avalos { (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO, "Marker Information"},
20141c99275SPeter Avalos { 0, NULL}
20241c99275SPeter Avalos };
20341c99275SPeter Avalos
20441c99275SPeter Avalos struct lacp_tlv_actor_partner_info_t {
205*ed775ee7SAntonio Huete Jimenez nd_uint16_t sys_pri;
206*ed775ee7SAntonio Huete Jimenez nd_mac_addr sys;
207*ed775ee7SAntonio Huete Jimenez nd_uint16_t key;
208*ed775ee7SAntonio Huete Jimenez nd_uint16_t port_pri;
209*ed775ee7SAntonio Huete Jimenez nd_uint16_t port;
210*ed775ee7SAntonio Huete Jimenez nd_uint8_t state;
211*ed775ee7SAntonio Huete Jimenez nd_byte pad[3];
21241c99275SPeter Avalos };
21341c99275SPeter Avalos
21441c99275SPeter Avalos static const struct tok lacp_tlv_actor_partner_info_state_values[] = {
21541c99275SPeter Avalos { 0x01, "Activity"},
21641c99275SPeter Avalos { 0x02, "Timeout"},
21741c99275SPeter Avalos { 0x04, "Aggregation"},
21841c99275SPeter Avalos { 0x08, "Synchronization"},
21941c99275SPeter Avalos { 0x10, "Collecting"},
22041c99275SPeter Avalos { 0x20, "Distributing"},
22141c99275SPeter Avalos { 0x40, "Default"},
22241c99275SPeter Avalos { 0x80, "Expired"},
22341c99275SPeter Avalos { 0, NULL}
22441c99275SPeter Avalos };
22541c99275SPeter Avalos
22641c99275SPeter Avalos struct lacp_tlv_collector_info_t {
227*ed775ee7SAntonio Huete Jimenez nd_uint16_t max_delay;
228*ed775ee7SAntonio Huete Jimenez nd_byte pad[12];
22941c99275SPeter Avalos };
23041c99275SPeter Avalos
23141c99275SPeter Avalos struct marker_tlv_marker_info_t {
232*ed775ee7SAntonio Huete Jimenez nd_uint16_t req_port;
233*ed775ee7SAntonio Huete Jimenez nd_mac_addr req_sys;
234*ed775ee7SAntonio Huete Jimenez nd_uint32_t req_trans_id;
235*ed775ee7SAntonio Huete Jimenez nd_byte pad[2];
23641c99275SPeter Avalos };
23741c99275SPeter Avalos
23841c99275SPeter Avalos struct lacp_marker_tlv_terminator_t {
239*ed775ee7SAntonio Huete Jimenez nd_byte pad[50];
24041c99275SPeter Avalos };
24141c99275SPeter Avalos
242*ed775ee7SAntonio Huete Jimenez static void slow_marker_lacp_print(netdissect_options *, const u_char *, u_int, u_int);
243*ed775ee7SAntonio Huete Jimenez static void slow_oam_print(netdissect_options *, const u_char *, u_int);
244ea7b4bf5SPeter Avalos
24541c99275SPeter Avalos void
slow_print(netdissect_options * ndo,const u_char * pptr,u_int len)246411677aeSAaron LI slow_print(netdissect_options *ndo,
247*ed775ee7SAntonio Huete Jimenez const u_char *pptr, u_int len)
248411677aeSAaron LI {
249ea7b4bf5SPeter Avalos int print_version;
250411677aeSAaron LI u_int subtype;
251ea7b4bf5SPeter Avalos
252*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "slow";
253411677aeSAaron LI if (len < 1)
254411677aeSAaron LI goto tooshort;
255*ed775ee7SAntonio Huete Jimenez subtype = GET_U_1(pptr);
256ea7b4bf5SPeter Avalos
257ea7b4bf5SPeter Avalos /*
258ea7b4bf5SPeter Avalos * Sanity checking of the header.
259ea7b4bf5SPeter Avalos */
260411677aeSAaron LI switch (subtype) {
261ea7b4bf5SPeter Avalos case SLOW_PROTO_LACP:
262411677aeSAaron LI if (len < 2)
263411677aeSAaron LI goto tooshort;
264*ed775ee7SAntonio Huete Jimenez if (GET_U_1(pptr + 1) != LACP_VERSION) {
265*ed775ee7SAntonio Huete Jimenez ND_PRINT("LACP version %u packet not supported",
266*ed775ee7SAntonio Huete Jimenez GET_U_1(pptr + 1));
267ea7b4bf5SPeter Avalos return;
268ea7b4bf5SPeter Avalos }
269ea7b4bf5SPeter Avalos print_version = 1;
270ea7b4bf5SPeter Avalos break;
271ea7b4bf5SPeter Avalos
272ea7b4bf5SPeter Avalos case SLOW_PROTO_MARKER:
273411677aeSAaron LI if (len < 2)
274411677aeSAaron LI goto tooshort;
275*ed775ee7SAntonio Huete Jimenez if (GET_U_1(pptr + 1) != MARKER_VERSION) {
276*ed775ee7SAntonio Huete Jimenez ND_PRINT("MARKER version %u packet not supported",
277*ed775ee7SAntonio Huete Jimenez GET_U_1(pptr + 1));
278ea7b4bf5SPeter Avalos return;
279ea7b4bf5SPeter Avalos }
280ea7b4bf5SPeter Avalos print_version = 1;
281ea7b4bf5SPeter Avalos break;
282ea7b4bf5SPeter Avalos
283ea7b4bf5SPeter Avalos case SLOW_PROTO_OAM: /* fall through */
284ea7b4bf5SPeter Avalos print_version = 0;
285ea7b4bf5SPeter Avalos break;
286ea7b4bf5SPeter Avalos
287ea7b4bf5SPeter Avalos default:
288ea7b4bf5SPeter Avalos /* print basic information and exit */
289ea7b4bf5SPeter Avalos print_version = -1;
290ea7b4bf5SPeter Avalos break;
291ea7b4bf5SPeter Avalos }
292ea7b4bf5SPeter Avalos
293411677aeSAaron LI if (print_version == 1) {
294*ed775ee7SAntonio Huete Jimenez ND_PRINT("%sv%u, length %u",
295411677aeSAaron LI tok2str(slow_proto_values, "unknown (%u)", subtype),
296*ed775ee7SAntonio Huete Jimenez GET_U_1((pptr + 1)),
297*ed775ee7SAntonio Huete Jimenez len);
298ea7b4bf5SPeter Avalos } else {
299ea7b4bf5SPeter Avalos /* some slow protos don't have a version number in the header */
300*ed775ee7SAntonio Huete Jimenez ND_PRINT("%s, length %u",
301411677aeSAaron LI tok2str(slow_proto_values, "unknown (%u)", subtype),
302*ed775ee7SAntonio Huete Jimenez len);
303ea7b4bf5SPeter Avalos }
304ea7b4bf5SPeter Avalos
305ea7b4bf5SPeter Avalos /* unrecognized subtype */
306ea7b4bf5SPeter Avalos if (print_version == -1) {
307411677aeSAaron LI print_unknown_data(ndo, pptr, "\n\t", len);
308ea7b4bf5SPeter Avalos return;
309ea7b4bf5SPeter Avalos }
310ea7b4bf5SPeter Avalos
311411677aeSAaron LI if (!ndo->ndo_vflag)
312ea7b4bf5SPeter Avalos return;
313ea7b4bf5SPeter Avalos
314411677aeSAaron LI switch (subtype) {
315ea7b4bf5SPeter Avalos default: /* should not happen */
316ea7b4bf5SPeter Avalos break;
317ea7b4bf5SPeter Avalos
318ea7b4bf5SPeter Avalos case SLOW_PROTO_OAM:
319411677aeSAaron LI /* skip subtype */
320411677aeSAaron LI len -= 1;
321411677aeSAaron LI pptr += 1;
322411677aeSAaron LI slow_oam_print(ndo, pptr, len);
323ea7b4bf5SPeter Avalos break;
324ea7b4bf5SPeter Avalos
325ea7b4bf5SPeter Avalos case SLOW_PROTO_LACP: /* LACP and MARKER share the same semantics */
326ea7b4bf5SPeter Avalos case SLOW_PROTO_MARKER:
327411677aeSAaron LI /* skip subtype and version */
328411677aeSAaron LI len -= 2;
329411677aeSAaron LI pptr += 2;
330411677aeSAaron LI slow_marker_lacp_print(ndo, pptr, len, subtype);
331ea7b4bf5SPeter Avalos break;
332ea7b4bf5SPeter Avalos }
333ea7b4bf5SPeter Avalos return;
334ea7b4bf5SPeter Avalos
335411677aeSAaron LI tooshort:
336411677aeSAaron LI if (!ndo->ndo_vflag)
337*ed775ee7SAntonio Huete Jimenez ND_PRINT(" (packet is too short)");
338411677aeSAaron LI else
339*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t\t packet is too short");
340ea7b4bf5SPeter Avalos }
341ea7b4bf5SPeter Avalos
342411677aeSAaron LI static void
slow_marker_lacp_print(netdissect_options * ndo,const u_char * tptr,u_int tlen,u_int proto_subtype)343411677aeSAaron LI slow_marker_lacp_print(netdissect_options *ndo,
344*ed775ee7SAntonio Huete Jimenez const u_char *tptr, u_int tlen,
345411677aeSAaron LI u_int proto_subtype)
346411677aeSAaron LI {
34741c99275SPeter Avalos const struct tlv_header_t *tlv_header;
348ea7b4bf5SPeter Avalos const u_char *tlv_tptr;
349*ed775ee7SAntonio Huete Jimenez u_int tlv_type, tlv_len, tlv_tlen;
35041c99275SPeter Avalos
35141c99275SPeter Avalos union {
35241c99275SPeter Avalos const struct lacp_marker_tlv_terminator_t *lacp_marker_tlv_terminator;
35341c99275SPeter Avalos const struct lacp_tlv_actor_partner_info_t *lacp_tlv_actor_partner_info;
35441c99275SPeter Avalos const struct lacp_tlv_collector_info_t *lacp_tlv_collector_info;
35541c99275SPeter Avalos const struct marker_tlv_marker_info_t *marker_tlv_marker_info;
35641c99275SPeter Avalos } tlv_ptr;
35741c99275SPeter Avalos
35841c99275SPeter Avalos while(tlen>0) {
359411677aeSAaron LI /* is the packet big enough to include the tlv header ? */
360411677aeSAaron LI if (tlen < sizeof(struct tlv_header_t))
361411677aeSAaron LI goto tooshort;
36241c99275SPeter Avalos /* did we capture enough for fully decoding the tlv header ? */
36341c99275SPeter Avalos tlv_header = (const struct tlv_header_t *)tptr;
364*ed775ee7SAntonio Huete Jimenez tlv_type = GET_U_1(tlv_header->type);
365*ed775ee7SAntonio Huete Jimenez tlv_len = GET_U_1(tlv_header->length);
36641c99275SPeter Avalos
367*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t%s TLV (0x%02x), length %u",
36841c99275SPeter Avalos tok2str(slow_tlv_values,
36941c99275SPeter Avalos "Unknown",
370*ed775ee7SAntonio Huete Jimenez (proto_subtype << 8) + tlv_type),
371*ed775ee7SAntonio Huete Jimenez tlv_type,
372*ed775ee7SAntonio Huete Jimenez tlv_len);
37341c99275SPeter Avalos
374*ed775ee7SAntonio Huete Jimenez if (tlv_type == LACP_MARKER_TLV_TERMINATOR) {
375411677aeSAaron LI /*
376411677aeSAaron LI * This TLV has a length of zero, and means there are no
377411677aeSAaron LI * more TLVs to process.
378411677aeSAaron LI */
37941c99275SPeter Avalos return;
38041c99275SPeter Avalos }
38141c99275SPeter Avalos
382411677aeSAaron LI /* length includes the type and length fields */
383411677aeSAaron LI if (tlv_len < sizeof(struct tlv_header_t)) {
384*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be >= %zu",
385*ed775ee7SAntonio Huete Jimenez sizeof(struct tlv_header_t));
386411677aeSAaron LI return;
387411677aeSAaron LI }
388411677aeSAaron LI
389411677aeSAaron LI /* is the packet big enough to include the tlv ? */
390411677aeSAaron LI if (tlen < tlv_len)
391411677aeSAaron LI goto tooshort;
392411677aeSAaron LI /* did we capture enough for fully decoding the tlv ? */
393*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(tptr, tlv_len);
394411677aeSAaron LI
39541c99275SPeter Avalos tlv_tptr=tptr+sizeof(struct tlv_header_t);
39641c99275SPeter Avalos tlv_tlen=tlv_len-sizeof(struct tlv_header_t);
39741c99275SPeter Avalos
398*ed775ee7SAntonio Huete Jimenez switch((proto_subtype << 8) + tlv_type) {
39941c99275SPeter Avalos
40041c99275SPeter Avalos /* those two TLVs have the same structure -> fall through */
40141c99275SPeter Avalos case ((SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO):
40241c99275SPeter Avalos case ((SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO):
403411677aeSAaron LI if (tlv_tlen !=
404411677aeSAaron LI sizeof(struct lacp_tlv_actor_partner_info_t)) {
405*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be %zu",
406*ed775ee7SAntonio Huete Jimenez sizeof(struct tlv_header_t) + sizeof(struct lacp_tlv_actor_partner_info_t));
407411677aeSAaron LI goto badlength;
408411677aeSAaron LI }
409411677aeSAaron LI
41041c99275SPeter Avalos tlv_ptr.lacp_tlv_actor_partner_info = (const struct lacp_tlv_actor_partner_info_t *)tlv_tptr;
41141c99275SPeter Avalos
412*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t System %s, System Priority %u, Key %u"
41341c99275SPeter Avalos ", Port %u, Port Priority %u\n\t State Flags [%s]",
414*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(tlv_ptr.lacp_tlv_actor_partner_info->sys),
415*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->sys_pri),
416*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->key),
417*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->port),
418*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->port_pri),
41941c99275SPeter Avalos bittok2str(lacp_tlv_actor_partner_info_state_values,
42041c99275SPeter Avalos "none",
421*ed775ee7SAntonio Huete Jimenez GET_U_1(tlv_ptr.lacp_tlv_actor_partner_info->state)));
42241c99275SPeter Avalos
42341c99275SPeter Avalos break;
42441c99275SPeter Avalos
42541c99275SPeter Avalos case ((SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO):
426411677aeSAaron LI if (tlv_tlen !=
427411677aeSAaron LI sizeof(struct lacp_tlv_collector_info_t)) {
428*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be %zu",
429*ed775ee7SAntonio Huete Jimenez sizeof(struct tlv_header_t) + sizeof(struct lacp_tlv_collector_info_t));
430411677aeSAaron LI goto badlength;
431411677aeSAaron LI }
432411677aeSAaron LI
43341c99275SPeter Avalos tlv_ptr.lacp_tlv_collector_info = (const struct lacp_tlv_collector_info_t *)tlv_tptr;
43441c99275SPeter Avalos
435*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Max Delay %u",
436*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv_ptr.lacp_tlv_collector_info->max_delay));
43741c99275SPeter Avalos
43841c99275SPeter Avalos break;
43941c99275SPeter Avalos
44041c99275SPeter Avalos case ((SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO):
441411677aeSAaron LI if (tlv_tlen !=
442411677aeSAaron LI sizeof(struct marker_tlv_marker_info_t)) {
443*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be %zu",
444*ed775ee7SAntonio Huete Jimenez sizeof(struct tlv_header_t) + sizeof(struct marker_tlv_marker_info_t));
445411677aeSAaron LI goto badlength;
446411677aeSAaron LI }
447411677aeSAaron LI
44841c99275SPeter Avalos tlv_ptr.marker_tlv_marker_info = (const struct marker_tlv_marker_info_t *)tlv_tptr;
44941c99275SPeter Avalos
450*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Request System %s, Request Port %u, Request Transaction ID 0x%08x",
451*ed775ee7SAntonio Huete Jimenez GET_ETHERADDR_STRING(tlv_ptr.marker_tlv_marker_info->req_sys),
452*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv_ptr.marker_tlv_marker_info->req_port),
453*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(tlv_ptr.marker_tlv_marker_info->req_trans_id));
45441c99275SPeter Avalos
45541c99275SPeter Avalos break;
45641c99275SPeter Avalos
45741c99275SPeter Avalos default:
458411677aeSAaron LI if (ndo->ndo_vflag <= 1)
459411677aeSAaron LI print_unknown_data(ndo, tlv_tptr, "\n\t ", tlv_tlen);
46041c99275SPeter Avalos break;
46141c99275SPeter Avalos }
462411677aeSAaron LI
463411677aeSAaron LI badlength:
464ea7b4bf5SPeter Avalos /* do we want to see an additional hexdump ? */
465411677aeSAaron LI if (ndo->ndo_vflag > 1) {
466411677aeSAaron LI print_unknown_data(ndo, tptr+sizeof(struct tlv_header_t), "\n\t ",
46741c99275SPeter Avalos tlv_len-sizeof(struct tlv_header_t));
468ea7b4bf5SPeter Avalos }
46941c99275SPeter Avalos
47041c99275SPeter Avalos tptr+=tlv_len;
47141c99275SPeter Avalos tlen-=tlv_len;
47241c99275SPeter Avalos }
47341c99275SPeter Avalos return;
474411677aeSAaron LI
475411677aeSAaron LI tooshort:
476*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t\t packet is too short");
47741c99275SPeter Avalos }
478ea7b4bf5SPeter Avalos
479411677aeSAaron LI static void
slow_oam_print(netdissect_options * ndo,const u_char * tptr,u_int tlen)480411677aeSAaron LI slow_oam_print(netdissect_options *ndo,
481*ed775ee7SAntonio Huete Jimenez const u_char *tptr, u_int tlen)
482411677aeSAaron LI {
483*ed775ee7SAntonio Huete Jimenez uint8_t code;
484*ed775ee7SAntonio Huete Jimenez uint8_t type, length;
485*ed775ee7SAntonio Huete Jimenez uint8_t state;
486*ed775ee7SAntonio Huete Jimenez uint8_t command;
487ea7b4bf5SPeter Avalos u_int hexdump;
488ea7b4bf5SPeter Avalos
489ea7b4bf5SPeter Avalos struct slow_oam_common_header_t {
490*ed775ee7SAntonio Huete Jimenez nd_uint16_t flags;
491*ed775ee7SAntonio Huete Jimenez nd_uint8_t code;
492ea7b4bf5SPeter Avalos };
493ea7b4bf5SPeter Avalos
494ea7b4bf5SPeter Avalos struct slow_oam_tlv_header_t {
495*ed775ee7SAntonio Huete Jimenez nd_uint8_t type;
496*ed775ee7SAntonio Huete Jimenez nd_uint8_t length;
497ea7b4bf5SPeter Avalos };
498ea7b4bf5SPeter Avalos
499ea7b4bf5SPeter Avalos union {
500ea7b4bf5SPeter Avalos const struct slow_oam_common_header_t *slow_oam_common_header;
501ea7b4bf5SPeter Avalos const struct slow_oam_tlv_header_t *slow_oam_tlv_header;
502ea7b4bf5SPeter Avalos } ptr;
503ea7b4bf5SPeter Avalos
504ea7b4bf5SPeter Avalos union {
505ea7b4bf5SPeter Avalos const struct slow_oam_info_t *slow_oam_info;
506ea7b4bf5SPeter Avalos const struct slow_oam_link_event_t *slow_oam_link_event;
507ea7b4bf5SPeter Avalos const struct slow_oam_variablerequest_t *slow_oam_variablerequest;
508ea7b4bf5SPeter Avalos const struct slow_oam_variableresponse_t *slow_oam_variableresponse;
509ea7b4bf5SPeter Avalos const struct slow_oam_loopbackctrl_t *slow_oam_loopbackctrl;
510ea7b4bf5SPeter Avalos } tlv;
511ea7b4bf5SPeter Avalos
512411677aeSAaron LI ptr.slow_oam_common_header = (const struct slow_oam_common_header_t *)tptr;
513411677aeSAaron LI if (tlen < sizeof(*ptr.slow_oam_common_header))
514411677aeSAaron LI goto tooshort;
515*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(ptr.slow_oam_common_header);
516ea7b4bf5SPeter Avalos tptr += sizeof(struct slow_oam_common_header_t);
517ea7b4bf5SPeter Avalos tlen -= sizeof(struct slow_oam_common_header_t);
518ea7b4bf5SPeter Avalos
519*ed775ee7SAntonio Huete Jimenez code = GET_U_1(ptr.slow_oam_common_header->code);
520*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tCode %s OAM PDU, Flags [%s]",
521*ed775ee7SAntonio Huete Jimenez tok2str(slow_oam_code_values, "Unknown (%u)", code),
522ea7b4bf5SPeter Avalos bittok2str(slow_oam_flag_values,
523ea7b4bf5SPeter Avalos "none",
524*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ptr.slow_oam_common_header->flags)));
525ea7b4bf5SPeter Avalos
526*ed775ee7SAntonio Huete Jimenez switch (code) {
527ea7b4bf5SPeter Avalos case SLOW_OAM_CODE_INFO:
528ea7b4bf5SPeter Avalos while (tlen > 0) {
529ea7b4bf5SPeter Avalos ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
530411677aeSAaron LI if (tlen < sizeof(*ptr.slow_oam_tlv_header))
531411677aeSAaron LI goto tooshort;
532*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(ptr.slow_oam_tlv_header);
533*ed775ee7SAntonio Huete Jimenez type = GET_U_1(ptr.slow_oam_tlv_header->type);
534*ed775ee7SAntonio Huete Jimenez length = GET_U_1(ptr.slow_oam_tlv_header->length);
535*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t %s Information Type (%u), length %u",
536*ed775ee7SAntonio Huete Jimenez tok2str(slow_oam_info_type_values, "Reserved", type),
537*ed775ee7SAntonio Huete Jimenez type,
538*ed775ee7SAntonio Huete Jimenez length);
539411677aeSAaron LI
540*ed775ee7SAntonio Huete Jimenez if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
541411677aeSAaron LI /*
542411677aeSAaron LI * As IEEE Std 802.3-2015 says for the End of TLV Marker,
543411677aeSAaron LI * "(the length and value of the Type 0x00 TLV can be ignored)".
544411677aeSAaron LI */
545411677aeSAaron LI return;
546411677aeSAaron LI }
547411677aeSAaron LI
548411677aeSAaron LI /* length includes the type and length fields */
549*ed775ee7SAntonio Huete Jimenez if (length < sizeof(struct slow_oam_tlv_header_t)) {
550*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be >= %zu",
551*ed775ee7SAntonio Huete Jimenez sizeof(struct slow_oam_tlv_header_t));
552411677aeSAaron LI return;
553411677aeSAaron LI }
554411677aeSAaron LI
555*ed775ee7SAntonio Huete Jimenez if (tlen < length)
556411677aeSAaron LI goto tooshort;
557*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(tptr, length);
558ea7b4bf5SPeter Avalos
559ea7b4bf5SPeter Avalos hexdump = FALSE;
560*ed775ee7SAntonio Huete Jimenez switch (type) {
561ea7b4bf5SPeter Avalos case SLOW_OAM_INFO_TYPE_LOCAL: /* identical format - fall through */
562ea7b4bf5SPeter Avalos case SLOW_OAM_INFO_TYPE_REMOTE:
563ea7b4bf5SPeter Avalos tlv.slow_oam_info = (const struct slow_oam_info_t *)tptr;
564ea7b4bf5SPeter Avalos
565*ed775ee7SAntonio Huete Jimenez if (GET_U_1(tlv.slow_oam_info->info_length) !=
566ea7b4bf5SPeter Avalos sizeof(struct slow_oam_info_t)) {
567*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be %zu",
568*ed775ee7SAntonio Huete Jimenez sizeof(struct slow_oam_info_t));
569411677aeSAaron LI hexdump = TRUE;
570411677aeSAaron LI goto badlength_code_info;
571ea7b4bf5SPeter Avalos }
572ea7b4bf5SPeter Avalos
573*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t OAM-Version %u, Revision %u",
574*ed775ee7SAntonio Huete Jimenez GET_U_1(tlv.slow_oam_info->oam_version),
575*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv.slow_oam_info->revision));
576ea7b4bf5SPeter Avalos
577*ed775ee7SAntonio Huete Jimenez state = GET_U_1(tlv.slow_oam_info->state);
578*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t State-Parser-Action %s, State-MUX-Action %s",
579ea7b4bf5SPeter Avalos tok2str(slow_oam_info_type_state_parser_values, "Reserved",
580*ed775ee7SAntonio Huete Jimenez state & OAM_INFO_TYPE_PARSER_MASK),
581ea7b4bf5SPeter Avalos tok2str(slow_oam_info_type_state_mux_values, "Reserved",
582*ed775ee7SAntonio Huete Jimenez state & OAM_INFO_TYPE_MUX_MASK));
583*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t OAM-Config Flags [%s], OAM-PDU-Config max-PDU size %u",
584ea7b4bf5SPeter Avalos bittok2str(slow_oam_info_type_oam_config_values, "none",
585*ed775ee7SAntonio Huete Jimenez GET_U_1(tlv.slow_oam_info->oam_config)),
586*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv.slow_oam_info->oam_pdu_config) &
587*ed775ee7SAntonio Huete Jimenez OAM_INFO_TYPE_PDU_SIZE_MASK);
588*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t OUI %s (0x%06x), Vendor-Private 0x%08x",
589ea7b4bf5SPeter Avalos tok2str(oui_values, "Unknown",
590*ed775ee7SAntonio Huete Jimenez GET_BE_U_3(tlv.slow_oam_info->oui)),
591*ed775ee7SAntonio Huete Jimenez GET_BE_U_3(tlv.slow_oam_info->oui),
592*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(tlv.slow_oam_info->vendor_private));
593ea7b4bf5SPeter Avalos break;
594ea7b4bf5SPeter Avalos
595ea7b4bf5SPeter Avalos case SLOW_OAM_INFO_TYPE_ORG_SPECIFIC:
596ea7b4bf5SPeter Avalos hexdump = TRUE;
597ea7b4bf5SPeter Avalos break;
598ea7b4bf5SPeter Avalos
599ea7b4bf5SPeter Avalos default:
600ea7b4bf5SPeter Avalos hexdump = TRUE;
601ea7b4bf5SPeter Avalos break;
602ea7b4bf5SPeter Avalos }
603ea7b4bf5SPeter Avalos
604411677aeSAaron LI badlength_code_info:
605ea7b4bf5SPeter Avalos /* do we also want to see a hex dump ? */
606411677aeSAaron LI if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
607411677aeSAaron LI print_unknown_data(ndo, tptr, "\n\t ",
608*ed775ee7SAntonio Huete Jimenez length);
609ea7b4bf5SPeter Avalos }
610ea7b4bf5SPeter Avalos
611*ed775ee7SAntonio Huete Jimenez tlen -= length;
612*ed775ee7SAntonio Huete Jimenez tptr += length;
613ea7b4bf5SPeter Avalos }
614ea7b4bf5SPeter Avalos break;
615ea7b4bf5SPeter Avalos
616ea7b4bf5SPeter Avalos case SLOW_OAM_CODE_EVENT_NOTIF:
617411677aeSAaron LI /* Sequence number */
618411677aeSAaron LI if (tlen < 2)
619411677aeSAaron LI goto tooshort;
620*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Sequence Number %u", GET_BE_U_2(tptr));
621411677aeSAaron LI tlen -= 2;
622411677aeSAaron LI tptr += 2;
623411677aeSAaron LI
624411677aeSAaron LI /* TLVs */
625ea7b4bf5SPeter Avalos while (tlen > 0) {
626ea7b4bf5SPeter Avalos ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
627411677aeSAaron LI if (tlen < sizeof(*ptr.slow_oam_tlv_header))
628411677aeSAaron LI goto tooshort;
629*ed775ee7SAntonio Huete Jimenez type = GET_U_1(ptr.slow_oam_tlv_header->type);
630*ed775ee7SAntonio Huete Jimenez length = GET_U_1(ptr.slow_oam_tlv_header->length);
631*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t %s Link Event Type (%u), length %u",
632ea7b4bf5SPeter Avalos tok2str(slow_oam_link_event_values, "Reserved",
633*ed775ee7SAntonio Huete Jimenez type),
634*ed775ee7SAntonio Huete Jimenez type,
635*ed775ee7SAntonio Huete Jimenez length);
636411677aeSAaron LI
637*ed775ee7SAntonio Huete Jimenez if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
638411677aeSAaron LI /*
639411677aeSAaron LI * As IEEE Std 802.3-2015 says for the End of TLV Marker,
640411677aeSAaron LI * "(the length and value of the Type 0x00 TLV can be ignored)".
641411677aeSAaron LI */
642411677aeSAaron LI return;
643411677aeSAaron LI }
644411677aeSAaron LI
645411677aeSAaron LI /* length includes the type and length fields */
646*ed775ee7SAntonio Huete Jimenez if (length < sizeof(struct slow_oam_tlv_header_t)) {
647*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be >= %zu",
648*ed775ee7SAntonio Huete Jimenez sizeof(struct slow_oam_tlv_header_t));
649411677aeSAaron LI return;
650411677aeSAaron LI }
651411677aeSAaron LI
652*ed775ee7SAntonio Huete Jimenez if (tlen < length)
653411677aeSAaron LI goto tooshort;
654*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(tptr, length);
655ea7b4bf5SPeter Avalos
656ea7b4bf5SPeter Avalos hexdump = FALSE;
657*ed775ee7SAntonio Huete Jimenez switch (type) {
658ea7b4bf5SPeter Avalos case SLOW_OAM_LINK_EVENT_ERR_SYM_PER: /* identical format - fall through */
659ea7b4bf5SPeter Avalos case SLOW_OAM_LINK_EVENT_ERR_FRM:
660ea7b4bf5SPeter Avalos case SLOW_OAM_LINK_EVENT_ERR_FRM_PER:
661ea7b4bf5SPeter Avalos case SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM:
662ea7b4bf5SPeter Avalos tlv.slow_oam_link_event = (const struct slow_oam_link_event_t *)tptr;
663ea7b4bf5SPeter Avalos
664*ed775ee7SAntonio Huete Jimenez if (GET_U_1(tlv.slow_oam_link_event->event_length) !=
665ea7b4bf5SPeter Avalos sizeof(struct slow_oam_link_event_t)) {
666*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t ERROR: illegal length - should be %zu",
667*ed775ee7SAntonio Huete Jimenez sizeof(struct slow_oam_link_event_t));
668411677aeSAaron LI hexdump = TRUE;
669411677aeSAaron LI goto badlength_event_notif;
670ea7b4bf5SPeter Avalos }
671ea7b4bf5SPeter Avalos
672*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Timestamp %u ms, Errored Window %" PRIu64
673ea7b4bf5SPeter Avalos "\n\t Errored Threshold %" PRIu64
674ea7b4bf5SPeter Avalos "\n\t Errors %" PRIu64
675ea7b4bf5SPeter Avalos "\n\t Error Running Total %" PRIu64
676ea7b4bf5SPeter Avalos "\n\t Event Running Total %u",
677*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(tlv.slow_oam_link_event->time_stamp)*100,
678*ed775ee7SAntonio Huete Jimenez GET_BE_U_8(tlv.slow_oam_link_event->window),
679*ed775ee7SAntonio Huete Jimenez GET_BE_U_8(tlv.slow_oam_link_event->threshold),
680*ed775ee7SAntonio Huete Jimenez GET_BE_U_8(tlv.slow_oam_link_event->errors),
681*ed775ee7SAntonio Huete Jimenez GET_BE_U_8(tlv.slow_oam_link_event->errors_running_total),
682*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(tlv.slow_oam_link_event->event_running_total));
683ea7b4bf5SPeter Avalos break;
684ea7b4bf5SPeter Avalos
685ea7b4bf5SPeter Avalos case SLOW_OAM_LINK_EVENT_ORG_SPECIFIC:
686ea7b4bf5SPeter Avalos hexdump = TRUE;
687ea7b4bf5SPeter Avalos break;
688ea7b4bf5SPeter Avalos
689ea7b4bf5SPeter Avalos default:
690ea7b4bf5SPeter Avalos hexdump = TRUE;
691ea7b4bf5SPeter Avalos break;
692ea7b4bf5SPeter Avalos }
693ea7b4bf5SPeter Avalos
694411677aeSAaron LI badlength_event_notif:
695ea7b4bf5SPeter Avalos /* do we also want to see a hex dump ? */
696411677aeSAaron LI if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
697411677aeSAaron LI print_unknown_data(ndo, tptr, "\n\t ",
698*ed775ee7SAntonio Huete Jimenez length);
699ea7b4bf5SPeter Avalos }
700ea7b4bf5SPeter Avalos
701*ed775ee7SAntonio Huete Jimenez tlen -= length;
702*ed775ee7SAntonio Huete Jimenez tptr += length;
703ea7b4bf5SPeter Avalos }
704ea7b4bf5SPeter Avalos break;
705ea7b4bf5SPeter Avalos
706ea7b4bf5SPeter Avalos case SLOW_OAM_CODE_LOOPBACK_CTRL:
707ea7b4bf5SPeter Avalos tlv.slow_oam_loopbackctrl = (const struct slow_oam_loopbackctrl_t *)tptr;
708411677aeSAaron LI if (tlen < sizeof(*tlv.slow_oam_loopbackctrl))
709411677aeSAaron LI goto tooshort;
710*ed775ee7SAntonio Huete Jimenez command = GET_U_1(tlv.slow_oam_loopbackctrl->command);
711*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Command %s (%u)",
712ea7b4bf5SPeter Avalos tok2str(slow_oam_loopbackctrl_cmd_values,
713ea7b4bf5SPeter Avalos "Unknown",
714*ed775ee7SAntonio Huete Jimenez command),
715*ed775ee7SAntonio Huete Jimenez command);
716ea7b4bf5SPeter Avalos tptr ++;
717ea7b4bf5SPeter Avalos tlen --;
718ea7b4bf5SPeter Avalos break;
719ea7b4bf5SPeter Avalos
720ea7b4bf5SPeter Avalos /*
721ea7b4bf5SPeter Avalos * FIXME those are the defined codes that lack a decoder
722ea7b4bf5SPeter Avalos * you are welcome to contribute code ;-)
723ea7b4bf5SPeter Avalos */
724ea7b4bf5SPeter Avalos case SLOW_OAM_CODE_VAR_REQUEST:
725ea7b4bf5SPeter Avalos case SLOW_OAM_CODE_VAR_RESPONSE:
726ea7b4bf5SPeter Avalos case SLOW_OAM_CODE_PRIVATE:
727ea7b4bf5SPeter Avalos default:
728411677aeSAaron LI if (ndo->ndo_vflag <= 1) {
729411677aeSAaron LI print_unknown_data(ndo, tptr, "\n\t ", tlen);
730ea7b4bf5SPeter Avalos }
731ea7b4bf5SPeter Avalos break;
732ea7b4bf5SPeter Avalos }
733ea7b4bf5SPeter Avalos return;
734411677aeSAaron LI
735411677aeSAaron LI tooshort:
736*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t\t packet is too short");
737ea7b4bf5SPeter Avalos }
738