2 * Copyright (c) 1998-2005 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
17 * Original code by Hannes Gredler (hannes@juniper.net)
21 static const char rcsid
[] _U_
=
22 "@(#) $Header: /tcpdump/master/tcpdump/print-slow.c,v 1.1.2.1 2005/07/10 14:47:56 hannes Exp $";
29 #include <tcpdump-stdinc.h>
35 #include "interface.h"
37 #include "addrtoname.h"
40 struct slow_common_header
{
41 u_int8_t proto_subtype
;
45 #define SLOW_PROTO_LACP 1
46 #define SLOW_PROTO_MARKER 2
48 #define LACP_VERSION 1
49 #define MARKER_VERSION 1
51 static const struct tok slow_proto_values
[] = {
52 { SLOW_PROTO_LACP
, "LACP" },
53 { SLOW_PROTO_MARKER
, "MARKER" },
62 #define LACP_TLV_TERMINATOR 0x00
63 #define LACP_TLV_ACTOR_INFO 0x01
64 #define LACP_TLV_PARTNER_INFO 0x02
65 #define LACP_TLV_COLLECTOR_INFO 0x03
67 #define MARKER_TLV_TERMINATOR 0x00
68 #define MARKER_TLV_MARKER_INFO 0x01
70 static const struct tok slow_tlv_values
[] = {
71 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_TERMINATOR
, "Terminator"},
72 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_ACTOR_INFO
, "Actor Information"},
73 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_PARTNER_INFO
, "Partner Information"},
74 { (SLOW_PROTO_LACP
<< 8) + LACP_TLV_COLLECTOR_INFO
, "Collector Information"},
76 { (SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_TERMINATOR
, "Terminator"},
77 { (SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_MARKER_INFO
, "Marker Information"},
81 struct lacp_tlv_actor_partner_info_t
{
83 u_int8_t sys
[ETHER_ADDR_LEN
];
91 static const struct tok lacp_tlv_actor_partner_info_state_values
[] = {
94 { 0x04, "Aggregation"},
95 { 0x08, "Synchronization"},
96 { 0x10, "Collecting"},
97 { 0x20, "Distributing"},
103 struct lacp_tlv_collector_info_t
{
104 u_int8_t max_delay
[2];
108 struct marker_tlv_marker_info_t
{
109 u_int8_t req_port
[2];
110 u_int8_t req_sys
[ETHER_ADDR_LEN
];
111 u_int8_t req_trans_id
[4];
115 struct lacp_marker_tlv_terminator_t
{
120 slow_print(register const u_char
*pptr
, register u_int len
) {
122 const struct slow_common_header
*slow_com_header
;
123 const struct tlv_header_t
*tlv_header
;
124 const u_char
*tptr
,*tlv_tptr
;
125 u_int tlv_len
,tlen
,tlv_tlen
;
128 const struct lacp_marker_tlv_terminator_t
*lacp_marker_tlv_terminator
;
129 const struct lacp_tlv_actor_partner_info_t
*lacp_tlv_actor_partner_info
;
130 const struct lacp_tlv_collector_info_t
*lacp_tlv_collector_info
;
131 const struct marker_tlv_marker_info_t
*marker_tlv_marker_info
;
135 slow_com_header
= (const struct slow_common_header
*)pptr
;
136 TCHECK(*slow_com_header
);
139 * Sanity checking of the header.
141 if (slow_com_header
->proto_subtype
== SLOW_PROTO_LACP
&&
142 slow_com_header
->version
!= LACP_VERSION
) {
143 printf("LACP version %u packet not supported",slow_com_header
->version
);
146 if (slow_com_header
->proto_subtype
== SLOW_PROTO_MARKER
&&
147 slow_com_header
->version
!= MARKER_VERSION
) {
148 printf("MARKER version %u packet not supported",slow_com_header
->version
);
152 printf("%sv%u, length: %u",
153 tok2str(slow_proto_values
, "unknown (%u)",slow_com_header
->proto_subtype
),
154 slow_com_header
->version
,
160 /* ok they seem to want to know everything - lets fully decode it */
161 tlen
=len
-sizeof(struct slow_common_header
);
162 tptr
+=sizeof(const struct slow_common_header
);
165 /* did we capture enough for fully decoding the tlv header ? */
166 TCHECK2(*tptr
, sizeof(struct tlv_header_t
));
167 tlv_header
= (const struct tlv_header_t
*)tptr
;
168 tlv_len
= tlv_header
->length
;
170 printf("\n\t%s TLV (0x%02x), length: %u",
171 tok2str(slow_tlv_values
,
173 (slow_com_header
->proto_subtype
<< 8) + tlv_header
->type
),
177 if ((tlv_len
< sizeof(struct tlv_header_t
) ||
179 tlv_header
->type
!= LACP_TLV_TERMINATOR
&&
180 tlv_header
->type
!= MARKER_TLV_TERMINATOR
) {
181 printf("\n\t-----trailing data-----");
182 print_unknown_data(tptr
+sizeof(sizeof(struct tlv_header_t
)),"\n\t ",tlen
);
186 tlv_tptr
=tptr
+sizeof(struct tlv_header_t
);
187 tlv_tlen
=tlv_len
-sizeof(struct tlv_header_t
);
189 /* did we capture enough for fully decoding the tlv ? */
190 TCHECK2(*tptr
, tlv_len
);
192 switch((slow_com_header
->proto_subtype
<< 8) + tlv_header
->type
) {
194 /* those two TLVs have the same structure -> fall through */
195 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_ACTOR_INFO
):
196 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_PARTNER_INFO
):
197 tlv_ptr
.lacp_tlv_actor_partner_info
= (const struct lacp_tlv_actor_partner_info_t
*)tlv_tptr
;
199 printf("\n\t System %s, System Priority %u, Key %u" \
200 ", Port %u, Port Priority %u\n\t State Flags [%s]",
201 etheraddr_string(tlv_ptr
.lacp_tlv_actor_partner_info
->sys
),
202 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->sys_pri
),
203 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->key
),
204 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->port
),
205 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_actor_partner_info
->port_pri
),
206 bittok2str(lacp_tlv_actor_partner_info_state_values
,
208 tlv_ptr
.lacp_tlv_actor_partner_info
->state
));
212 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_COLLECTOR_INFO
):
213 tlv_ptr
.lacp_tlv_collector_info
= (const struct lacp_tlv_collector_info_t
*)tlv_tptr
;
215 printf("\n\t Max Delay %u",
216 EXTRACT_16BITS(tlv_ptr
.lacp_tlv_collector_info
->max_delay
));
220 case ((SLOW_PROTO_MARKER
<< 8) + MARKER_TLV_MARKER_INFO
):
221 tlv_ptr
.marker_tlv_marker_info
= (const struct marker_tlv_marker_info_t
*)tlv_tptr
;
223 printf("\n\t Request System %s, Request Port %u, Request Transaction ID 0x%08x",
224 etheraddr_string(tlv_ptr
.marker_tlv_marker_info
->req_sys
),
225 EXTRACT_16BITS(tlv_ptr
.marker_tlv_marker_info
->req_port
),
226 EXTRACT_32BITS(tlv_ptr
.marker_tlv_marker_info
->req_trans_id
));
230 /* those two TLVs have the same structure -> fall through */
231 case ((SLOW_PROTO_LACP
<< 8) + LACP_TLV_TERMINATOR
):
232 case ((SLOW_PROTO_MARKER
<< 8) + LACP_TLV_TERMINATOR
):
233 tlv_ptr
.lacp_marker_tlv_terminator
= (const struct lacp_marker_tlv_terminator_t
*)tlv_tptr
;
235 tlv_len
= sizeof(tlv_ptr
.lacp_marker_tlv_terminator
->pad
) +
236 sizeof(struct tlv_header_t
);
237 /* tell the user that we modified the length field */
239 printf(" (=%u)",tlv_len
);
240 /* we have messed around with the length field - now we need to check
241 * again if there are enough bytes on the wire for the hexdump */
242 TCHECK2(tlv_ptr
.lacp_marker_tlv_terminator
->pad
[0],
243 sizeof(tlv_ptr
.lacp_marker_tlv_terminator
->pad
));
250 print_unknown_data(tlv_tptr
,"\n\t ",tlv_tlen
);
253 /* do we want to see an additionally hexdump ? */
255 print_unknown_data(tptr
+sizeof(sizeof(struct tlv_header_t
)),"\n\t ",
256 tlv_len
-sizeof(struct tlv_header_t
));
263 printf("\n\t\t packet exceeded snapshot");