summaryrefslogtreecommitdiffstats
path: root/contrib/tcpdump/print-slow.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2006-09-04 20:04:42 +0000
committersam <sam@FreeBSD.org>2006-09-04 20:04:42 +0000
commit498672d44881880f8839eb7839500652b77e08b9 (patch)
tree13652f8bd7a5a6bc4657d530dd6ddfbeef554e16 /contrib/tcpdump/print-slow.c
parent6dcc5281a5e8c0e636fcbf5736a3125dd9d14880 (diff)
downloadFreeBSD-src-498672d44881880f8839eb7839500652b77e08b9.zip
FreeBSD-src-498672d44881880f8839eb7839500652b77e08b9.tar.gz
Import of tcpdump v3.9.4
Diffstat (limited to 'contrib/tcpdump/print-slow.c')
-rw-r--r--contrib/tcpdump/print-slow.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/contrib/tcpdump/print-slow.c b/contrib/tcpdump/print-slow.c
new file mode 100644
index 0000000..9609922
--- /dev/null
+++ b/contrib/tcpdump/print-slow.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 1998-2005 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
+ *
+ * Original code by Hannes Gredler (hannes@juniper.net)
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-slow.c,v 1.1.2.1 2005/07/10 14:47:56 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "addrtoname.h"
+#include "ether.h"
+
+struct slow_common_header {
+ u_int8_t proto_subtype;
+ u_int8_t version;
+};
+
+#define SLOW_PROTO_LACP 1
+#define SLOW_PROTO_MARKER 2
+
+#define LACP_VERSION 1
+#define MARKER_VERSION 1
+
+static const struct tok slow_proto_values[] = {
+ { SLOW_PROTO_LACP, "LACP" },
+ { SLOW_PROTO_MARKER, "MARKER" },
+ { 0, NULL}
+};
+
+struct tlv_header_t {
+ u_int8_t type;
+ u_int8_t length;
+};
+
+#define LACP_TLV_TERMINATOR 0x00
+#define LACP_TLV_ACTOR_INFO 0x01
+#define LACP_TLV_PARTNER_INFO 0x02
+#define LACP_TLV_COLLECTOR_INFO 0x03
+
+#define MARKER_TLV_TERMINATOR 0x00
+#define MARKER_TLV_MARKER_INFO 0x01
+
+static const struct tok slow_tlv_values[] = {
+ { (SLOW_PROTO_LACP << 8) + LACP_TLV_TERMINATOR, "Terminator"},
+ { (SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO, "Actor Information"},
+ { (SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO, "Partner Information"},
+ { (SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO, "Collector Information"},
+
+ { (SLOW_PROTO_MARKER << 8) + MARKER_TLV_TERMINATOR, "Terminator"},
+ { (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO, "Marker Information"},
+ { 0, NULL}
+};
+
+struct lacp_tlv_actor_partner_info_t {
+ u_int8_t sys_pri[2];
+ u_int8_t sys[ETHER_ADDR_LEN];
+ u_int8_t key[2];
+ u_int8_t port_pri[2];
+ u_int8_t port[2];
+ u_int8_t state;
+ u_int8_t pad[3];
+};
+
+static const struct tok lacp_tlv_actor_partner_info_state_values[] = {
+ { 0x01, "Activity"},
+ { 0x02, "Timeout"},
+ { 0x04, "Aggregation"},
+ { 0x08, "Synchronization"},
+ { 0x10, "Collecting"},
+ { 0x20, "Distributing"},
+ { 0x40, "Default"},
+ { 0x80, "Expired"},
+ { 0, NULL}
+};
+
+struct lacp_tlv_collector_info_t {
+ u_int8_t max_delay[2];
+ u_int8_t pad[12];
+};
+
+struct marker_tlv_marker_info_t {
+ u_int8_t req_port[2];
+ u_int8_t req_sys[ETHER_ADDR_LEN];
+ u_int8_t req_trans_id[4];
+ u_int8_t pad[2];
+};
+
+struct lacp_marker_tlv_terminator_t {
+ u_int8_t pad[50];
+};
+
+void
+slow_print(register const u_char *pptr, register u_int len) {
+
+ const struct slow_common_header *slow_com_header;
+ const struct tlv_header_t *tlv_header;
+ const u_char *tptr,*tlv_tptr;
+ u_int tlv_len,tlen,tlv_tlen;
+
+ union {
+ const struct lacp_marker_tlv_terminator_t *lacp_marker_tlv_terminator;
+ const struct lacp_tlv_actor_partner_info_t *lacp_tlv_actor_partner_info;
+ const struct lacp_tlv_collector_info_t *lacp_tlv_collector_info;
+ const struct marker_tlv_marker_info_t *marker_tlv_marker_info;
+ } tlv_ptr;
+
+ tptr=pptr;
+ slow_com_header = (const struct slow_common_header *)pptr;
+ TCHECK(*slow_com_header);
+
+ /*
+ * Sanity checking of the header.
+ */
+ if (slow_com_header->proto_subtype == SLOW_PROTO_LACP &&
+ slow_com_header->version != LACP_VERSION) {
+ printf("LACP version %u packet not supported",slow_com_header->version);
+ return;
+ }
+ if (slow_com_header->proto_subtype == SLOW_PROTO_MARKER &&
+ slow_com_header->version != MARKER_VERSION) {
+ printf("MARKER version %u packet not supported",slow_com_header->version);
+ return;
+ }
+
+ printf("%sv%u, length: %u",
+ tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype),
+ slow_com_header->version,
+ len);
+
+ if (!vflag)
+ return;
+
+ /* ok they seem to want to know everything - lets fully decode it */
+ tlen=len-sizeof(struct slow_common_header);
+ tptr+=sizeof(const struct slow_common_header);
+
+ while(tlen>0) {
+ /* did we capture enough for fully decoding the tlv header ? */
+ TCHECK2(*tptr, sizeof(struct tlv_header_t));
+ tlv_header = (const struct tlv_header_t *)tptr;
+ tlv_len = tlv_header->length;
+
+ printf("\n\t%s TLV (0x%02x), length: %u",
+ tok2str(slow_tlv_values,
+ "Unknown",
+ (slow_com_header->proto_subtype << 8) + tlv_header->type),
+ tlv_header->type,
+ tlv_len);
+
+ if ((tlv_len < sizeof(struct tlv_header_t) ||
+ tlv_len > tlen) &&
+ tlv_header->type != LACP_TLV_TERMINATOR &&
+ tlv_header->type != MARKER_TLV_TERMINATOR) {
+ printf("\n\t-----trailing data-----");
+ print_unknown_data(tptr+sizeof(sizeof(struct tlv_header_t)),"\n\t ",tlen);
+ return;
+ }
+
+ tlv_tptr=tptr+sizeof(struct tlv_header_t);
+ tlv_tlen=tlv_len-sizeof(struct tlv_header_t);
+
+ /* did we capture enough for fully decoding the tlv ? */
+ TCHECK2(*tptr, tlv_len);
+
+ switch((slow_com_header->proto_subtype << 8) + tlv_header->type) {
+
+ /* those two TLVs have the same structure -> fall through */
+ case ((SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO):
+ case ((SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO):
+ tlv_ptr.lacp_tlv_actor_partner_info = (const struct lacp_tlv_actor_partner_info_t *)tlv_tptr;
+
+ printf("\n\t System %s, System Priority %u, Key %u" \
+ ", Port %u, Port Priority %u\n\t State Flags [%s]",
+ etheraddr_string(tlv_ptr.lacp_tlv_actor_partner_info->sys),
+ EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->sys_pri),
+ EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->key),
+ EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->port),
+ EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->port_pri),
+ bittok2str(lacp_tlv_actor_partner_info_state_values,
+ "none",
+ tlv_ptr.lacp_tlv_actor_partner_info->state));
+
+ break;
+
+ case ((SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO):
+ tlv_ptr.lacp_tlv_collector_info = (const struct lacp_tlv_collector_info_t *)tlv_tptr;
+
+ printf("\n\t Max Delay %u",
+ EXTRACT_16BITS(tlv_ptr.lacp_tlv_collector_info->max_delay));
+
+ break;
+
+ case ((SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO):
+ tlv_ptr.marker_tlv_marker_info = (const struct marker_tlv_marker_info_t *)tlv_tptr;
+
+ printf("\n\t Request System %s, Request Port %u, Request Transaction ID 0x%08x",
+ etheraddr_string(tlv_ptr.marker_tlv_marker_info->req_sys),
+ EXTRACT_16BITS(tlv_ptr.marker_tlv_marker_info->req_port),
+ EXTRACT_32BITS(tlv_ptr.marker_tlv_marker_info->req_trans_id));
+
+ break;
+
+ /* those two TLVs have the same structure -> fall through */
+ case ((SLOW_PROTO_LACP << 8) + LACP_TLV_TERMINATOR):
+ case ((SLOW_PROTO_MARKER << 8) + LACP_TLV_TERMINATOR):
+ tlv_ptr.lacp_marker_tlv_terminator = (const struct lacp_marker_tlv_terminator_t *)tlv_tptr;
+ if (tlv_len == 0) {
+ tlv_len = sizeof(tlv_ptr.lacp_marker_tlv_terminator->pad) +
+ sizeof(struct tlv_header_t);
+ /* tell the user that we modified the length field */
+ if (vflag>1)
+ printf(" (=%u)",tlv_len);
+ /* we have messed around with the length field - now we need to check
+ * again if there are enough bytes on the wire for the hexdump */
+ TCHECK2(tlv_ptr.lacp_marker_tlv_terminator->pad[0],
+ sizeof(tlv_ptr.lacp_marker_tlv_terminator->pad));
+ }
+
+ break;
+
+ default:
+ if (vflag <= 1)
+ print_unknown_data(tlv_tptr,"\n\t ",tlv_tlen);
+ break;
+ }
+ /* do we want to see an additionally hexdump ? */
+ if (vflag > 1)
+ print_unknown_data(tptr+sizeof(sizeof(struct tlv_header_t)),"\n\t ",
+ tlv_len-sizeof(struct tlv_header_t));
+
+ tptr+=tlv_len;
+ tlen-=tlv_len;
+ }
+ return;
+trunc:
+ printf("\n\t\t packet exceeded snapshot");
+}
OpenPOWER on IntegriCloud