• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1998-2005 The TCPDUMP project
3  *
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.
14  *
15  * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
16  *
17  * Original code by Hannes Gredler (hannes@juniper.net)
18  */
19 
20 #ifndef lint
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 $";
23 #endif
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include <tcpdump-stdinc.h>
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "interface.h"
36 #include "extract.h"
37 #include "addrtoname.h"
38 #include "ether.h"
39 
40 struct slow_common_header {
41     u_int8_t proto_subtype;
42     u_int8_t version;
43 };
44 
45 #define	SLOW_PROTO_LACP                     1
46 #define	SLOW_PROTO_MARKER                   2
47 
48 #define	LACP_VERSION                        1
49 #define	MARKER_VERSION                      1
50 
51 static const struct tok slow_proto_values[] = {
52     { SLOW_PROTO_LACP, "LACP" },
53     { SLOW_PROTO_MARKER, "MARKER" },
54     { 0, NULL}
55 };
56 
57 struct tlv_header_t {
58     u_int8_t type;
59     u_int8_t length;
60 };
61 
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
66 
67 #define MARKER_TLV_TERMINATOR   0x00
68 #define MARKER_TLV_MARKER_INFO  0x01
69 
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"},
75 
76     { (SLOW_PROTO_MARKER << 8) + MARKER_TLV_TERMINATOR, "Terminator"},
77     { (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO, "Marker Information"},
78     { 0, NULL}
79 };
80 
81 struct lacp_tlv_actor_partner_info_t {
82     u_int8_t sys_pri[2];
83     u_int8_t sys[ETHER_ADDR_LEN];
84     u_int8_t key[2];
85     u_int8_t port_pri[2];
86     u_int8_t port[2];
87     u_int8_t state;
88     u_int8_t pad[3];
89 };
90 
91 static const struct tok lacp_tlv_actor_partner_info_state_values[] = {
92     { 0x01, "Activity"},
93     { 0x02, "Timeout"},
94     { 0x04, "Aggregation"},
95     { 0x08, "Synchronization"},
96     { 0x10, "Collecting"},
97     { 0x20, "Distributing"},
98     { 0x40, "Default"},
99     { 0x80, "Expired"},
100     { 0, NULL}
101 };
102 
103 struct lacp_tlv_collector_info_t {
104     u_int8_t max_delay[2];
105     u_int8_t pad[12];
106 };
107 
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];
112     u_int8_t pad[2];
113 };
114 
115 struct lacp_marker_tlv_terminator_t {
116     u_int8_t pad[50];
117 };
118 
119 void
slow_print(register const u_char * pptr,register u_int len)120 slow_print(register const u_char *pptr, register u_int len) {
121 
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;
126 
127     union {
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;
132     } tlv_ptr;
133 
134     tptr=pptr;
135     slow_com_header = (const struct slow_common_header *)pptr;
136     TCHECK(*slow_com_header);
137 
138     /*
139      * Sanity checking of the header.
140      */
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);
144 	return;
145     }
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);
149 	return;
150     }
151 
152     printf("%sv%u, length: %u",
153            tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype),
154            slow_com_header->version,
155            len);
156 
157     if (!vflag)
158         return;
159 
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);
163 
164     while(tlen>0) {
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;
169 
170         printf("\n\t%s TLV (0x%02x), length: %u",
171                tok2str(slow_tlv_values,
172                        "Unknown",
173                        (slow_com_header->proto_subtype << 8) + tlv_header->type),
174                tlv_header->type,
175                tlv_len);
176 
177         if ((tlv_len < sizeof(struct tlv_header_t) ||
178             tlv_len > tlen) &&
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);
183             return;
184         }
185 
186         tlv_tptr=tptr+sizeof(struct tlv_header_t);
187         tlv_tlen=tlv_len-sizeof(struct tlv_header_t);
188 
189         /* did we capture enough for fully decoding the tlv ? */
190         TCHECK2(*tptr, tlv_len);
191 
192         switch((slow_com_header->proto_subtype << 8) + tlv_header->type) {
193 
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;
198 
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,
207                               "none",
208                               tlv_ptr.lacp_tlv_actor_partner_info->state));
209 
210             break;
211 
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;
214 
215             printf("\n\t  Max Delay %u",
216                    EXTRACT_16BITS(tlv_ptr.lacp_tlv_collector_info->max_delay));
217 
218             break;
219 
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;
222 
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));
227 
228             break;
229 
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;
234             if (tlv_len == 0) {
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  */
238                 if (vflag>1)
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));
244             }
245 
246             break;
247 
248         default:
249             if (vflag <= 1)
250                 print_unknown_data(tlv_tptr,"\n\t  ",tlv_tlen);
251             break;
252         }
253         /* do we want to see an additionally hexdump ? */
254         if (vflag > 1)
255             print_unknown_data(tptr+sizeof(sizeof(struct tlv_header_t)),"\n\t  ",
256                                tlv_len-sizeof(struct tlv_header_t));
257 
258         tptr+=tlv_len;
259         tlen-=tlv_len;
260     }
261     return;
262 trunc:
263     printf("\n\t\t packet exceeded snapshot");
264 }
265