• 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