4 * Copyright (c) 1998-2005 The TCPDUMP project
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that: (1) source code
8 * distributions retain the above copyright notice and this paragraph
9 * in its entirety, and (2) distributions including binary code include
10 * the above copyright notice and this paragraph in its entirety in
11 * the documentation or other materials provided with the distribution.
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
13 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
14 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 * FOR A PARTICULAR PURPOSE.
17 * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
19 * Original code by Hannes Gredler (hannes@juniper.net)
22 #include <sys/cdefs.h>
25 static const char rcsid
[] _U_
=
26 "@(#) Header: /tcpdump/master/tcpdump/print-slow.c,v 1.1.2.1 2005/07/10 14:47:56 hannes Exp";
28 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
36 #include <tcpdump-stdinc.h>
42 #include "interface.h"
44 #include "addrtoname.h"
47 struct slow_common_header
{
48 u_int8_t proto_subtype
;
52 #define SLOW_PROTO_LACP 1
53 #define SLOW_PROTO_MARKER 2
55 #define LACP_VERSION 1
56 #define MARKER_VERSION 1
58 static const struct tok slow_proto_values
[] = {
59 { SLOW_PROTO_LACP
, "LACP" },
60 { SLOW_PROTO_MARKER
, "MARKER" },
69 #define LACP_TLV_TERMINATOR 0x00
70 #define LACP_TLV_ACTOR_INFO 0x01
71 #define LACP_TLV_PARTNER_INFO 0x02
72 #define LACP_TLV_COLLECTOR_INFO 0x03
74 #define MARKER_TLV_TERMINATOR 0x00
75 #define MARKER_TLV_MARKER_INFO 0x01
77 static const struct tok slow_tlv_values
[] = {
78 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_TERMINATOR
, "Terminator"},
79 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_ACTOR_INFO
, "Actor Information"},
80 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_PARTNER_INFO
, "Partner Information"},
81 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_COLLECTOR_INFO
, "Collector Information"},
83 { (SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_TERMINATOR
, "Terminator"},
84 { (SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_MARKER_INFO
, "Marker Information"},
88 struct lacp_tlv_actor_partner_info_t
{
90 u_int8_t sys
[ETHER_ADDR_LEN
];
98 static const struct tok lacp_tlv_actor_partner_info_state_values
[] = {
101 { 0x04, "Aggregation"},
102 { 0x08, "Synchronization"},
103 { 0x10, "Collecting"},
104 { 0x20, "Distributing"},
110 struct lacp_tlv_collector_info_t
{
111 u_int8_t max_delay
[2];
115 struct marker_tlv_marker_info_t
{
116 u_int8_t req_port
[2];
117 u_int8_t req_sys
[ETHER_ADDR_LEN
];
118 u_int8_t req_trans_id
[4];
122 struct lacp_marker_tlv_terminator_t
{
127 slow_print(register const u_char
*pptr
, register u_int len
) {
129 const struct slow_common_header
*slow_com_header
;
130 const struct tlv_header_t
*tlv_header
;
131 const u_char
*tptr
,*tlv_tptr
;
132 u_int tlv_len
,tlen
,tlv_tlen
;
135 const struct lacp_marker_tlv_terminator_t
*lacp_marker_tlv_terminator
;
136 const struct lacp_tlv_actor_partner_info_t
*lacp_tlv_actor_partner_info
;
137 const struct lacp_tlv_collector_info_t
*lacp_tlv_collector_info
;
138 const struct marker_tlv_marker_info_t
*marker_tlv_marker_info
;
142 slow_com_header
= (const struct slow_common_header
*)pptr
;
143 TCHECK(*slow_com_header
);
146 * Sanity checking of the header.
148 if (slow_com_header
->proto_subtype
== SLOW_PROTO_LACP
&&
149 slow_com_header
->version
!= LACP_VERSION
) {
150 printf("LACP version %u packet not supported",slow_com_header
->version
);
153 if (slow_com_header
->proto_subtype
== SLOW_PROTO_MARKER
&&
154 slow_com_header
->version
!= MARKER_VERSION
) {
155 printf("MARKER version %u packet not supported",slow_com_header
->version
);
159 printf("%sv%u, length: %u",
160 tok2str(slow_proto_values
, "unknown (%u)",slow_com_header
->proto_subtype
),
161 slow_com_header
->version
,
167 /* ok they seem to want to know everything - lets fully decode it */
168 tlen
=len
-sizeof(struct slow_common_header
);
169 tptr
+=sizeof(const struct slow_common_header
);
172 /* did we capture enough for fully decoding the tlv header ? */
173 TCHECK2(*tptr
, sizeof(struct tlv_header_t
));
174 tlv_header
= (const struct tlv_header_t
*)tptr
;
175 tlv_len
= tlv_header
->length
;
177 printf("\n\t%s TLV (0x%02x), length: %u",
178 tok2str(slow_tlv_values
,
180 (slow_com_header
->proto_subtype
<< 8) + tlv_header
->type
),
184 if ((tlv_len
< sizeof(struct tlv_header_t
) ||
186 tlv_header
->type
!= LACP_TLV_TERMINATOR
&&
187 tlv_header
->type
!= MARKER_TLV_TERMINATOR
) {
188 printf("\n\t-----trailing data-----");
189 print_unknown_data(tptr
+sizeof(sizeof(struct tlv_header_t
)),"\n\t ",tlen
);
193 tlv_tptr
=tptr
+sizeof(struct tlv_header_t
);
194 tlv_tlen
=tlv_len
-sizeof(struct tlv_header_t
);
196 /* did we capture enough for fully decoding the tlv ? */
197 TCHECK2(*tptr
, tlv_len
);
199 switch((slow_com_header
->proto_subtype
<< 8) + tlv_header
->type
) {
201 /* those two TLVs have the same structure -> fall through */
202 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_ACTOR_INFO
):
203 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_PARTNER_INFO
):
204 tlv_ptr
.lacp_tlv_actor_partner_info
= (const struct lacp_tlv_actor_partner_info_t
*)tlv_tptr
;
206 printf("\n\t System %s, System Priority %u, Key %u" \
207 ", Port %u, Port Priority %u\n\t State Flags [%s]",
208 etheraddr_string(tlv_ptr
.lacp_tlv_actor_partner_info
->sys
),
209 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->sys_pri
),
210 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->key
),
211 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->port
),
212 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->port_pri
),
213 bittok2str(lacp_tlv_actor_partner_info_state_values
,
215 tlv_ptr
.lacp_tlv_actor_partner_info
->state
));
219 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_COLLECTOR_INFO
):
220 tlv_ptr
.lacp_tlv_collector_info
= (const struct lacp_tlv_collector_info_t
*)tlv_tptr
;
222 printf("\n\t Max Delay %u",
223 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_collector_info
->max_delay
));
227 case ((SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_MARKER_INFO
):
228 tlv_ptr
.marker_tlv_marker_info
= (const struct marker_tlv_marker_info_t
*)tlv_tptr
;
230 printf("\n\t Request System %s, Request Port %u, Request Transaction ID 0x%08x",
231 etheraddr_string(tlv_ptr
.marker_tlv_marker_info
->req_sys
),
232 EXTRACT_16BITS(tlv_ptr
.marker_tlv_marker_info
->req_port
),
233 EXTRACT_32BITS(tlv_ptr
.marker_tlv_marker_info
->req_trans_id
));
237 /* those two TLVs have the same structure -> fall through */
238 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_TERMINATOR
):
239 case ((SLOW_PROTO_MARKER
<< 8) + LACP_TLV_TERMINATOR
):
240 tlv_ptr
.lacp_marker_tlv_terminator
= (const struct lacp_marker_tlv_terminator_t
*)tlv_tptr
;
242 tlv_len
= sizeof(tlv_ptr
.lacp_marker_tlv_terminator
->pad
) +
243 sizeof(struct tlv_header_t
);
244 /* tell the user that we modified the length field */
246 printf(" (=%u)",tlv_len
);
247 /* we have messed around with the length field - now we need to check
248 * again if there are enough bytes on the wire for the hexdump */
249 TCHECK2(tlv_ptr
.lacp_marker_tlv_terminator
->pad
[0],
250 sizeof(tlv_ptr
.lacp_marker_tlv_terminator
->pad
));
257 print_unknown_data(tlv_tptr
,"\n\t ",tlv_tlen
);
260 /* do we want to see an additionally hexdump ? */
262 print_unknown_data(tptr
+sizeof(sizeof(struct tlv_header_t
)),"\n\t ",
263 tlv_len
-sizeof(struct tlv_header_t
));
270 printf("\n\t\t packet exceeded snapshot");