]> The Tcpdump Group git mirrors - tcpdump/commitdiff
From Paul S. Traina: FreeBSD's Frame Relay printer.
authorguy <guy>
Thu, 11 Jul 2002 08:09:45 +0000 (08:09 +0000)
committerguy <guy>
Thu, 11 Jul 2002 08:09:45 +0000 (08:09 +0000)
Make the code to print a SNAP-encapsulated packet a separate routine,
for use by the Frame Relay code.

CREDITS
FILES
Makefile.in
interface.h
print-fr.c [new file with mode: 0644]
print-llc.c
tcpdump.c

diff --git a/CREDITS b/CREDITS
index 0179c951881f519d54eb74f8c4e4136440c171bf..0b18ea3a98682259535c0e42207c32f10d549f1f 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -73,6 +73,7 @@ Additional people who have contributed patches:
        Onno van der Linden             <[email protected]>
        Pascal Hennequin                <[email protected]>
        Pasvorn Boonmark                <[email protected]>
+       Paul S. Traina                  <[email protected]>
        Pekka Savola                    <[email protected]>     
        Peter Jeremy                    <[email protected]>
        Phil Wood                       <[email protected]>
diff --git a/FILES b/FILES
index bac3414d8ea68276b89a6bdd3dc74aed1e1b850a..8fcee549d5f758e1fc05e158d0cd4c02ef490334 100644 (file)
--- a/FILES
+++ b/FILES
@@ -99,6 +99,7 @@ print-egp.c
 print-esp.c
 print-ether.c
 print-fddi.c
+print-fr.c
 print-frag6.c
 print-gre.c
 print-hsrp.c
index c485eff4e8ef296a84f039c2a9768bc68f12bb35..4e67524021a2c7fdac05b4b1e4918ca75f62a21f 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.263 2002-07-06 18:49:36 fenner Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.264 2002-07-11 08:09:46 guy Exp $ (LBL)
 
 #
 # Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -71,16 +71,16 @@ CSRC =      addrtoname.c gmt2local.c machdep.c parsenfsfh.c \
        print-bootp.c print-beep.c print-cdp.c print-chdlc.c \
        print-cip.c print-cnfp.c print-decnet.c print-domain.c \
        print-dvmrp.c print-egp.c print-esp.c print-ether.c \
-       print-fddi.c print-gre.c print-hsrp.c print-icmp.c \
-       print-igmp.c print-igrp.c print-ip.c print-ipcomp.c \
-       print-ipx.c print-isakmp.c print-isoclns.c print-krb.c \
-       print-l2tp.c print-lane.c print-lcp.c print-llc.c print-lwres.c \
-       print-msdp.c print-mobile.c print-mpls.c print-nfs.c \
-       print-ntp.c print-null.c print-ospf.c print-pflog.c \
-       print-pim.c print-ppp.c print-pppoe.c print-pptp.c \
-       print-radius.c print-raw.c print-rip.c print-rx.c \
-       print-sctp.c print-sl.c print-sll.c print-snmp.c \
-       print-stp.c print-sunrpc.c print-tcp.c \
+       print-fddi.c print-fr.c print-gre.c print-hsrp.c \
+       print-icmp.c print-igmp.c print-igrp.c print-ip.c \
+       print-ipcomp.c print-ipx.c print-isakmp.c print-isoclns.c \
+       print-krb.c print-l2tp.c print-lane.c print-lcp.c \
+       print-llc.c print-lwres.c print-msdp.c print-mobile.c \
+       print-mpls.c print-nfs.c print-ntp.c print-null.c \
+       print-ospf.c print-pflog.c print-pim.c print-ppp.c \
+       print-pppoe.c print-pptp.c print-radius.c print-raw.c \
+       print-rip.c print-rx.c print-sctp.c print-sl.c print-sll.c \
+       print-snmp.c print-stp.c print-sunrpc.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 c94612cc67c2830a5d368758d7ca6edf8afbc811..56d507d99a947e60cbe5d3da8d21259a1fceed44 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.187 2002-06-27 08:21:40 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.188 2002-07-11 08:09:46 guy Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -197,6 +197,8 @@ extern void hex_print(const u_char *, u_int);
 extern int ether_encap_print(u_short, const u_char *, u_int, u_int, u_short *);
 extern int llc_print(const u_char *, u_int, u_int, const u_char *,
        const u_char *, u_short *);
