xref: /aosp_15_r20/external/tcpdump/print-slow.c (revision 05b00f6010a2396e3db2409989fc67270046269f)
1*05b00f60SXin Li /*
2*05b00f60SXin Li  * Copyright (c) 1998-2006 The TCPDUMP project
3*05b00f60SXin Li  *
4*05b00f60SXin Li  * Redistribution and use in source and binary forms, with or without
5*05b00f60SXin Li  * modification, are permitted provided that: (1) source code
6*05b00f60SXin Li  * distributions retain the above copyright notice and this paragraph
7*05b00f60SXin Li  * in its entirety, and (2) distributions including binary code include
8*05b00f60SXin Li  * the above copyright notice and this paragraph in its entirety in
9*05b00f60SXin Li  * the documentation or other materials provided with the distribution.
10*05b00f60SXin Li  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11*05b00f60SXin Li  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12*05b00f60SXin Li  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13*05b00f60SXin Li  * FOR A PARTICULAR PURPOSE.
14*05b00f60SXin Li  *
15*05b00f60SXin Li  * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
16*05b00f60SXin Li  *                                       OAM as per 802.3ah
17*05b00f60SXin Li  *
18*05b00f60SXin Li  * Original code by Hannes Gredler ([email protected])
19*05b00f60SXin Li  */
20*05b00f60SXin Li 
21*05b00f60SXin Li /* \summary: IEEE "slow protocols" (802.3ad/802.3ah) printer */
22*05b00f60SXin Li 
23*05b00f60SXin Li #ifdef HAVE_CONFIG_H
24*05b00f60SXin Li #include <config.h>
25*05b00f60SXin Li #endif
26*05b00f60SXin Li 
27*05b00f60SXin Li #include "netdissect-stdinc.h"
28*05b00f60SXin Li 
29*05b00f60SXin Li #define ND_LONGJMP_FROM_TCHECK
30*05b00f60SXin Li #include "netdissect.h"
31*05b00f60SXin Li #include "extract.h"
32*05b00f60SXin Li #include "addrtoname.h"
33*05b00f60SXin Li #include "oui.h"
34*05b00f60SXin Li 
35*05b00f60SXin Li 
36*05b00f60SXin Li #define	SLOW_PROTO_LACP                     1
37*05b00f60SXin Li #define	SLOW_PROTO_MARKER                   2
38*05b00f60SXin Li #define SLOW_PROTO_OAM                      3
39*05b00f60SXin Li 
40*05b00f60SXin Li #define	LACP_VERSION                        1
41*05b00f60SXin Li #define	MARKER_VERSION                      1
42*05b00f60SXin Li 
43*05b00f60SXin Li static const struct tok slow_proto_values[] = {
44*05b00f60SXin Li     { SLOW_PROTO_LACP, "LACP" },
45*05b00f60SXin Li     { SLOW_PROTO_MARKER, "MARKER" },
46*05b00f60SXin Li     { SLOW_PROTO_OAM, "OAM" },
47*05b00f60SXin Li     { 0, NULL}
48*05b00f60SXin Li };
49*05b00f60SXin Li 
50*05b00f60SXin Li static const struct tok slow_oam_flag_values[] = {
51*05b00f60SXin Li     { 0x0001, "Link Fault" },
52*05b00f60SXin Li     { 0x0002, "Dying Gasp" },
53*05b00f60SXin Li     { 0x0004, "Critical Event" },
54*05b00f60SXin Li     { 0x0008, "Local Evaluating" },
55*05b00f60SXin Li     { 0x0010, "Local Stable" },
56*05b00f60SXin Li     { 0x0020, "Remote Evaluating" },
57*05b00f60SXin Li     { 0x0040, "Remote Stable" },
58*05b00f60SXin Li     { 0, NULL}
59*05b00f60SXin Li };
60*05b00f60SXin Li 
61*05b00f60SXin Li #define SLOW_OAM_CODE_INFO          0x00
62*05b00f60SXin Li #define SLOW_OAM_CODE_EVENT_NOTIF   0x01
63*05b00f60SXin Li #define SLOW_OAM_CODE_VAR_REQUEST   0x02
64*05b00f60SXin Li #define SLOW_OAM_CODE_VAR_RESPONSE  0x03
65*05b00f60SXin Li #define SLOW_OAM_CODE_LOOPBACK_CTRL 0x04
66*05b00f60SXin Li #define SLOW_OAM_CODE_PRIVATE       0xfe
67*05b00f60SXin Li 
68*05b00f60SXin Li static const struct tok slow_oam_code_values[] = {
69*05b00f60SXin Li     { SLOW_OAM_CODE_INFO, "Information" },
70*05b00f60SXin Li     { SLOW_OAM_CODE_EVENT_NOTIF, "Event Notification" },
71*05b00f60SXin Li     { SLOW_OAM_CODE_VAR_REQUEST, "Variable Request" },
72*05b00f60SXin Li     { SLOW_OAM_CODE_VAR_RESPONSE, "Variable Response" },
73*05b00f60SXin Li     { SLOW_OAM_CODE_LOOPBACK_CTRL, "Loopback Control" },
74*05b00f60SXin Li     { SLOW_OAM_CODE_PRIVATE, "Vendor Private" },
75*05b00f60SXin Li     { 0, NULL}
76*05b00f60SXin Li };
77*05b00f60SXin Li 
78*05b00f60SXin Li struct slow_oam_info_t {
79*05b00f60SXin Li     nd_uint8_t info_type;
80*05b00f60SXin Li     nd_uint8_t info_length;
81*05b00f60SXin Li     nd_uint8_t oam_version;
82*05b00f60SXin Li     nd_uint16_t revision;
83*05b00f60SXin Li     nd_uint8_t state;
84*05b00f60SXin Li     nd_uint8_t oam_config;
85*05b00f60SXin Li     nd_uint16_t oam_pdu_config;
86*05b00f60SXin Li     nd_uint24_t oui;
87*05b00f60SXin Li     nd_uint32_t vendor_private;
88*05b00f60SXin Li };
89*05b00f60SXin Li 
90*05b00f60SXin Li #define SLOW_OAM_INFO_TYPE_END_OF_TLV 0x00
91*05b00f60SXin Li #define SLOW_OAM_INFO_TYPE_LOCAL 0x01
92*05b00f60SXin Li #define SLOW_OAM_INFO_TYPE_REMOTE 0x02
93*05b00f60SXin Li #define SLOW_OAM_INFO_TYPE_ORG_SPECIFIC 0xfe
94*05b00f60SXin Li 
95*05b00f60SXin Li static const struct tok slow_oam_info_type_values[] = {
96*05b00f60SXin Li     { SLOW_OAM_INFO_TYPE_END_OF_TLV, "End of TLV marker" },
97*05b00f60SXin Li     { SLOW_OAM_INFO_TYPE_LOCAL, "Local" },
98*05b00f60SXin Li     { SLOW_OAM_INFO_TYPE_REMOTE, "Remote" },
99*05b00f60SXin Li     { SLOW_OAM_INFO_TYPE_ORG_SPECIFIC, "Organization specific" },
100*05b00f60SXin Li     { 0, NULL}
101*05b00f60SXin Li };
102*05b00f60SXin Li 
103*05b00f60SXin Li #define OAM_INFO_TYPE_PARSER_MASK 0x3
104*05b00f60SXin Li static const struct tok slow_oam_info_type_state_parser_values[] = {
105*05b00f60SXin Li     { 0x00, "forwarding" },
106*05b00f60SXin Li     { 0x01, "looping back" },
107*05b00f60SXin Li     { 0x02, "discarding" },
108*05b00f60SXin Li     { 0x03, "reserved" },
109*05b00f60SXin Li     { 0, NULL}
110*05b00f60SXin Li };
111*05b00f60SXin Li 
112*05b00f60SXin Li #define OAM_INFO_TYPE_MUX_MASK 0x4
113*05b00f60SXin Li static const struct tok slow_oam_info_type_state_mux_values[] = {
114*05b00f60SXin Li     { 0x00, "forwarding" },
115*05b00f60SXin Li     { 0x04, "discarding" },
116*05b00f60SXin Li     { 0, NULL}
117*05b00f60SXin Li };
118*05b00f60SXin Li 
119*05b00f60SXin Li static const struct tok slow_oam_info_type_oam_config_values[] = {
120*05b00f60SXin Li     { 0x01, "Active" },
121*05b00f60SXin Li     { 0x02, "Unidirectional" },
122*05b00f60SXin Li     { 0x04, "Remote-Loopback" },
123*05b00f60SXin Li     { 0x08, "Link-Events" },
124*05b00f60SXin Li     { 0x10, "Variable-Retrieval" },
125*05b00f60SXin Li     { 0, NULL}
126*05b00f60SXin Li };
127*05b00f60SXin Li 
128*05b00f60SXin Li /* 11 Bits */
129*05b00f60SXin Li #define OAM_INFO_TYPE_PDU_SIZE_MASK 0x7ff
130*05b00f60SXin Li 
131*05b00f60SXin Li #define SLOW_OAM_LINK_EVENT_END_OF_TLV 0x00
132*05b00f60SXin Li #define SLOW_OAM_LINK_EVENT_ERR_SYM_PER 0x01
133*05b00f60SXin Li #define SLOW_OAM_LINK_EVENT_ERR_FRM 0x02
134*05b00f60SXin Li #define SLOW_OAM_LINK_EVENT_ERR_FRM_PER 0x03
135*05b00f60SXin Li #define SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM 0x04
136*05b00f60SXin Li #define SLOW_OAM_LINK_EVENT_ORG_SPECIFIC 0xfe
137*05b00f60SXin Li 
138*05b00f60SXin Li static const struct tok slow_oam_link_event_values[] = {
139*05b00f60SXin Li     { SLOW_OAM_LINK_EVENT_END_OF_TLV, "End of TLV marker" },
140*05b00f60SXin Li     { SLOW_OAM_LINK_EVENT_ERR_SYM_PER, "Errored Symbol Period Event" },
141*05b00f60SXin Li     { SLOW_OAM_LINK_EVENT_ERR_FRM, "Errored Frame Event" },
142*05b00f60SXin Li     { SLOW_OAM_LINK_EVENT_ERR_FRM_PER, "Errored Frame Period Event" },
143*05b00f60SXin Li     { SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM, "Errored Frame Seconds Summary Event" },
144*05b00f60SXin Li     { SLOW_OAM_LINK_EVENT_ORG_SPECIFIC, "Organization specific" },
145*05b00f60SXin Li     { 0, NULL}
146*05b00f60SXin Li };
147*05b00f60SXin Li 
148*05b00f60SXin Li struct slow_oam_link_event_t {
149*05b00f60SXin Li     nd_uint8_t event_type;
150*05b00f60SXin Li     nd_uint8_t event_length;
151*05b00f60SXin Li     nd_uint16_t time_stamp;
152*05b00f60SXin Li     nd_uint64_t window;
153*05b00f60SXin Li     nd_uint64_t threshold;
154*05b00f60SXin Li     nd_uint64_t errors;
155*05b00f60SXin Li     nd_uint64_t errors_running_total;
156*05b00f60SXin Li     nd_uint32_t event_running_total;
157*05b00f60SXin Li };
158*05b00f60SXin Li 
159*05b00f60SXin Li struct slow_oam_variablerequest_t {
160*05b00f60SXin Li     nd_uint8_t branch;
161*05b00f60SXin Li     nd_uint16_t leaf;
162*05b00f60SXin Li };
163*05b00f60SXin Li 
164*05b00f60SXin Li struct slow_oam_variableresponse_t {
165*05b00f60SXin Li     nd_uint8_t branch;
166*05b00f60SXin Li     nd_uint16_t leaf;
167*05b00f60SXin Li     nd_uint8_t length;
168*05b00f60SXin Li };
169*05b00f60SXin Li 
170*05b00f60SXin Li struct slow_oam_loopbackctrl_t {
171*05b00f60SXin Li     nd_uint8_t command;
172*05b00f60SXin Li };
173*05b00f60SXin Li 
174*05b00f60SXin Li static const struct tok slow_oam_loopbackctrl_cmd_values[] = {
175*05b00f60SXin Li     { 0x01, "Enable OAM Remote Loopback" },
176*05b00f60SXin Li     { 0x02, "Disable OAM Remote Loopback" },
177*05b00f60SXin Li     { 0, NULL}
178*05b00f60SXin Li };
179*05b00f60SXin Li 
180*05b00f60SXin Li struct tlv_header_t {
181*05b00f60SXin Li     nd_uint8_t type;
182*05b00f60SXin Li     nd_uint8_t length;
183*05b00f60SXin Li };
184*05b00f60SXin Li 
185*05b00f60SXin Li #define LACP_MARKER_TLV_TERMINATOR     0x00  /* same code for LACP and Marker */
186*05b00f60SXin Li 
187*05b00f60SXin Li #define LACP_TLV_ACTOR_INFO            0x01
188*05b00f60SXin Li #define LACP_TLV_PARTNER_INFO          0x02
189*05b00f60SXin Li #define LACP_TLV_COLLECTOR_INFO        0x03
190*05b00f60SXin Li 
191*05b00f60SXin Li #define MARKER_TLV_MARKER_INFO         0x01
192*05b00f60SXin Li 
193*05b00f60SXin Li static const struct tok slow_tlv_values[] = {
194*05b00f60SXin Li     { (SLOW_PROTO_LACP << 8) + LACP_MARKER_TLV_TERMINATOR, "Terminator"},
195*05b00f60SXin Li     { (SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO, "Actor Information"},
196*05b00f60SXin Li     { (SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO, "Partner Information"},
197*05b00f60SXin Li     { (SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO, "Collector Information"},
198*05b00f60SXin Li 
199*05b00f60SXin Li     { (SLOW_PROTO_MARKER << 8) + LACP_MARKER_TLV_TERMINATOR, "Terminator"},
200*05b00f60SXin Li     { (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO, "Marker Information"},
201*05b00f60SXin Li     { 0, NULL}
202*05b00f60SXin Li };
203*05b00f60SXin Li 
204*05b00f60SXin Li struct lacp_tlv_actor_partner_info_t {
205*05b00f60SXin Li     nd_uint16_t sys_pri;
206*05b00f60SXin Li     nd_mac_addr sys;
207*05b00f60SXin Li     nd_uint16_t key;
208*05b00f60SXin Li     nd_uint16_t port_pri;
209*05b00f60SXin Li     nd_uint16_t port;
210*05b00f60SXin Li     nd_uint8_t state;
211*05b00f60SXin Li     nd_byte    pad[3];
212*05b00f60SXin Li };
213*05b00f60SXin Li 
214*05b00f60SXin Li static const struct tok lacp_tlv_actor_partner_info_state_values[] = {
215*05b00f60SXin Li     { 0x01, "Activity"},
216*05b00f60SXin Li     { 0x02, "Timeout"},
217*05b00f60SXin Li     { 0x04, "Aggregation"},
218*05b00f60SXin Li     { 0x08, "Synchronization"},
219*05b00f60SXin Li     { 0x10, "Collecting"},
220*05b00f60SXin Li     { 0x20, "Distributing"},
221*05b00f60SXin Li     { 0x40, "Default"},
222*05b00f60SXin Li     { 0x80, "Expired"},
223*05b00f60SXin Li     { 0, NULL}
224*05b00f60SXin Li };
225*05b00f60SXin Li 
226*05b00f60SXin Li struct lacp_tlv_collector_info_t {
227*05b00f60SXin Li     nd_uint16_t max_delay;
228*05b00f60SXin Li     nd_byte     pad[12];
229*05b00f60SXin Li };
230*05b00f60SXin Li 
231*05b00f60SXin Li struct marker_tlv_marker_info_t {
232*05b00f60SXin Li     nd_uint16_t req_port;
233*05b00f60SXin Li     nd_mac_addr req_sys;
234*05b00f60SXin Li     nd_uint32_t req_trans_id;
235*05b00f60SXin Li     nd_byte     pad[2];
236*05b00f60SXin Li };
237*05b00f60SXin Li 
238*05b00f60SXin Li struct lacp_marker_tlv_terminator_t {
239*05b00f60SXin Li     nd_byte     pad[50];
240*05b00f60SXin Li };
241*05b00f60SXin Li 
242*05b00f60SXin Li static void slow_marker_lacp_print(netdissect_options *, const u_char *, u_int, u_int);
243*05b00f60SXin Li static void slow_oam_print(netdissect_options *, const u_char *, u_int);
244*05b00f60SXin Li 
245*05b00f60SXin Li void
slow_print(netdissect_options * ndo,const u_char * pptr,u_int len)246*05b00f60SXin Li slow_print(netdissect_options *ndo,
247*05b00f60SXin Li            const u_char *pptr, u_int len)
248*05b00f60SXin Li {
249*05b00f60SXin Li     int print_version;
250*05b00f60SXin Li     u_int subtype;
251*05b00f60SXin Li 
252*05b00f60SXin Li     ndo->ndo_protocol = "slow";
253*05b00f60SXin Li     if (len < 1)
254*05b00f60SXin Li         goto tooshort;
255*05b00f60SXin Li     subtype = GET_U_1(pptr);
256*05b00f60SXin Li 
257*05b00f60SXin Li     /*
258*05b00f60SXin Li      * Sanity checking of the header.
259*05b00f60SXin Li      */
260*05b00f60SXin Li     switch (subtype) {
261*05b00f60SXin Li     case SLOW_PROTO_LACP:
262*05b00f60SXin Li         if (len < 2)
263*05b00f60SXin Li             goto tooshort;
264*05b00f60SXin Li         if (GET_U_1(pptr + 1) != LACP_VERSION) {
265*05b00f60SXin Li             ND_PRINT("LACP version %u packet not supported",
266*05b00f60SXin Li                      GET_U_1(pptr + 1));
267*05b00f60SXin Li             return;
268*05b00f60SXin Li         }
269*05b00f60SXin Li         print_version = 1;
270*05b00f60SXin Li         break;
271*05b00f60SXin Li 
272*05b00f60SXin Li     case SLOW_PROTO_MARKER:
273*05b00f60SXin Li         if (len < 2)
274*05b00f60SXin Li             goto tooshort;
275*05b00f60SXin Li         if (GET_U_1(pptr + 1) != MARKER_VERSION) {
276*05b00f60SXin Li             ND_PRINT("MARKER version %u packet not supported",
277*05b00f60SXin Li                      GET_U_1(pptr + 1));
278*05b00f60SXin Li             return;
279*05b00f60SXin Li         }
280*05b00f60SXin Li         print_version = 1;
281*05b00f60SXin Li         break;
282*05b00f60SXin Li 
283*05b00f60SXin Li     case SLOW_PROTO_OAM: /* fall through */
284*05b00f60SXin Li         print_version = 0;
285*05b00f60SXin Li         break;
286*05b00f60SXin Li 
287*05b00f60SXin Li     default:
288*05b00f60SXin Li         /* print basic information and exit */
289*05b00f60SXin Li         print_version = -1;
290*05b00f60SXin Li         break;
291*05b00f60SXin Li     }
292*05b00f60SXin Li 
293*05b00f60SXin Li     if (print_version == 1) {
294*05b00f60SXin Li         ND_PRINT("%sv%u, length %u",
295*05b00f60SXin Li                tok2str(slow_proto_values, "unknown (%u)", subtype),
296*05b00f60SXin Li                GET_U_1((pptr + 1)),
297*05b00f60SXin Li                len);
298*05b00f60SXin Li     } else {
299*05b00f60SXin Li         /* some slow protos don't have a version number in the header */
300*05b00f60SXin Li         ND_PRINT("%s, length %u",
301*05b00f60SXin Li                tok2str(slow_proto_values, "unknown (%u)", subtype),
302*05b00f60SXin Li                len);
303*05b00f60SXin Li     }
304*05b00f60SXin Li 
305*05b00f60SXin Li     /* unrecognized subtype */
306*05b00f60SXin Li     if (print_version == -1) {
307*05b00f60SXin Li         print_unknown_data(ndo, pptr, "\n\t", len);
308*05b00f60SXin Li         return;
309*05b00f60SXin Li     }
310*05b00f60SXin Li 
311*05b00f60SXin Li     if (!ndo->ndo_vflag)
312*05b00f60SXin Li         return;
313*05b00f60SXin Li 
314*05b00f60SXin Li     switch (subtype) {
315*05b00f60SXin Li     default: /* should not happen */
316*05b00f60SXin Li         break;
317*05b00f60SXin Li 
318*05b00f60SXin Li     case SLOW_PROTO_OAM:
319*05b00f60SXin Li         /* skip subtype */
320*05b00f60SXin Li         len -= 1;
321*05b00f60SXin Li         pptr += 1;
322*05b00f60SXin Li         slow_oam_print(ndo, pptr, len);
323*05b00f60SXin Li         break;
324*05b00f60SXin Li 
325*05b00f60SXin Li     case SLOW_PROTO_LACP:   /* LACP and MARKER share the same semantics */
326*05b00f60SXin Li     case SLOW_PROTO_MARKER:
327*05b00f60SXin Li         /* skip subtype and version */
328*05b00f60SXin Li         len -= 2;
329*05b00f60SXin Li         pptr += 2;
330*05b00f60SXin Li         slow_marker_lacp_print(ndo, pptr, len, subtype);
331*05b00f60SXin Li         break;
332*05b00f60SXin Li     }
333*05b00f60SXin Li     return;
334*05b00f60SXin Li 
335*05b00f60SXin Li tooshort:
336*05b00f60SXin Li     if (!ndo->ndo_vflag)
337*05b00f60SXin Li         ND_PRINT(" (packet is too short)");
338*05b00f60SXin Li     else
339*05b00f60SXin Li         ND_PRINT("\n\t\t packet is too short");
340*05b00f60SXin Li }
341*05b00f60SXin Li 
342*05b00f60SXin Li static void
slow_marker_lacp_print(netdissect_options * ndo,const u_char * tptr,u_int tlen,u_int proto_subtype)343*05b00f60SXin Li slow_marker_lacp_print(netdissect_options *ndo,
344*05b00f60SXin Li                        const u_char *tptr, u_int tlen,
345*05b00f60SXin Li                        u_int proto_subtype)
346*05b00f60SXin Li {
347*05b00f60SXin Li     const struct tlv_header_t *tlv_header;
348*05b00f60SXin Li     const u_char *tlv_tptr;
349*05b00f60SXin Li     u_int tlv_type, tlv_len, tlv_tlen;
350*05b00f60SXin Li 
351*05b00f60SXin Li     union {
352*05b00f60SXin Li         const struct lacp_marker_tlv_terminator_t *lacp_marker_tlv_terminator;
353*05b00f60SXin Li         const struct lacp_tlv_actor_partner_info_t *lacp_tlv_actor_partner_info;
354*05b00f60SXin Li         const struct lacp_tlv_collector_info_t *lacp_tlv_collector_info;
355*05b00f60SXin Li         const struct marker_tlv_marker_info_t *marker_tlv_marker_info;
356*05b00f60SXin Li     } tlv_ptr;
357*05b00f60SXin Li 
358*05b00f60SXin Li     while(tlen>0) {
359*05b00f60SXin Li         /* is the packet big enough to include the tlv header ? */
360*05b00f60SXin Li         if (tlen < sizeof(struct tlv_header_t))
361*05b00f60SXin Li             goto tooshort;
362*05b00f60SXin Li         /* did we capture enough for fully decoding the tlv header ? */
363*05b00f60SXin Li         tlv_header = (const struct tlv_header_t *)tptr;
364*05b00f60SXin Li         tlv_type = GET_U_1(tlv_header->type);
365*05b00f60SXin Li         tlv_len = GET_U_1(tlv_header->length);
366*05b00f60SXin Li 
367*05b00f60SXin Li         ND_PRINT("\n\t%s TLV (0x%02x), length %u",
368*05b00f60SXin Li                tok2str(slow_tlv_values,
369*05b00f60SXin Li                        "Unknown",
370*05b00f60SXin Li                        (proto_subtype << 8) + tlv_type),
371*05b00f60SXin Li                tlv_type,
372*05b00f60SXin Li                tlv_len);
373*05b00f60SXin Li 
374*05b00f60SXin Li         if (tlv_type == LACP_MARKER_TLV_TERMINATOR) {
375*05b00f60SXin Li             /*
376*05b00f60SXin Li              * This TLV has a length of zero, and means there are no
377*05b00f60SXin Li              * more TLVs to process.
378*05b00f60SXin Li              */
379*05b00f60SXin Li             return;
380*05b00f60SXin Li         }
381*05b00f60SXin Li 
382*05b00f60SXin Li         /* length includes the type and length fields */
383*05b00f60SXin Li         if (tlv_len < sizeof(struct tlv_header_t)) {
384*05b00f60SXin Li             ND_PRINT("\n\t    ERROR: illegal length - should be >= %zu",
385*05b00f60SXin Li                      sizeof(struct tlv_header_t));
386*05b00f60SXin Li             return;
387*05b00f60SXin Li         }
388*05b00f60SXin Li 
389*05b00f60SXin Li         /* is the packet big enough to include the tlv ? */
390*05b00f60SXin Li         if (tlen < tlv_len)
391*05b00f60SXin Li             goto tooshort;
392*05b00f60SXin Li         /* did we capture enough for fully decoding the tlv ? */
393*05b00f60SXin Li         ND_TCHECK_LEN(tptr, tlv_len);
394*05b00f60SXin Li 
395*05b00f60SXin Li         tlv_tptr=tptr+sizeof(struct tlv_header_t);
396*05b00f60SXin Li         tlv_tlen=tlv_len-sizeof(struct tlv_header_t);
397*05b00f60SXin Li 
398*05b00f60SXin Li         switch((proto_subtype << 8) + tlv_type) {
399*05b00f60SXin Li 
400*05b00f60SXin Li             /* those two TLVs have the same structure -> fall through */
401*05b00f60SXin Li         case ((SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO):
402*05b00f60SXin Li         case ((SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO):
403*05b00f60SXin Li             if (tlv_tlen !=
404*05b00f60SXin Li                 sizeof(struct lacp_tlv_actor_partner_info_t)) {
405*05b00f60SXin Li                 ND_PRINT("\n\t    ERROR: illegal length - should be %zu",
406*05b00f60SXin Li                          sizeof(struct tlv_header_t) + sizeof(struct lacp_tlv_actor_partner_info_t));
407*05b00f60SXin Li                 goto badlength;
408*05b00f60SXin Li             }
409*05b00f60SXin Li 
410*05b00f60SXin Li             tlv_ptr.lacp_tlv_actor_partner_info = (const struct lacp_tlv_actor_partner_info_t *)tlv_tptr;
411*05b00f60SXin Li 
412*05b00f60SXin Li             ND_PRINT("\n\t  System %s, System Priority %u, Key %u"
413*05b00f60SXin Li                    ", Port %u, Port Priority %u\n\t  State Flags [%s]",
414*05b00f60SXin Li                    GET_ETHERADDR_STRING(tlv_ptr.lacp_tlv_actor_partner_info->sys),
415*05b00f60SXin Li                    GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->sys_pri),
416*05b00f60SXin Li                    GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->key),
417*05b00f60SXin Li                    GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->port),
418*05b00f60SXin Li                    GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->port_pri),
419*05b00f60SXin Li                    bittok2str(lacp_tlv_actor_partner_info_state_values,
420*05b00f60SXin Li                               "none",
421*05b00f60SXin Li                               GET_U_1(tlv_ptr.lacp_tlv_actor_partner_info->state)));
422*05b00f60SXin Li 
423*05b00f60SXin Li             break;
424*05b00f60SXin Li 
425*05b00f60SXin Li         case ((SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO):
426*05b00f60SXin Li             if (tlv_tlen !=
427*05b00f60SXin Li                 sizeof(struct lacp_tlv_collector_info_t)) {
428*05b00f60SXin Li                 ND_PRINT("\n\t    ERROR: illegal length - should be %zu",
429*05b00f60SXin Li                          sizeof(struct tlv_header_t) + sizeof(struct lacp_tlv_collector_info_t));
430*05b00f60SXin Li                 goto badlength;
431*05b00f60SXin Li             }
432*05b00f60SXin Li 
433*05b00f60SXin Li             tlv_ptr.lacp_tlv_collector_info = (const struct lacp_tlv_collector_info_t *)tlv_tptr;
434*05b00f60SXin Li 
435*05b00f60SXin Li             ND_PRINT("\n\t  Max Delay %u",
436*05b00f60SXin Li                    GET_BE_U_2(tlv_ptr.lacp_tlv_collector_info->max_delay));
437*05b00f60SXin Li 
438*05b00f60SXin Li             break;
439*05b00f60SXin Li 
440*05b00f60SXin Li         case ((SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO):
441*05b00f60SXin Li             if (tlv_tlen !=
442*05b00f60SXin Li                 sizeof(struct marker_tlv_marker_info_t)) {
443*05b00f60SXin Li                 ND_PRINT("\n\t    ERROR: illegal length - should be %zu",
444*05b00f60SXin Li                          sizeof(struct tlv_header_t) + sizeof(struct marker_tlv_marker_info_t));
445*05b00f60SXin Li                 goto badlength;
446*05b00f60SXin Li             }
447*05b00f60SXin Li 
448*05b00f60SXin Li             tlv_ptr.marker_tlv_marker_info = (const struct marker_tlv_marker_info_t *)tlv_tptr;
449*05b00f60SXin Li 
450*05b00f60SXin Li             ND_PRINT("\n\t  Request System %s, Request Port %u, Request Transaction ID 0x%08x",
451*05b00f60SXin Li                    GET_ETHERADDR_STRING(tlv_ptr.marker_tlv_marker_info->req_sys),
452*05b00f60SXin Li                    GET_BE_U_2(tlv_ptr.marker_tlv_marker_info->req_port),
453*05b00f60SXin Li                    GET_BE_U_4(tlv_ptr.marker_tlv_marker_info->req_trans_id));
454*05b00f60SXin Li 
455*05b00f60SXin Li             break;
456*05b00f60SXin Li 
457*05b00f60SXin Li         default:
458*05b00f60SXin Li             if (ndo->ndo_vflag <= 1)
459*05b00f60SXin Li                 print_unknown_data(ndo, tlv_tptr, "\n\t  ", tlv_tlen);
460*05b00f60SXin Li             break;
461*05b00f60SXin Li         }
462*05b00f60SXin Li 
463*05b00f60SXin Li     badlength:
464*05b00f60SXin Li         /* do we want to see an additional hexdump ? */
465*05b00f60SXin Li         if (ndo->ndo_vflag > 1) {
466*05b00f60SXin Li             print_unknown_data(ndo, tptr+sizeof(struct tlv_header_t), "\n\t  ",
467*05b00f60SXin Li                                tlv_len-sizeof(struct tlv_header_t));
468*05b00f60SXin Li         }
469*05b00f60SXin Li 
470*05b00f60SXin Li         tptr+=tlv_len;
471*05b00f60SXin Li         tlen-=tlv_len;
472*05b00f60SXin Li     }
473*05b00f60SXin Li     return;
474*05b00f60SXin Li 
475*05b00f60SXin Li tooshort:
476*05b00f60SXin Li     ND_PRINT("\n\t\t packet is too short");
477*05b00f60SXin Li }
478*05b00f60SXin Li 
479*05b00f60SXin Li static void
slow_oam_print(netdissect_options * ndo,const u_char * tptr,u_int tlen)480*05b00f60SXin Li slow_oam_print(netdissect_options *ndo,
481*05b00f60SXin Li                const u_char *tptr, u_int tlen)
482*05b00f60SXin Li {
483*05b00f60SXin Li     uint8_t code;
484*05b00f60SXin Li     uint8_t type, length;
485*05b00f60SXin Li     uint8_t state;
486*05b00f60SXin Li     uint8_t command;
487*05b00f60SXin Li     u_int hexdump;
488*05b00f60SXin Li 
489*05b00f60SXin Li     struct slow_oam_common_header_t {
490*05b00f60SXin Li         nd_uint16_t flags;
491*05b00f60SXin Li         nd_uint8_t code;
492*05b00f60SXin Li     };
493*05b00f60SXin Li 
494*05b00f60SXin Li     struct slow_oam_tlv_header_t {
495*05b00f60SXin Li         nd_uint8_t type;
496*05b00f60SXin Li         nd_uint8_t length;
497*05b00f60SXin Li     };
498*05b00f60SXin Li 
499*05b00f60SXin Li     union {
500*05b00f60SXin Li         const struct slow_oam_common_header_t *slow_oam_common_header;
501*05b00f60SXin Li         const struct slow_oam_tlv_header_t *slow_oam_tlv_header;
502*05b00f60SXin Li     } ptr;
503*05b00f60SXin Li 
504*05b00f60SXin Li     union {
505*05b00f60SXin Li         const struct slow_oam_info_t *slow_oam_info;
506*05b00f60SXin Li         const struct slow_oam_link_event_t *slow_oam_link_event;
507*05b00f60SXin Li         const struct slow_oam_variablerequest_t *slow_oam_variablerequest;
508*05b00f60SXin Li         const struct slow_oam_variableresponse_t *slow_oam_variableresponse;
509*05b00f60SXin Li         const struct slow_oam_loopbackctrl_t *slow_oam_loopbackctrl;
510*05b00f60SXin Li     } tlv;
511*05b00f60SXin Li 
512*05b00f60SXin Li     ptr.slow_oam_common_header = (const struct slow_oam_common_header_t *)tptr;
513*05b00f60SXin Li     if (tlen < sizeof(*ptr.slow_oam_common_header))
514*05b00f60SXin Li         goto tooshort;
515*05b00f60SXin Li     ND_TCHECK_SIZE(ptr.slow_oam_common_header);
516*05b00f60SXin Li     tptr += sizeof(struct slow_oam_common_header_t);
517*05b00f60SXin Li     tlen -= sizeof(struct slow_oam_common_header_t);
518*05b00f60SXin Li 
519*05b00f60SXin Li     code = GET_U_1(ptr.slow_oam_common_header->code);
520*05b00f60SXin Li     ND_PRINT("\n\tCode %s OAM PDU, Flags [%s]",
521*05b00f60SXin Li            tok2str(slow_oam_code_values, "Unknown (%u)", code),
522*05b00f60SXin Li            bittok2str(slow_oam_flag_values,
523*05b00f60SXin Li                       "none",
524*05b00f60SXin Li                       GET_BE_U_2(ptr.slow_oam_common_header->flags)));
525*05b00f60SXin Li 
526*05b00f60SXin Li     switch (code) {
527*05b00f60SXin Li     case SLOW_OAM_CODE_INFO:
528*05b00f60SXin Li         while (tlen > 0) {
529*05b00f60SXin Li             ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
530*05b00f60SXin Li             if (tlen < sizeof(*ptr.slow_oam_tlv_header))
531*05b00f60SXin Li                 goto tooshort;
532*05b00f60SXin Li             ND_TCHECK_SIZE(ptr.slow_oam_tlv_header);
533*05b00f60SXin Li             type = GET_U_1(ptr.slow_oam_tlv_header->type);
534*05b00f60SXin Li             length = GET_U_1(ptr.slow_oam_tlv_header->length);
535*05b00f60SXin Li             ND_PRINT("\n\t  %s Information Type (%u), length %u",
536*05b00f60SXin Li                    tok2str(slow_oam_info_type_values, "Reserved", type),
537*05b00f60SXin Li                    type,
538*05b00f60SXin Li                    length);
539*05b00f60SXin Li 
540*05b00f60SXin Li             if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
541*05b00f60SXin Li                 /*
542*05b00f60SXin Li                  * As IEEE Std 802.3-2015 says for the End of TLV Marker,
543*05b00f60SXin Li                  * "(the length and value of the Type 0x00 TLV can be ignored)".
544*05b00f60SXin Li                  */
545*05b00f60SXin Li                 return;
546*05b00f60SXin Li             }
547*05b00f60SXin Li 
548*05b00f60SXin Li             /* length includes the type and length fields */
549*05b00f60SXin Li             if (length < sizeof(struct slow_oam_tlv_header_t)) {
550*05b00f60SXin Li                 ND_PRINT("\n\t    ERROR: illegal length - should be >= %zu",
551*05b00f60SXin Li                          sizeof(struct slow_oam_tlv_header_t));
552*05b00f60SXin Li                 return;
553*05b00f60SXin Li             }
554*05b00f60SXin Li 
555*05b00f60SXin Li             if (tlen < length)
556*05b00f60SXin Li                 goto tooshort;
557*05b00f60SXin Li             ND_TCHECK_LEN(tptr, length);
558*05b00f60SXin Li 
559*05b00f60SXin Li             hexdump = FALSE;
560*05b00f60SXin Li             switch (type) {
561*05b00f60SXin Li             case SLOW_OAM_INFO_TYPE_LOCAL: /* identical format - fall through */
562*05b00f60SXin Li             case SLOW_OAM_INFO_TYPE_REMOTE:
563*05b00f60SXin Li                 tlv.slow_oam_info = (const struct slow_oam_info_t *)tptr;
564*05b00f60SXin Li 
565*05b00f60SXin Li                 if (GET_U_1(tlv.slow_oam_info->info_length) !=
566*05b00f60SXin Li                     sizeof(struct slow_oam_info_t)) {
567*05b00f60SXin Li                     ND_PRINT("\n\t    ERROR: illegal length - should be %zu",
568*05b00f60SXin Li                            sizeof(struct slow_oam_info_t));
569*05b00f60SXin Li                     hexdump = TRUE;
570*05b00f60SXin Li                     goto badlength_code_info;
571*05b00f60SXin Li                 }
572*05b00f60SXin Li 
573*05b00f60SXin Li                 ND_PRINT("\n\t    OAM-Version %u, Revision %u",
574*05b00f60SXin Li                        GET_U_1(tlv.slow_oam_info->oam_version),
575*05b00f60SXin Li                        GET_BE_U_2(tlv.slow_oam_info->revision));
576*05b00f60SXin Li 
577*05b00f60SXin Li                 state = GET_U_1(tlv.slow_oam_info->state);
578*05b00f60SXin Li                 ND_PRINT("\n\t    State-Parser-Action %s, State-MUX-Action %s",
579*05b00f60SXin Li                        tok2str(slow_oam_info_type_state_parser_values, "Reserved",
580*05b00f60SXin Li                                state & OAM_INFO_TYPE_PARSER_MASK),
581*05b00f60SXin Li                        tok2str(slow_oam_info_type_state_mux_values, "Reserved",
582*05b00f60SXin Li                                state & OAM_INFO_TYPE_MUX_MASK));
583*05b00f60SXin Li                 ND_PRINT("\n\t    OAM-Config Flags [%s], OAM-PDU-Config max-PDU size %u",
584*05b00f60SXin Li                        bittok2str(slow_oam_info_type_oam_config_values, "none",
585*05b00f60SXin Li                                   GET_U_1(tlv.slow_oam_info->oam_config)),
586*05b00f60SXin Li                        GET_BE_U_2(tlv.slow_oam_info->oam_pdu_config) &
587*05b00f60SXin Li                        OAM_INFO_TYPE_PDU_SIZE_MASK);
588*05b00f60SXin Li                 ND_PRINT("\n\t    OUI %s (0x%06x), Vendor-Private 0x%08x",
589*05b00f60SXin Li                        tok2str(oui_values, "Unknown",
590*05b00f60SXin Li                                GET_BE_U_3(tlv.slow_oam_info->oui)),
591*05b00f60SXin Li                        GET_BE_U_3(tlv.slow_oam_info->oui),
592*05b00f60SXin Li                        GET_BE_U_4(tlv.slow_oam_info->vendor_private));
593*05b00f60SXin Li                 break;
594*05b00f60SXin Li 
595*05b00f60SXin Li             case SLOW_OAM_INFO_TYPE_ORG_SPECIFIC:
596*05b00f60SXin Li                 hexdump = TRUE;
597*05b00f60SXin Li                 break;
598*05b00f60SXin Li 
599*05b00f60SXin Li             default:
600*05b00f60SXin Li                 hexdump = TRUE;
601*05b00f60SXin Li                 break;
602*05b00f60SXin Li             }
603*05b00f60SXin Li 
604*05b00f60SXin Li         badlength_code_info:
605*05b00f60SXin Li             /* do we also want to see a hex dump ? */
606*05b00f60SXin Li             if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
607*05b00f60SXin Li                 print_unknown_data(ndo, tptr, "\n\t  ",
608*05b00f60SXin Li                                    length);
609*05b00f60SXin Li             }
610*05b00f60SXin Li 
611*05b00f60SXin Li             tlen -= length;
612*05b00f60SXin Li             tptr += length;
613*05b00f60SXin Li         }
614*05b00f60SXin Li         break;
615*05b00f60SXin Li 
616*05b00f60SXin Li     case SLOW_OAM_CODE_EVENT_NOTIF:
617*05b00f60SXin Li         /* Sequence number */
618*05b00f60SXin Li         if (tlen < 2)
619*05b00f60SXin Li             goto tooshort;
620*05b00f60SXin Li         ND_PRINT("\n\t  Sequence Number %u", GET_BE_U_2(tptr));
621*05b00f60SXin Li         tlen -= 2;
622*05b00f60SXin Li         tptr += 2;
623*05b00f60SXin Li 
624*05b00f60SXin Li         /* TLVs */
625*05b00f60SXin Li         while (tlen > 0) {
626*05b00f60SXin Li             ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
627*05b00f60SXin Li             if (tlen < sizeof(*ptr.slow_oam_tlv_header))
628*05b00f60SXin Li                 goto tooshort;
629*05b00f60SXin Li             type = GET_U_1(ptr.slow_oam_tlv_header->type);
630*05b00f60SXin Li             length = GET_U_1(ptr.slow_oam_tlv_header->length);
631*05b00f60SXin Li             ND_PRINT("\n\t  %s Link Event Type (%u), length %u",
632*05b00f60SXin Li                    tok2str(slow_oam_link_event_values, "Reserved",
633*05b00f60SXin Li                            type),
634*05b00f60SXin Li                    type,
635*05b00f60SXin Li                    length);
636*05b00f60SXin Li 
637*05b00f60SXin Li             if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
638*05b00f60SXin Li                 /*
639*05b00f60SXin Li                  * As IEEE Std 802.3-2015 says for the End of TLV Marker,
640*05b00f60SXin Li                  * "(the length and value of the Type 0x00 TLV can be ignored)".
641*05b00f60SXin Li                  */
642*05b00f60SXin Li                 return;
643*05b00f60SXin Li             }
644*05b00f60SXin Li 
645*05b00f60SXin Li             /* length includes the type and length fields */
646*05b00f60SXin Li             if (length < sizeof(struct slow_oam_tlv_header_t)) {
647*05b00f60SXin Li                 ND_PRINT("\n\t    ERROR: illegal length - should be >= %zu",
648*05b00f60SXin Li                          sizeof(struct slow_oam_tlv_header_t));
649*05b00f60SXin Li                 return;
650*05b00f60SXin Li             }
651*05b00f60SXin Li 
652*05b00f60SXin Li             if (tlen < length)
653*05b00f60SXin Li                 goto tooshort;
654*05b00f60SXin Li             ND_TCHECK_LEN(tptr, length);
655*05b00f60SXin Li 
656*05b00f60SXin Li             hexdump = FALSE;
657*05b00f60SXin Li             switch (type) {
658*05b00f60SXin Li             case SLOW_OAM_LINK_EVENT_ERR_SYM_PER: /* identical format - fall through */
659*05b00f60SXin Li             case SLOW_OAM_LINK_EVENT_ERR_FRM:
660*05b00f60SXin Li             case SLOW_OAM_LINK_EVENT_ERR_FRM_PER:
661*05b00f60SXin Li             case SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM:
662*05b00f60SXin Li                 tlv.slow_oam_link_event = (const struct slow_oam_link_event_t *)tptr;
663*05b00f60SXin Li 
664*05b00f60SXin Li                 if (GET_U_1(tlv.slow_oam_link_event->event_length) !=
665*05b00f60SXin Li                     sizeof(struct slow_oam_link_event_t)) {
666*05b00f60SXin Li                     ND_PRINT("\n\t    ERROR: illegal length - should be %zu",
667*05b00f60SXin Li                              sizeof(struct slow_oam_link_event_t));
668*05b00f60SXin Li                     hexdump = TRUE;
669*05b00f60SXin Li                     goto badlength_event_notif;
670*05b00f60SXin Li                 }
671*05b00f60SXin Li 
672*05b00f60SXin Li                 ND_PRINT("\n\t    Timestamp %u ms, Errored Window %" PRIu64
673*05b00f60SXin Li                        "\n\t    Errored Threshold %" PRIu64
674*05b00f60SXin Li                        "\n\t    Errors %" PRIu64
675*05b00f60SXin Li                        "\n\t    Error Running Total %" PRIu64
676*05b00f60SXin Li                        "\n\t    Event Running Total %u",
677*05b00f60SXin Li                        GET_BE_U_2(tlv.slow_oam_link_event->time_stamp)*100,
678*05b00f60SXin Li                        GET_BE_U_8(tlv.slow_oam_link_event->window),
679*05b00f60SXin Li                        GET_BE_U_8(tlv.slow_oam_link_event->threshold),
680*05b00f60SXin Li                        GET_BE_U_8(tlv.slow_oam_link_event->errors),
681*05b00f60SXin Li                        GET_BE_U_8(tlv.slow_oam_link_event->errors_running_total),
682*05b00f60SXin Li                        GET_BE_U_4(tlv.slow_oam_link_event->event_running_total));
683*05b00f60SXin Li                 break;
684*05b00f60SXin Li 
685*05b00f60SXin Li             case SLOW_OAM_LINK_EVENT_ORG_SPECIFIC:
686*05b00f60SXin Li                 hexdump = TRUE;
687*05b00f60SXin Li                 break;
688*05b00f60SXin Li 
689*05b00f60SXin Li             default:
690*05b00f60SXin Li                 hexdump = TRUE;
691*05b00f60SXin Li                 break;
692*05b00f60SXin Li             }
693*05b00f60SXin Li 
694*05b00f60SXin Li         badlength_event_notif:
695*05b00f60SXin Li             /* do we also want to see a hex dump ? */
696*05b00f60SXin Li             if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
697*05b00f60SXin Li                 print_unknown_data(ndo, tptr, "\n\t  ",
698*05b00f60SXin Li                                    length);
699*05b00f60SXin Li             }
700*05b00f60SXin Li 
701*05b00f60SXin Li             tlen -= length;
702*05b00f60SXin Li             tptr += length;
703*05b00f60SXin Li         }
704*05b00f60SXin Li         break;
705*05b00f60SXin Li 
706*05b00f60SXin Li     case SLOW_OAM_CODE_LOOPBACK_CTRL:
707*05b00f60SXin Li         tlv.slow_oam_loopbackctrl = (const struct slow_oam_loopbackctrl_t *)tptr;
708*05b00f60SXin Li         if (tlen < sizeof(*tlv.slow_oam_loopbackctrl))
709*05b00f60SXin Li             goto tooshort;
710*05b00f60SXin Li         command = GET_U_1(tlv.slow_oam_loopbackctrl->command);
711*05b00f60SXin Li         ND_PRINT("\n\t  Command %s (%u)",
712*05b00f60SXin Li                tok2str(slow_oam_loopbackctrl_cmd_values,
713*05b00f60SXin Li                        "Unknown",
714*05b00f60SXin Li                        command),
715*05b00f60SXin Li                command);
716*05b00f60SXin Li         tptr ++;
717*05b00f60SXin Li         tlen --;
718*05b00f60SXin Li         break;
719*05b00f60SXin Li 
720*05b00f60SXin Li         /*
721*05b00f60SXin Li          * FIXME those are the defined codes that lack a decoder
722*05b00f60SXin Li          * you are welcome to contribute code ;-)
723*05b00f60SXin Li          */
724*05b00f60SXin Li     case SLOW_OAM_CODE_VAR_REQUEST:
725*05b00f60SXin Li     case SLOW_OAM_CODE_VAR_RESPONSE:
726*05b00f60SXin Li     case SLOW_OAM_CODE_PRIVATE:
727*05b00f60SXin Li     default:
728*05b00f60SXin Li         if (ndo->ndo_vflag <= 1) {
729*05b00f60SXin Li             print_unknown_data(ndo, tptr, "\n\t  ", tlen);
730*05b00f60SXin Li         }
731*05b00f60SXin Li         break;
732*05b00f60SXin Li     }
733*05b00f60SXin Li     return;
734*05b00f60SXin Li 
735*05b00f60SXin Li tooshort:
736*05b00f60SXin Li     ND_PRINT("\n\t\t packet is too short");
737*05b00f60SXin Li }
738