2 * Copyright (c) 1998-2006 The TCPDUMP project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that: (1) source code
6 * distributions retain the above copyright notice and this paragraph
7 * in its entirety, and (2) distributions including binary code include
8 * the above copyright notice and this paragraph in its entirety in
9 * the documentation or other materials provided with the distribution.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
15 * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
18 * Original code by Hannes Gredler (hannes@juniper.net)
22 static const char rcsid
[] _U_
=
23 "@(#) $Header: /tcpdump/master/tcpdump/print-slow.c,v 1.2 2006-02-16 16:42:44 hannes Exp $";
30 #include <tcpdump-stdinc.h>
36 #include "interface.h"
38 #include "addrtoname.h"
41 struct slow_common_header_t
{
42 u_int8_t proto_subtype
;
46 #define SLOW_PROTO_LACP 1
47 #define SLOW_PROTO_MARKER 2
48 #define SLOW_PROTO_OAM 3
50 #define LACP_VERSION 1
51 #define MARKER_VERSION 1
53 static const struct tok slow_proto_values
[] = {
54 { SLOW_PROTO_LACP
, "LACP" },
55 { SLOW_PROTO_MARKER
, "MARKER" },
56 { SLOW_PROTO_OAM
, "OAM" },
60 static const struct tok slow_oam_flag_values
[] = {
61 { 0x0001, "Link Fault" },
62 { 0x0002, "Dying Gasp" },
63 { 0x0004, "Critical Event" },
64 { 0x0008, "Local Evaluating" },
65 { 0x0010, "Local Stable" },
66 { 0x0020, "Remote Evaluating" },
67 { 0x0040, "Remote Stable" },
71 #define SLOW_OAM_CODE_INFO 0x00
72 #define SLOW_OAM_CODE_EVENT_NOTIF 0x01
73 #define SLOW_OAM_CODE_VAR_REQUEST 0x02
74 #define SLOW_OAM_CODE_VAR_RESPONSE 0x03
75 #define SLOW_OAM_CODE_LOOPBACK_CTRL 0x04
76 #define SLOW_OAM_CODE_PRIVATE 0xfe
78 static const struct tok slow_oam_code_values
[] = {
79 { SLOW_OAM_CODE_INFO
, "Information" },
80 { SLOW_OAM_CODE_EVENT_NOTIF
, "Event Notification" },
81 { SLOW_OAM_CODE_VAR_REQUEST
, "Variable Request" },
82 { SLOW_OAM_CODE_VAR_RESPONSE
, "Variable Response" },
83 { SLOW_OAM_CODE_LOOPBACK_CTRL
, "Loopback Control" },
84 { SLOW_OAM_CODE_PRIVATE
, "Vendor Private" },
93 #define LACP_TLV_TERMINATOR 0x00
94 #define LACP_TLV_ACTOR_INFO 0x01
95 #define LACP_TLV_PARTNER_INFO 0x02
96 #define LACP_TLV_COLLECTOR_INFO 0x03
98 #define MARKER_TLV_TERMINATOR 0x00
99 #define MARKER_TLV_MARKER_INFO 0x01
101 static const struct tok slow_tlv_values
[] = {
102 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_TERMINATOR
, "Terminator"},
103 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_ACTOR_INFO
, "Actor Information"},
104 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_PARTNER_INFO
, "Partner Information"},
105 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_COLLECTOR_INFO
, "Collector Information"},
107 { (SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_TERMINATOR
, "Terminator"},
108 { (SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_MARKER_INFO
, "Marker Information"},
112 struct lacp_tlv_actor_partner_info_t
{
114 u_int8_t sys
[ETHER_ADDR_LEN
];
116 u_int8_t port_pri
[2];
122 static const struct tok lacp_tlv_actor_partner_info_state_values
[] = {
125 { 0x04, "Aggregation"},
126 { 0x08, "Synchronization"},
127 { 0x10, "Collecting"},
128 { 0x20, "Distributing"},
134 struct lacp_tlv_collector_info_t
{
135 u_int8_t max_delay
[2];
139 struct marker_tlv_marker_info_t
{
140 u_int8_t req_port
[2];
141 u_int8_t req_sys
[ETHER_ADDR_LEN
];
142 u_int8_t req_trans_id
[4];
146 struct lacp_marker_tlv_terminator_t
{
150 void slow_marker_lacp_print(register const u_char
*, register u_int
);
151 void slow_oam_print(register const u_char
*, register u_int
);
153 const struct slow_common_header_t
*slow_com_header
;
156 slow_print(register const u_char
*pptr
, register u_int len
) {
160 slow_com_header
= (const struct slow_common_header_t
*)pptr
;
161 TCHECK(*slow_com_header
);
164 * Sanity checking of the header.
166 switch (slow_com_header
->proto_subtype
) {
167 case SLOW_PROTO_LACP
:
168 if (slow_com_header
->version
!= LACP_VERSION
) {
169 printf("LACP version %u packet not supported",slow_com_header
->version
);
175 case SLOW_PROTO_MARKER
:
176 if (slow_com_header
->version
!= MARKER_VERSION
) {
177 printf("MARKER version %u packet not supported",slow_com_header
->version
);
183 case SLOW_PROTO_OAM
: /* fall through */
188 /* print basic information and exit */
194 printf("%sv%u, length %u",
195 tok2str(slow_proto_values
, "unknown (%u)",slow_com_header
->proto_subtype
),
196 slow_com_header
->version
,
199 /* some slow protos don't have a version number in the header */
200 printf("%s, length %u",
201 tok2str(slow_proto_values
, "unknown (%u)",slow_com_header
->proto_subtype
),
205 /* unrecognized subtype */
206 if (print_version
== -1) {
207 print_unknown_data(pptr
, "\n\t", len
);
214 switch (slow_com_header
->proto_subtype
) {
215 default: /* should not happen */
219 /* skip proto_subtype */
220 slow_oam_print(pptr
+1, len
-1);
223 case SLOW_PROTO_LACP
: /* LACP and MARKER share the same semantics */
224 case SLOW_PROTO_MARKER
:
225 /* skip slow_common_header */
226 len
-= sizeof(const struct slow_common_header_t
);
227 pptr
+= sizeof(const struct slow_common_header_t
);
228 slow_marker_lacp_print(pptr
, len
);
234 printf("\n\t\t packet exceeded snapshot");
237 void slow_marker_lacp_print(register const u_char
*tptr
, register u_int tlen
) {
239 const struct tlv_header_t
*tlv_header
;
240 const u_char
*tlv_tptr
;
241 u_int tlv_len
, tlv_tlen
;
244 const struct lacp_marker_tlv_terminator_t
*lacp_marker_tlv_terminator
;
245 const struct lacp_tlv_actor_partner_info_t
*lacp_tlv_actor_partner_info
;
246 const struct lacp_tlv_collector_info_t
*lacp_tlv_collector_info
;
247 const struct marker_tlv_marker_info_t
*marker_tlv_marker_info
;
251 /* did we capture enough for fully decoding the tlv header ? */
252 TCHECK2(*tptr
, sizeof(struct tlv_header_t
));
253 tlv_header
= (const struct tlv_header_t
*)tptr
;
254 tlv_len
= tlv_header
->length
;
256 printf("\n\t%s TLV (0x%02x), length %u",
257 tok2str(slow_tlv_values
,
259 (slow_com_header
->proto_subtype
<< 8) + tlv_header
->type
),
263 if ((tlv_len
< sizeof(struct tlv_header_t
) ||
265 tlv_header
->type
!= LACP_TLV_TERMINATOR
&&
266 tlv_header
->type
!= MARKER_TLV_TERMINATOR
) {
267 printf("\n\t-----trailing data-----");
268 print_unknown_data(tptr
+sizeof(sizeof(struct tlv_header_t
)),"\n\t ",tlen
);
272 tlv_tptr
=tptr
+sizeof(struct tlv_header_t
);
273 tlv_tlen
=tlv_len
-sizeof(struct tlv_header_t
);
275 /* did we capture enough for fully decoding the tlv ? */
276 TCHECK2(*tptr
, tlv_len
);
278 switch((slow_com_header
->proto_subtype
<< 8) + tlv_header
->type
) {
280 /* those two TLVs have the same structure -> fall through */
281 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_ACTOR_INFO
):
282 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_PARTNER_INFO
):
283 tlv_ptr
.lacp_tlv_actor_partner_info
= (const struct lacp_tlv_actor_partner_info_t
*)tlv_tptr
;
285 printf("\n\t System %s, System Priority %u, Key %u" \
286 ", Port %u, Port Priority %u\n\t State Flags [%s]",
287 etheraddr_string(tlv_ptr
.lacp_tlv_actor_partner_info
->sys
),
288 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->sys_pri
),
289 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->key
),
290 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->port
),
291 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->port_pri
),
292 bittok2str(lacp_tlv_actor_partner_info_state_values
,
294 tlv_ptr
.lacp_tlv_actor_partner_info
->state
));
298 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_COLLECTOR_INFO
):
299 tlv_ptr
.lacp_tlv_collector_info
= (const struct lacp_tlv_collector_info_t
*)tlv_tptr
;
301 printf("\n\t Max Delay %u",
302 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_collector_info
->max_delay
));
306 case ((SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_MARKER_INFO
):
307 tlv_ptr
.marker_tlv_marker_info
= (const struct marker_tlv_marker_info_t
*)tlv_tptr
;
309 printf("\n\t Request System %s, Request Port %u, Request Transaction ID 0x%08x",
310 etheraddr_string(tlv_ptr
.marker_tlv_marker_info
->req_sys
),
311 EXTRACT_16BITS(tlv_ptr
.marker_tlv_marker_info
->req_port
),
312 EXTRACT_32BITS(tlv_ptr
.marker_tlv_marker_info
->req_trans_id
));
316 /* those two TLVs have the same structure -> fall through */
317 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_TERMINATOR
):
318 case ((SLOW_PROTO_MARKER
<< 8) + LACP_TLV_TERMINATOR
):
319 tlv_ptr
.lacp_marker_tlv_terminator
= (const struct lacp_marker_tlv_terminator_t
*)tlv_tptr
;
321 tlv_len
= sizeof(tlv_ptr
.lacp_marker_tlv_terminator
->pad
) +
322 sizeof(struct tlv_header_t
);
323 /* tell the user that we modified the length field */
325 printf(" (=%u)",tlv_len
);
326 /* we have messed around with the length field - now we need to check
327 * again if there are enough bytes on the wire for the hexdump */
328 TCHECK2(tlv_ptr
.lacp_marker_tlv_terminator
->pad
[0],
329 sizeof(tlv_ptr
.lacp_marker_tlv_terminator
->pad
));
336 print_unknown_data(tlv_tptr
,"\n\t ",tlv_tlen
);
339 /* do we want to see an additional hexdump ? */
341 print_unknown_data(tptr
+sizeof(sizeof(struct tlv_header_t
)),"\n\t ",
342 tlv_len
-sizeof(struct tlv_header_t
));
350 printf("\n\t\t packet exceeded snapshot");
353 void slow_oam_print(register const u_char
*tptr
, register u_int tlen
) {
355 struct slow_oam_common_header_t
{
359 const struct slow_oam_common_header_t
*slow_oam_common_header
;
361 slow_oam_common_header
= (struct slow_oam_common_header_t
*)tptr
;
363 printf("Flags [ %s ], Code %s",
364 bittok2str(slow_oam_flag_values
,
366 EXTRACT_16BITS(&slow_oam_common_header
->flags
)),
367 tok2str(slow_oam_code_values
, "Unknown (%u)", slow_oam_common_header
->code
));
369 switch (slow_oam_common_header
->code
) {
370 /* FIXME no codes yet known - just hexdump for now */
371 case SLOW_OAM_CODE_INFO
:
372 case SLOW_OAM_CODE_EVENT_NOTIF
:
373 case SLOW_OAM_CODE_VAR_REQUEST
:
374 case SLOW_OAM_CODE_VAR_RESPONSE
:
375 case SLOW_OAM_CODE_LOOPBACK_CTRL
:
376 case SLOW_OAM_CODE_PRIVATE
:
379 print_unknown_data(tptr
,"\n\t ", tlen
);
383 /* do we want to see an additional hexdump ? */
385 print_unknown_data(tptr
,"\n\t ", tlen
);