+extern int snap_print(const u_char *, u_int, u_int, const u_char *,
+       const u_char *, u_short *, u_int32_t, u_short);
 extern void aarp_print(const u_char *, u_int);
 extern void arp_print(const u_char *, u_int, u_int);
 extern void atalk_print(const u_char *, u_int);
@@ -222,6 +224,7 @@ extern void token_if_print(u_char *, const struct pcap_pkthdr *,
        const u_char *);
 extern void fddi_print(const u_char *, u_int, u_int);
 extern void fddi_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
+extern void fr_if_print(u_char *, const struct pcap_pkthdr *, const u_char *);
 extern void ieee802_11_if_print(u_char *, const struct pcap_pkthdr *,
        const u_char *);
 extern void gre_print(const u_char *, u_int);
diff --git a/print-fr.c b/print-fr.c
new file mode 100644 (file)
index 0000000..cdd4906
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * 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, (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, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * 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.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+       "@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.1 2002-07-11 08:09:47 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+struct mbuf;
+struct rtentry;
+
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <pcap.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ethertype.h"
+#include "extract.h"
+
+static void q933_print(const u_char *, int);
+
+#define FR_CR_BIT      0x02
+#define FR_EA_BIT(p)   ((p)&0x01)
+#define FR_FECN                0x08
+#define FR_BECN                0x04
+#define FR_DE          0x02
+#define FR_DLCI(b0, b1)        ((((b0)&0xFC)<<2)+(((b1)&0xF0)>>4))
+
+/* find out how many bytes are there in a frame */
+static int
+fr_addr_len(const u_char *p)
+{
+       int i=0;
+       
+       while (!FR_EA_BIT(p[i]) && i++ && !FR_EA_BIT(p[i+1])) i++;
+       return (i+1);
+}
+
+/* the following is for framerelay */
+#define NLPID_LEN      1       /* NLPID is one byte long */
+#define NLPID_Q933      0x08
+#define NLPID_LMI       0x09
+#define NLPID_SNAP      0x80
+#define NLPID_CLNP      0x81
+#define NLPID_ESIS      0x82
+#define NLPID_ISIS      0x83
+#define NLPID_CONS      0x84
+#define NLPID_IDRP      0x85
+#define NLPID_X25_ESIS  0x8a
+#define NLPID_IP        0xcc
+
+
+static const char *fr_nlpids[256];
+
+static void
+init_fr_nlpids(void)
+{
+       int i;
+       static int fr_nlpid_flag = 0;
+
+       if (!fr_nlpid_flag) {
+               for (i=0; i < 256; i++)
+                       fr_nlpids[i] = NULL;
+               fr_nlpids[NLPID_Q933] = "Q.933";
+               fr_nlpids[NLPID_LMI] = "LMI";
+               fr_nlpids[NLPID_SNAP] = "SNAP";
+               fr_nlpids[NLPID_CLNP] = "CLNP";
+               fr_nlpids[NLPID_ESIS] = "ESIS";
+               fr_nlpids[NLPID_ISIS] = "ISIS";
+               fr_nlpids[NLPID_CONS] = "CONS";
+               fr_nlpids[NLPID_IDRP] = "IDRP";
+               fr_nlpids[NLPID_X25_ESIS] = "X25_ESIS";
+               fr_nlpids[NLPID_IP] = "IP";
+       }
+       fr_nlpid_flag = 1;
+}
+
+/* Framerelay packet structure */
+
+/*
+                  +---------------------------+
+                  |    flag (7E hexadecimal)  |
+                  +---------------------------+
+                  |       Q.922 Address*      |
+                  +--                       --+
+                  |                           |
+                  +---------------------------+
+                  | Control (UI = 0x03)       |
+                  +---------------------------+
+                  | Optional Pad      (0x00)  |
+                  +---------------------------+
+                  | NLPID                     |
+                  +---------------------------+
+                  |             .             |
+                  |             .             |
+                  |             .             |
+                  |           Data            |
+                  |             .             |
+                  |             .             |
+                  +---------------------------+
+                  |   Frame Check Sequence    |
+                  +--           .           --+
+                  |       (two octets)        |
+                  +---------------------------+
+                  |   flag (7E hexadecimal)   |
+                  +---------------------------+
+
+           * Q.922 addresses, as presently defined, are two octets and
+             contain a 10-bit DLCI.  In some networks Q.922 addresses
+             may optionally be increased to three or four octets.
+
+*/
+
+#define FR_PROTOCOL(p) fr_protocol((p))
+
+static int
+fr_hdrlen(const u_char *p)
+{
+       int hlen;
+       hlen = fr_addr_len(p)+1;  /* addr_len + 0x03 + padding */
+       if (p[hlen])
+               return hlen;
+       else
+               return hlen+1;
+}
+
+#define LAYER2_LEN(p) (fr_hdrlen((p))+NLPID_LEN)
+
+static int
+fr_protocol(const u_char *p)
+{
+       int hlen;
+       
+       hlen = fr_addr_len(p) + 1;
+       if (p[hlen])  /* check for padding */
+               return p[hlen];
+       else 
+               return p[hlen+1];
+}
+
+static char *
+fr_flags(const u_char *p)
+{
+       static char flags[1+1+4+1+4+1+2+1];
+
+       if (p[0] & FR_CR_BIT)
+               strcpy(flags, "C");
+       else
+               strcpy(flags, "R");
+       if (p[1] & FR_FECN)
+               strcat(flags, ",FECN");
+       if (p[1] & FR_BECN)
+               strcat(flags, ",BECN");
+       if (p[1] & FR_DE)
+               strcat(flags, ",DE");
+       return flags;
+}
+
+static const char *
+fr_protostring(u_int8_t proto)
+{
+       static char buf[5+1+2+1];
+
+       if (nflag || fr_nlpids[proto] == NULL) {
+               sprintf(buf, "proto-%02x", proto);
+               return buf;
+       }
+       return fr_nlpids[proto];
+}
+
+static void
+fr_hdr_print(const u_char *p, int length)
+{
+       u_int8_t proto;
+
+       proto = FR_PROTOCOL(p);
+
+       init_fr_nlpids();
+       /* this is kinda kludge since it assumed that DLCI is two bytes. */
+       if (qflag)
+               (void)printf("DLCI-%u-%s %d: ",
+                            FR_DLCI(p[0], p[1]), fr_flags(p), length);
+       else
+               (void)printf("DLCI-%u-%s %s %d: ",
+                            FR_DLCI(p[0], p[1]), fr_flags(p),
+                            fr_protostring(proto), length);
+}
+
+void
+fr_if_print(u_char *user, const struct pcap_pkthdr *h,
+            register const u_char *p)
+{
+       register u_int length = h->len;
+       register u_int caplen = h->caplen;
+       u_char protocol;
+       int layer2_len;
+       u_short extracted_ethertype;
+       u_int32_t orgcode;
+       register u_short et;
+
+       ts_print(&h->ts);
+
+       if (caplen < fr_hdrlen(p)) {
+               printf("[|fr]");
+               goto out;
+       }
+
+       /*
+        * Some printers want to get back at the link level addresses,
+        * and/or check that they're not walking off the end of the packet.
+        * Rather than pass them all the way down, we set these globals.
+        */
+       packetp = p;
+       snapend = p + caplen;
+
+       if (eflag)
+               fr_hdr_print(p, length);
+
+       protocol = FR_PROTOCOL(p);
+       layer2_len = LAYER2_LEN(p);
+       p += layer2_len;
+       length -= layer2_len;
+       caplen -= layer2_len;
+
+       switch (protocol) {
+
+       case NLPID_IP:
+       case ETHERTYPE_IP:
+               ip_print(p, length);
+               break;
+
+       case NLPID_CLNP:
+       case NLPID_ESIS:
+       case NLPID_ISIS:
+               isoclns_print(p, length, caplen, NULL, NULL);
+               break;
+
+       case NLPID_SNAP:
+               orgcode = EXTRACT_24BITS(p);
+               et = EXTRACT_16BITS(p + 3);
+               if (snap_print((const u_char *)(p + 5), length - 5,
+                          caplen - 5, NULL, NULL,
+                          &extracted_ethertype, orgcode, et) == 0) {
+                       /* ether_type not known, print raw packet */
+                       if (!eflag)
+                               fr_hdr_print(p - layer2_len, length + layer2_len);
+                       if (extracted_ethertype) {
+                               printf("(SNAP %s) ",
+                              etherproto_string(htons(extracted_ethertype)));
+                       }
+                       if (!xflag && !qflag)
+                               default_print(p - layer2_len, caplen + layer2_len);
+               }
+               break;
+
+       case NLPID_Q933:
+               q933_print(p, length);
+               break;
+
+       default:
+               if (!eflag)
+                       fr_hdr_print(p - layer2_len, length + layer2_len);
+               if (!xflag)
+                       default_print(p, caplen);
+       }
+
+       if (xflag)
+               default_print(p, caplen);
+out:
+       putchar('\n');
+}
+
+/*
+ * Q.933 decoding portion for framerelay specific.
+ */
+
+/* Q.933 packet format
+                      Format of Other Protocols   
+                          using Q.933 NLPID
+                  +-------------------------------+            
+                  |        Q.922 Address          | 
+                  +---------------+---------------+
+                  |Control  0x03  | NLPID   0x08  |        
+                  +---------------+---------------+        
+                  |          L2 Protocol ID       |
+                  | octet 1       |  octet 2      |
+                  +-------------------------------+
+                  |          L3 Protocol ID       |
+                  | octet 2       |  octet 2      |
+                  +-------------------------------+
+                  |         Protocol Data         |
+                  +-------------------------------+
+                  | FCS                           |
+                  +-------------------------------+
+ */
+
+/* L2 (Octet 1)- Call Reference Usually is 0x0 */
+
+/*
+ * L2 (Octet 2)- Message Types definition 1 byte long.
+ */
+/* Call Establish */
+#define MSG_TYPE_ESC_TO_NATIONAL  0x00
+#define MSG_TYPE_ALERT            0x01
+#define MSG_TYPE_CALL_PROCEEDING  0x02
+#define MSG_TYPE_CONNECT          0x07
+#define MSG_TYPE_CONNECT_ACK      0x0F
+#define MSG_TYPE_PROGRESS         0x03
+#define MSG_TYPE_SETUP            0x05
+/* Call Clear */
+#define MSG_TYPE_DISCONNECT       0x45
+#define MSG_TYPE_RELEASE          0x4D
+#define MSG_TYPE_RELEASE_COMPLETE 0x5A
+#define MSG_TYPE_RESTART          0x46
+#define MSG_TYPE_RESTART_ACK      0x4E
+/* Status */
+#define MSG_TYPE_STATUS           0x7D
+#define MSG_TYPE_STATUS_ENQ       0x75
+
+#define ONE_BYTE_IE_MASK 0xF0
+
+/* See L2 protocol ID picture above */
+struct q933_header {
+    u_char call_ref;  /* usually is 0 for framerelay PVC */
+    u_char msg_type;  
+};
+
+#define REPORT_TYPE_IE    0x01
+#define LINK_VERIFY_IE_91 0x19
+#define LINK_VERIFY_IE_94 0x03
+#define PVC_STATUS_IE     0x07
+
+#define MAX_IE_SIZE
+
+struct common_ie_header {
+    u_char ie_id;
+    u_char ie_len;
+};
+
+#define FULL_STATUS 0
+#define LINK_VERIFY 1
+#define ASYNC_PVC   2
+
+static void
+q933_print(const u_char *p, int length)
+{
+       struct q933_header *header = (struct q933_header *)(p+1);
+       const u_char *ptemp = p;
+       int ie_len;
+       char *decode_str, temp_str[255];
+       struct common_ie_header *ie_p;
+    
+       /* printing out header part */
+       printf("Call Ref: %02x, MSG Type: %02x", 
+              header->call_ref, header->msg_type);
+       switch(header->msg_type) {
+       case MSG_TYPE_STATUS:
+           decode_str = "STATUS REPLY";
+           break;
+       case MSG_TYPE_STATUS_ENQ:
+           decode_str = "STATUS ENQUIRY";
+           break;
+       default:
+           decode_str = "UNKNOWN MSG Type";
+       }
+       printf(" %s\n", decode_str);
+
+       length = length - 3;
+       ptemp = ptemp + 3;
+       
+       /* Loop through the rest of IE */
+       while( length > 0 ) {
+           if (ptemp[0] & ONE_BYTE_IE_MASK) {
+               ie_len = 1;
+               printf("\t\tOne byte IE: %02x, Content %02x\n", 
+                      (*ptemp & 0x70)>>4, (*ptemp & 0x0F));
+               length--;
+               ptemp++;
+           }
+           else {  /* Multi-byte IE */
+               ie_p = (struct common_ie_header *)ptemp;
+               switch (ie_p->ie_id) {
+               case REPORT_TYPE_IE:
+                   switch(ptemp[2]) {
+                   case FULL_STATUS:
+                       decode_str = "FULL STATUS";
+                       break;
+                   case LINK_VERIFY:
+                       decode_str = "LINK VERIFY";
+                       break;
+                   case ASYNC_PVC:
+                       decode_str = "Async PVC Status";
+                       break;
+                   default:
+                       decode_str = "Reserved Value";
+                   }
+                   break;
+               case LINK_VERIFY_IE_91:
+               case LINK_VERIFY_IE_94:
+                   snprintf(temp_str, sizeof (temp_str), "TX Seq: %3d, RX Seq: %3d",
+                           ptemp[2], ptemp[3]);
+                   decode_str = temp_str;
+                   break;
+               case PVC_STATUS_IE:
+                   snprintf(temp_str, sizeof (temp_str), "DLCI %d: status %s %s",
+                           ((ptemp[2]&0x3f)<<4)+ ((ptemp[3]&0x78)>>3), 
+                           ptemp[4] & 0x8 ?"new,":" ",
+                           ptemp[4] & 0x2 ?"Active":"Inactive");
+                   break;
+               default:
+                   decode_str = "Non-decoded Value";               
+               }
+               printf("\t\tIE: %02X Len: %d, %s\n",
+                      ie_p->ie_id, ie_p->ie_len, decode_str);
+               length = length - ie_p->ie_len - 2;
+               ptemp = ptemp + ie_p->ie_len + 2;
+           }
+       }
+}
index d36dd570b04e5e0ea116c6b5e9b53802ecdfe81b..14c30064195d3ffeaaeeb382fdff945caf69b871 100644 (file)
@@ -24,7 +24,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.45 2002-04-07 09:50:33 guy Exp $";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.46 2002-07-11 08:09:47 guy Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -193,112 +193,10 @@ llc_print(const u_char *p, u_int length, u_int caplen,
 
                orgcode = EXTRACT_24BITS(&llc.llc_orgcode[0]);
                et = EXTRACT_16BITS(&llc.llc_ethertype[0]);
-               switch (orgcode) {
-               case OUI_ENCAP_ETHER:
-               case OUI_CISCO_90:
-                       /*
-                        * This is an encapsulated Ethernet packet,
-                        * or a packet bridged by some piece of
-                        * Cisco hardware; the protocol ID is
-                        * an Ethernet protocol type.
-                        */
-                       ret = ether_encap_print(et, p, length, caplen,
-                           extracted_ethertype);
-                       if (ret)
-                               return (ret);
-                       break;
-
-               case OUI_APPLETALK:
-                       if (et == ETHERTYPE_ATALK) {
-                               /*
-                                * No, I have no idea why Apple used one
-                                * of their own OUIs, rather than
-                                * 0x000000, and an Ethernet packet
-                                * type, for Appletalk data packets,
-                                * but used 0x000000 and an Ethernet
-                                * packet type for AARP packets.
-                                */
-                               ret = ether_encap_print(et, p, length, caplen,
-                                   extracted_ethertype);
-                               if (ret)
-                                       return (ret);
-                       }
-                       break;
-
-               case OUI_CISCO:
-                       if (et == PID_CISCO_CDP) {
-                               cdp_print(p, length, caplen, esrc, edst);
-                               return 1;
-                       }
-                       break;
-
-               case OUI_RFC2684:
-                       switch (et) {
-
-                       case PID_RFC2684_ETH_FCS:
-                       case PID_RFC2684_ETH_NOFCS:
-                               /*
-                                * XXX - remove the last two bytes for
-                                * PID_RFC2684_ETH_FCS?
-                                */
-                               /*
-                                * Skip the padding.
-                                */
-                               caplen -= 2;
-                               length -= 2;
-                               p += 2;
-
-                               /*
-                                * What remains is an Ethernet packet.
-                                */
-                               ether_print(p, length, caplen);
-                               return (1);
-
-                       case PID_RFC2684_802_5_FCS:
-                       case PID_RFC2684_802_5_NOFCS:
-                               /*
-                                * XXX - remove the last two bytes for
-                                * PID_RFC2684_ETH_FCS?
-                                */
-                               /*
-                                * Skip the padding, but not the Access
-                                * Control field.
-                                */
-                               caplen -= 2;
-                               length -= 2;
-                               p += 2;
-
-                               /*
-                                * What remains is an 802.5 Token Ring
-                                * packet.
-                                */
-                               token_print(p, length, caplen);
-                               return (1);
-
-                       case PID_RFC2684_FDDI_FCS:
-                       case PID_RFC2684_FDDI_NOFCS:
-                               /*
-                                * XXX - remove the last two bytes for
-                                * PID_RFC2684_ETH_FCS?
-                                */
-                               /*
-                                * Skip the padding.
-                                */
-                               caplen -= 3;
-                               length -= 3;
-                               p += 3;
-
-                               /*
-                                * What remains is an FDDI packet.
-                                */
-                               fddi_print(p, length, caplen);
-                               return (1);
-
-                       case PID_RFC2684_BPDU:
-                               stp_print(p, length);
-                               return (1);
-                       }
-               }
+               ret = snap_print(p, length, caplen, esrc, edst,
+                   extracted_ethertype, orgcode, et);
+               if (ret)
+                       return (ret);
        }
 
        if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
