Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / tcpdump / print-slow.c
blobe2788990d15e4946dc996f3dd0281ce18fcea108
1 /* $NetBSD$ */
3 /*
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>
23 #ifndef lint
24 #if 0
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";
27 #else
28 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
29 #endif
30 #endif
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <tcpdump-stdinc.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
42 #include "interface.h"
43 #include "extract.h"
44 #include "addrtoname.h"
45 #include "ether.h"
47 struct slow_common_header {
48 u_int8_t proto_subtype;
49 u_int8_t version;
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" },
61 { 0, NULL}
64 struct tlv_header_t {
65 u_int8_t type;
66 u_int8_t length;
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"},
85 { 0, NULL}
88 struct lacp_tlv_actor_partner_info_t {
89 u_int8_t sys_pri[2];
90 u_int8_t sys[ETHER_ADDR_LEN];
91 u_int8_t key[2];
92 u_int8_t port_pri[2];
93 u_int8_t port[2];
94 u_int8_t state;
95 u_int8_t pad[3];
96 };
98 static const struct tok lacp_tlv_actor_partner_info_state_values[] = {
99 { 0x01, "Activity"},
100 { 0x02, "Timeout"},
101 { 0x04, "Aggregation"},
102 { 0x08, "Synchronization"},
103 { 0x10, "Collecting"},
104 { 0x20, "Distributing"},
105 { 0x40, "Default"},
106 { 0x80, "Expired"},
107 { 0, NULL}
110 struct lacp_tlv_collector_info_t {
111 u_int8_t max_delay[2];
112 u_int8_t pad[12];
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];
119 u_int8_t pad[2];
122 struct lacp_marker_tlv_terminator_t {
123 u_int8_t pad[50];
126 void
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;
134 union {
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;
139 } tlv_ptr;
141 tptr=pptr;
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);
151 return;
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);
156 return;
159 printf("%sv%u, length: %u",
160 tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype),
161 slow_com_header->version,
162 len);
164 if (!vflag)
165 return;
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);
171 while(tlen>0) {
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,
179 "Unknown",
180 (slow_com_header->proto_subtype << 8) + tlv_header->type),
181 tlv_header->type,
182 tlv_len);
184 if ((tlv_len < sizeof(struct tlv_header_t) ||
185 tlv_len > tlen) &&
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);
190 return;
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,
214 "none",
215 tlv_ptr.lacp_tlv_actor_partner_info->state));
217 break;
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));
225 break;
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));
235 break;
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;
241 if (tlv_len == 0) {
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 */
245 if (vflag>1)
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));
253 break;
255 default:
256 if (vflag <= 1)
257 print_unknown_data(tlv_tptr,"\n\t ",tlv_tlen);
258 break;
260 /* do we want to see an additionally hexdump ? */
261 if (vflag > 1)
262 print_unknown_data(tptr+sizeof(sizeof(struct tlv_header_t)),"\n\t ",
263 tlv_len-sizeof(struct tlv_header_t));
265 tptr+=tlv_len;
266 tlen-=tlv_len;
268 return;
269 trunc:
270 printf("\n\t\t packet exceeded snapshot");