]> The Tcpdump Group git mirrors - tcpdump/commitdiff
add support for the IEEE slow protocols LACP, MARKER as per 802.3ad
authorhannes <hannes>
Sun, 10 Jul 2005 14:41:34 +0000 (14:41 +0000)
committerhannes <hannes>
Sun, 10 Jul 2005 14:41:34 +0000 (14:41 +0000)
FILES
Makefile.in
ethertype.h
interface.h
print-ether.c
print-slow.c [new file with mode: 0644]

diff --git a/FILES b/FILES
index ebd02cbd7a71e6a9e75e5d1264890b610de3d6d5..73e2919762ee633d1e1d6c5a8641d880c76b1627 100644 (file)
--- a/FILES
+++ b/FILES
@@ -188,6 +188,7 @@ print-sctp.c
 print-sip.c
 print-sl.c
 print-sll.c
+print-slow.c
 print-smb.c
 print-snmp.c
 print-stp.c
index edd83280ae88138f491ce99c528f2eda339cb51a..9cdf409864f4b493120a7d94904b91f3109128b9 100644 (file)
@@ -17,7 +17,7 @@
 #  WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 #  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 #
-# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.294 2005-05-20 21:02:29 hannes Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.295 2005-07-10 14:44:50 hannes Exp $ (LBL)
 
 #
 # Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -84,7 +84,7 @@ CSRC =        addrtoname.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c \
        print-pflog.c print-pgm.c print-pim.c print-ppp.c print-pppoe.c \
        print-pptp.c print-radius.c print-raw.c print-rip.c \
        print-rsvp.c print-rx.c print-sctp.c print-sip.c print-sl.c print-sll.c \
-       print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
+       print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
        print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \
        print-timed.c print-token.c print-udp.c print-vjc.c print-vrrp.c \
        print-wb.c print-zephyr.c setsignal.c tcpdump.c util.c
index 6e93be9fb5d9e06619818c11545d10e215d2018a..4f85202b292588d7c2aba78219c1d69ab4faaab9 100644 (file)
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/ethertype.h,v 1.24 2004-10-07 16:04:07 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/ethertype.h,v 1.25 2005-07-10 14:49:48 hannes Exp $ (LBL)
  */
 
 /*
 #ifndef ETHERTYPE_PPP
 #define        ETHERTYPE_PPP           0x880b
 #endif
+#ifndef ETHERTYPE_SLOW
+#define        ETHERTYPE_SLOW          0x8809
+#endif
 #ifndef        ETHERTYPE_MPLS
 #define        ETHERTYPE_MPLS          0x8847
 #endif
index 66639b0697ebc9cb112d523dfabfa06f906760d2..605c8a46cc597b862cfa8fe10b7af9cba20aae01 100644 (file)
@@ -18,7 +18,7 @@
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.257 2005-07-07 01:22:15 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.258 2005-07-10 14:41:35 hannes Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -285,6 +285,7 @@ extern const char *nt_errstr(u_int32_t);
 extern void print_data(const unsigned char *, int);
 extern void l2tp_print(const u_char *, u_int);
 extern void vrrp_print(const u_char *, u_int, int);
+extern void slow_print(const u_char *, u_int);
 extern void pgm_print(const u_char *, u_int, const u_char *);
 extern void cdp_print(const u_char *, u_int, u_int);
 extern void stp_print(const u_char *, u_int);
index ace88877a01ecd3f268d0b576b33b5712a181b67..13c06174fa1931f8b2056936bd77926c0be0e847 100644 (file)
@@ -20,7 +20,7 @@
  */
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.98 2005-07-07 01:22:17 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.99 2005-07-10 14:41:34 hannes Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -65,6 +65,7 @@ const struct tok ethertype_values[] = {
     { ETHERTYPE_AARP,           "Appletalk ARP" },
     { ETHERTYPE_IPX,            "IPX" },
     { ETHERTYPE_PPP,            "PPP" },
+    { ETHERTYPE_SLOW,           "Slow Protocols" },
     { ETHERTYPE_PPPOED,         "PPPoE D" },
     { ETHERTYPE_PPPOES,         "PPPoE S" },
     { ETHERTYPE_EAPOL,          "EAPOL" },
@@ -295,6 +296,10 @@ ether_encap_print(u_short ether_type, const u_char *p,
                }
                return (1);
 
+       case ETHERTYPE_SLOW:
+               slow_print(p, length);
+               return (1);
+
         case ETHERTYPE_LOOPBACK:
                 return (1);
 
diff --git a/print-slow.c b/print-slow.c
new file mode 100644 (file)
index 0000000..4038b9e
--- /dev/null
@@ -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 ([email protected])
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/tcpdump/print-slow.c,v 1.1 2005-07-10 14:41:34 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");
+}