@@ -385,3 +283,119 @@ llc_print(const u_char *p, u_int length, u_int caplen,
        (void)printf(" len=%d", length);
        return(1);
 }
+
+int
+snap_print(const u_char *p, u_int length, u_int caplen,
+    const u_char *esrc, const u_char *edst, u_short *extracted_ethertype,
+    u_int32_t orgcode, u_short et)
+{
+       register int ret;
+
+       switch (orgcode) {
+       case OUI_ENCAP_ETHER:
+       case OUI_CISCO_90:
+               /*
+                * This is an encapsulated Ethernet packet,
+                * or a packet bridged by some piece of
+                * Cisco hardware; the protocol ID is
+                * an Ethernet protocol type.
+                */
+               ret = ether_encap_print(et, p, length, caplen,
+                   extracted_ethertype);
+               if (ret)
+                       return (ret);
+               break;
+
+       case OUI_APPLETALK:
+               if (et == ETHERTYPE_ATALK) {
+                       /*
+                        * No, I have no idea why Apple used one
+                        * of their own OUIs, rather than
+                        * 0x000000, and an Ethernet packet
+                        * type, for Appletalk data packets,
+                        * but used 0x000000 and an Ethernet
+                        * packet type for AARP packets.
+                        */
+                       ret = ether_encap_print(et, p, length, caplen,
+                           extracted_ethertype);
+                       if (ret)
+                               return (ret);
+               }
+               break;
+
+       case OUI_CISCO:
+               if (et == PID_CISCO_CDP) {
+                       cdp_print(p, length, caplen, esrc, edst);
+                       return (1);
+               }
+               break;
+
+       case OUI_RFC2684:
+               switch (et) {
+
+               case PID_RFC2684_ETH_FCS:
+               case PID_RFC2684_ETH_NOFCS:
+                       /*
+                        * XXX - remove the last two bytes for
+                        * PID_RFC2684_ETH_FCS?
+                        */
+                       /*
+                        * Skip the padding.
+                        */
+                       caplen -= 2;
+                       length -= 2;
+                       p += 2;
+
+                       /*
+                        * What remains is an Ethernet packet.
+                        */
+                       ether_print(p, length, caplen);
+                       return (1);
+
+               case PID_RFC2684_802_5_FCS:
+               case PID_RFC2684_802_5_NOFCS:
+                       /*
+                        * XXX - remove the last two bytes for
+                        * PID_RFC2684_ETH_FCS?
+                        */
+                       /*
+                        * Skip the padding, but not the Access
+                        * Control field.
+                        */
+                       caplen -= 2;
+                       length -= 2;
+                       p += 2;
+
+                       /*
+                        * What remains is an 802.5 Token Ring
+                        * packet.
+                        */
+                       token_print(p, length, caplen);
+                       return (1);
+
+               case PID_RFC2684_FDDI_FCS:
+               case PID_RFC2684_FDDI_NOFCS:
+                       /*
+                        * XXX - remove the last two bytes for
+                        * PID_RFC2684_ETH_FCS?
+                        */
+                       /*
+                        * Skip the padding.
+                        */
+                       caplen -= 3;
+                       length -= 3;
+                       p += 3;
+
+                       /*
+                        * What remains is an FDDI packet.
+                        */
+                       fddi_print(p, length, caplen);
+                       return (1);
+
+               case PID_RFC2684_BPDU:
+                       stp_print(p, length);
+                       return (1);
+               }
+       }
+       return (0);
+}
index 6becb9b3dd6fa154f44ee42d014eeec9c2a7fafb..30fdce8b60feaca67c45f194bd7899b15edadae6 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -30,7 +30,7 @@ static const char copyright[] =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
 The Regents of the University of California.  All rights reserved.\n";
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.177 2002-06-11 17:09:00 itojun Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.178 2002-07-11 08:09:47 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -161,6 +161,12 @@ static struct printer printers[] = {
 #endif
 #ifdef DLT_PFLOG
        { pflog_if_print,       DLT_PFLOG },
+#endif
+#ifdef DLT_FR
+       { fr_if_print,          DLT_FR },
+#endif
+#ifdef DLT_FRELAY
+       { fr_if_print,          DLT_FRELAY },
 #endif
        { NULL,                 0 },
 };