]> The Tcpdump Group git mirrors - tcpdump/commitdiff
IEEE 802.11 support, from Charlie Lenahan <[email protected]>.
authorguy <guy>
Tue, 12 Jun 2001 05:17:16 +0000 (05:17 +0000)
committerguy <guy>
Tue, 12 Jun 2001 05:17:16 +0000 (05:17 +0000)
CREDITS
FILES
Makefile.in
ieee802_11.h [new file with mode: 0644]
interface.h
print-802_11.c [new file with mode: 0644]
tcpdump.c

diff --git a/CREDITS b/CREDITS
index 00553e469d6bbe4cd86fdd19c9f912d48bd6a093..1a5409f93ca2f1f05267b7f8eaf99bebcd3cde6b 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -16,6 +16,7 @@ Additional people who have contributed patches:
        Andrew Tridgell                 <[email protected]>
        Arkadiusz Miskiewicz            <[email protected]>
        Armando L. Caro Jr.             <[email protected]>
+       Charlie Lenahan                 <[email protected]>
        Chris G. Demetriou              <[email protected]>
        Craig Rodrigues                 <[email protected]>
        Daniel Hagerty                  <[email protected]>
diff --git a/FILES b/FILES
index e0f2663531748a0e3cb3bbbea723872855303ab2..c6bd8f86d597acf457220b26553ad1a40e5f3745 100644 (file)
--- a/FILES
+++ b/FILES
@@ -31,6 +31,7 @@ extract.h
 fddi.h
 gmt2local.c
 gmt2local.h
+ieee802_11.h
 igrp.h
 install-sh
 interface.h
@@ -75,6 +76,7 @@ ospf6.h
 packetdat.awk
 parsenfsfh.c
 ppp.h
+print-802_11.c
 print-ah.c
 print-arcnet.c
 print-arp.c
index d5a9454c77db3c90aebef5a84c99c58c2b6f8272..af3bcced5ff12a4e42f3b88d9937168e13abf54b 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.250 2001-05-09 01:25:55 fenner Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.251 2001-06-12 05:17:16 guy Exp $ (LBL)
 
 #
 # Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -66,22 +66,22 @@ INSTALL_DATA = @INSTALL_DATA@
        $(CC) $(CFLAGS) -c $(srcdir)/$*.c
 
 CSRC = addrtoname.c gmt2local.c machdep.c parsenfsfh.c \
-       print-ah.c print-arcnet.c print-arp.c print-ascii.c \
-       print-atalk.c print-atm.c print-bgp.c print-bootp.c \
-       print-bxxp.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-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-mobile.c \
-       print-nfs.c print-ntp.c print-null.c print-ospf.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-smb.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-802_11.c print-ah.c print-arcnet.c print-arp.c \
+       print-ascii.c print-atalk.c print-atm.c print-bgp.c \
+       print-bootp.c print-bxxp.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-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-mobile.c print-nfs.c print-ntp.c print-null.c \
+       print-ospf.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-smb.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 \
        setsignal.c smbutil.c tcpdump.c util.c
 
 LOCALSRC = @LOCALSRC@
diff --git a/ieee802_11.h b/ieee802_11.h
new file mode 100644 (file)
index 0000000..4bbebe0
--- /dev/null
@@ -0,0 +1,230 @@
+/* @(#) $Header: /tcpdump/master/tcpdump/ieee802_11.h,v 1.1 2001-06-12 05:17:17 guy Exp $ (LBL) */
+/*
+ * Copyright (c) 2001
+ *     Fortress Technologies
+ *      Charlie Lenahan ( [email protected] )
+ *
+ * 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.
+ */
+
+#define IEEE802_11_FC_LEN      2
+
+#define T_MGMT 0x0  /* management */
+#define T_CTRL 0x1  /* control */
+#define T_DATA 0x2 /* data */
+#define T_RESV 0x3  /* reserved */
+
+#define ST_ASSOC_REQUEST       0x0 
+#define ST_ASSOC_RESPONSE      0x1 
+#define ST_REASSOC_REQUEST     0x2 
+#define ST_REASSOC_RESPONSE    0x3 
+#define ST_PROBE_REQUEST       0x4 
+#define ST_PROBE_RESPONSE      0x5 
+/* RESERVED                    0x6  */
+/* RESERVED                    0x7  */
+#define ST_BEACON              0x8 
+#define ST_ATIM                        0x9
+#define ST_DISASSOC            0xA
+#define ST_AUTH                        0xB
+#define ST_DEAUTH              0xC
+/* RESERVED                    0xD  */
+/* RESERVED                    0xE  */
+/* RESERVED                    0xF  */
+
+
+#define CTRL_PS_POLL   0xA 
+#define CTRL_RTS       0xB
+#define CTRL_CTS       0xC
+#define CTRL_ACK       0xD
+#define CTRL_CF_END    0xE
+#define CTRL_END_ACK   0xF
+
+/*
+ * Bits in the frame control field.
+ */
+#define FC_VERSION(fc)         ((fc) & 0x3)
+#define FC_TYPE(fc)            (((fc) >> 2) & 0x3)
+#define FC_SUBTYPE(fc)         (((fc) >> 4) & 0xF)
+#define FC_TO_DS(fc)           ((fc) & 0x0100)
+#define FC_FROM_DS(fc)         ((fc) & 0x0200)
+#define FC_MORE_FLAG(fc)       ((fc) & 0x0400)
+#define FC_RETRY(fc)           ((fc) & 0x0800)
+#define FC_POWER_MGMT(fc)      ((fc) & 0x1000)
+#define FC_MORE_DATA(fc)       ((fc) & 0x2000)
+#define FC_WEP(fc)             ((fc) & 0x4000)
+#define FC_ORDER(fc)           ((fc) & 0x8000)
+
+struct mgmt_header_t {
+       u_int16_t       fc;
+       u_int16_t       duration;
+       u_int8_t        da[6];
+       u_int8_t        sa[6];
+       u_int8_t        bssid[6];
+       u_int8_t        seq_ctrl;
+};
+
+#define CAPABILITY_ESS(cap)    ((cap) & 0x0001)
+#define CAPABILITY_IBSS(cap)   ((cap) & 0x0002)
+#define CAPABILITY_CFP(cap)    ((cap) & 0x0004)
+#define CAPABILITY_CFP_REQ(cap)        ((cap) & 0x0008)
+#define CAPABILITY_PRIVACY(cap)        ((cap) & 0x0010)
+
+struct ssid_t {
+       u_int8_t        element_id;
+       u_int8_t        length;
+       u_char          ssid[33];  /* 32 + 1 for null */
+} ;
+
+struct rates_t {
+       u_int8_t        element_id;
+       u_int8_t        length;
+       u_int8_t        rate[8];
+};
+
+struct challenge_t {
+       u_int8_t        element_id;
+       u_int8_t        length;
+       u_int8_t        text[254]; /* 1-253 + 1 for null */
+};
+struct fh_t {
+       u_int8_t        element_id;
+       u_int8_t        length;
+       u_int16_t       dwell_time;
+       u_int8_t        hop_set;
+       u_int8_t        hop_pattern;
+       u_int8_t        hop_index;
+};
+
+struct ds_t {
+       u_int8_t        element_id;
+       u_int8_t        length;
+       u_int8_t        channel;
+};
+
+struct cf_t {
+       u_int8_t        element_id;
+       u_int8_t        length;
+       u_int8_t        count;
+       u_int8_t        period;
+       u_int16_t       max_duration;
+       u_int16_t       dur_remaing;
+};
+
+struct tim_t {
+       u_int8_t        element_id;
+       u_int8_t        length;
+       u_int8_t        count;
+       u_int8_t        period;
+       u_int8_t        bitmap_control;
+       u_int8_t        bitmap[251];
+};
+
+#define E_SSID                 0
+#define E_RATES        1
+#define E_FH           2
+#define E_DS           3
+#define E_CF           4
+#define E_TIM          5
+#define E_IBSS                 6
+/* reserved            7 */
+/* reserved            8 */
+/* reserved            9 */
+/* reserved            10 */
+/* reserved            11 */
+/* reserved            12 */
+/* reserved            13 */
+/* reserved            14 */
+/* reserved            15 */
+/* reserved            16 */
+
+#define E_CHALLENGE    16      
+/* reserved            17 */
+/* reserved            18 */
+/* reserved            19 */
+/* reserved            16 */
+/* reserved            16 */
+
+
+struct mgmt_body_t {
+       u_int8_t        timestamp[8];
+       u_int16_t       beacon_interval;
+       u_int16_t       listen_interval;
+       u_int16_t       status_code;
+       u_int16_t       aid;
+       u_char          ap[6];
+       u_int16_t       reason_code;
+       u_int16_t       auth_alg;
+       u_int16_t       auth_trans_seq_num;
+       struct challenge_t  challenge;
+       u_int16_t       capability_info;
+       struct ssid_t   ssid;
+       struct rates_t  rates;
+       struct ds_t     ds;
+       struct cf_t     cf;
+       struct fh_t     fh;
+       struct tim_t    tim;
+};
+
+struct ctrl_rts_t {
+       u_int16_t       fc;
+       u_int16_t       duration;
+       u_int8_t        ra[6];
+       u_int8_t        ta[6];
+       u_int32_t       fcs;
+};
+
+struct ctrl_cts_t {
+       u_int16_t       fc;
+       u_int16_t       duration;
+       u_int8_t        ra[6];
+       u_int32_t       fcs;
+};
+
+struct ctrl_ack_t {
+       u_int16_t       fc;
+       u_int16_t       duration;
+       u_int8_t        ra[6];
+       u_int32_t       fcs;
+};
+
+struct ctrl_ps_poll_t {
+       u_int16_t       fc;
+       u_int16_t       aid;
+       u_int8_t        bssid[6];
+       u_int8_t        ta[6];
+       u_int32_t       fcs;
+};
+
+struct ctrl_end_t {
+       u_int16_t       fc;
+       u_int16_t       duration;
+       u_int8_t        ra[6];
+       u_int8_t        bssid[6];
+       u_int32_t       fcs;
+};
+
+struct ctrl_end_ack_t {
+       u_int16_t       fc;
+       u_int16_t       duration;
+       u_int8_t        ra[6];
+       u_int8_t        bssid[6];
+       u_int32_t       fcs;
+};
+
+#define IV_IV(iv)      ((iv) & 0xFFFFFF)
+#define IV_PAD(iv)     (((iv) >> 24) & 0x3F)
+#define IV_KEYID(iv)   (((iv) >> 30) & 0x03)
index a3aed3fe323bc951496616a17cd3f1acb8db8359..c94369e86f6ff6843c097cc0992b4840ec1f2002 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.159 2001-05-17 18:33:00 fenner Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.160 2001-06-12 05:17:17 guy Exp $ (LBL)
  */
 
 #ifndef tcpdump_interface_h
@@ -205,6 +205,8 @@ extern void ether_if_print(u_char *, const struct pcap_pkthdr *,
 extern void token_if_print(u_char *, const struct pcap_pkthdr *,
        const u_char *);
 extern void fddi_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);
 extern void icmp_print(const u_char *, u_int, const u_char *);
 extern void igmp_print(const u_char *, u_int, const u_char *);
diff --git a/print-802_11.c b/print-802_11.c
new file mode 100644 (file)
index 0000000..f468c3d
--- /dev/null
@@ -0,0 +1,781 @@
+/*
+ * Copyright (c) 2001  
+ *     Fortress Technologies, Inc.  All rights reserved.
+ *      Charlie Lenahan ([email protected])
+ *
+ * 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-802_11.c,v 1.1 2001-06-12 05:17:17 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <pcap.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "ethertype.h"
+
+#include "extract.h"
+
+#include "ieee802_11.h"
+
+#define RATEStoBUF(p,buf)      { int z=0; for (z=0 ; z < p.rates.length ; z++) \
+                                        sprintf(buf,"%s %2.1f",buf, (.5 * (p.rates.rate[z] & 0x7f))); }
+
+static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
+static const char *subtype_text[]={
+       "Assoc Request",
+       "Assoc Response",
+       "ReAssoc Request",
+       "ReAssoc Response",
+       "Probe Request",
+       "Probe Response",
+       "RESERVED",
+       "RESERVED",
+       "Beacon",
+       "ATIM",
+       "Disassociation",
+       "Authentication",
+       "DeAuthentication",
+       "RESERVED",
+       "RESERVED"
+};
+
+static const char *status_text[]={"Succesful",  /*  0  */
+                               "Unspecified failure",  /*  1  */
+                               "Reserved",       /*  2  */
+                               "Reserved",       /*  3  */
+                               "Reserved",       /*  4  */
+                               "Reserved",       /*  5  */
+                               "Reserved",       /*  6  */
+                               "Reserved",       /*  7  */
+                               "Reserved",       /*  8  */
+                               "Reserved",       /*  9  */
+                               "Cannot Support all requested capabilities in the Capability Information field",          /*  10  */
+                               "Reassociation denied due to inability to confirm that association exists",       /*  11  */
+                               "Association denied due to reason outside the scope of the standard",     /*  12  */
+                               "Responding station does not support the specified authentication algorithm ",    /*  13  */
+                               "Received an Authentication frame with authentication transaction " \
+                                       "sequence number out of expected sequence",       /*  14  */
+                               "Authentication rejected because of challenge failure",   /*  15 */
+                               "Authentication rejected due to timeout waiting for next frame in sequence",      /*  16 */
+                               "Association denied because AP is unable to handle additional associated stations",       /*  17 */
+                               "Association denied due to requesting station not supporting all of the " \
+                                       "data rates in BSSBasicRateSet parameter",        /*  18 */
+                               NULL };
+
+static const char *reason_text[]= { "Reserved", /* 0 */
+                               "Unspecified reason", /* 1 */
+                               "Previous authentication no longer valid",  /* 2 */
+                               "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
+                               "Disassociated due to inactivity", /* 4 */
+                               "Disassociated because AP is unable to handle all currently associated stations", /* 5 */
+                               "Class 2 frame receivedfrom nonauthenticated station", /* 6 */
+                               "Class 3 frame received from nonassociated station", /* 7 */
+                               "Disassociated because sending station is leaving (or has left) BSS", /* 8 */
+                               "Station requesting (re)association is not authenticated with responding station", /* 9 */
+                               NULL };
+       
+static void wep_print(const u_char *p,u_int length)
+{
+       u_int32_t iv;
+
+       iv = EXTRACT_LE_32BITS(p);
+
+       printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
+           IV_KEYID(iv));
+
+       return;
+}
+
+
+static void parse_elements(struct mgmt_body_t *pbody,const u_char *p,int offset)
+{      
+       while ( *(p+offset) != 0xff )
+       {
+               switch (*(p+offset))
+               {
+                       case E_SSID:
+                               memcpy(&(pbody->ssid),p+offset,2); offset += 2;
+                               if (pbody->ssid.length > 0)
+                               {
+                                       memcpy(&(pbody->ssid.ssid),p+offset,pbody->ssid.length); offset += pbody->ssid.length;
+                                       pbody->ssid.ssid[pbody->ssid.length]='\0';
+                               }
+                               break;
+                       case E_CHALLENGE:
+                               memcpy(&(pbody->challenge),p+offset,2); offset += 2;
+                               if (pbody->challenge.length > 0)
+                               {
+                                       memcpy(&(pbody->challenge.text),p+offset,pbody->challenge.length); offset += pbody->challenge.length;
+                                       pbody->challenge.text[pbody->challenge.length]='\0';
+                               }
+                               break;
+       
+                       case E_RATES:
+                               memcpy(&(pbody->rates),p+offset,2); offset += 2;
+                               if (pbody->rates.length > 0)
+                                       memcpy(&(pbody->rates.rate),p+offset,pbody->rates.length); offset += pbody->rates.length;
+                               break;
+                       case E_DS:
+                               memcpy(&(pbody->ds),p+offset,3); offset +=3;
+                               break;
+                       case E_CF:
+                               memcpy(&(pbody->cf),p+offset,8); offset +=8;
+                               break;
+                       case E_TIM:
+                               memcpy(&(pbody->tim),p+offset,2); offset +=2;
+                               memcpy(&(pbody->tim.count),p+offset,3); offset +=3;
+
+                               if ((pbody->tim.length -3) > 0)
+                               {
+                                       memcpy((pbody->tim.bitmap),p+(pbody->tim.length -3),(pbody->tim.length -3));
+                                       offset += pbody->tim.length -3;
+                               }
+               
+                               break;
+                       default:
+#if 0
+                               printf("(1) unhandled element_id (%d)  ", *(p+offset) );
+#endif
+                               offset+= *(p+offset+1) + 2;
+                               break;
+               }
+       }
+}
+
+/*********************************************************************************
+ * Print Handle functions for the management frame types
+ *********************************************************************************/
+
+static void handle_beacon(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t pbody;
+       int offset=0;
+       char buf[128];
+
+       memset(buf,0,128);
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       memcpy(&pbody.timestamp,p,8);
+       offset += 8;
+       pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+       pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+
+       parse_elements(&pbody,p,offset);
+
+       RATEStoBUF(pbody,buf);
+
+       printf("%s (%s) [%s Mbit] %s CH: %x %s",
+               subtype_text[FC_SUBTYPE(fc)],
+               pbody.ssid.ssid,buf,CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS" ,pbody.ds.channel,
+               CAPABILITY_PRIVACY(pbody.capability_info) ? ", PRIVACY" : "" );
+       
+       return ;
+}
+
+static void handle_assoc_request(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t pbody;
+       int offset=0; 
+       char buf[128];
+
+       memset(buf,0,128);
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       pbody.capability_info = EXTRACT_LE_16BITS(p);
+       offset += 2;
+       pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+       
+       parse_elements(&pbody,p,offset);
+
+       RATEStoBUF(pbody,buf);
+
+       printf("%s (%s) [%s Mbit] ", subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid,buf);
+       return;
+}
+
+static void handle_assoc_response(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t pbody;
+       int offset=0; 
+
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       pbody.capability_info = EXTRACT_LE_16BITS(p);
+       offset += 2;
+       pbody.status_code = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+       pbody.aid = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+
+       parse_elements(&pbody,p,offset);
+
+       printf("%s AID(%x) :%s: %s   ",subtype_text[FC_SUBTYPE(fc)], 
+               ((u_int16_t)( pbody.aid << 2 )) >> 2 , 
+               CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "" ,
+               (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a")  );
+
+       return;
+}
+
+
+static void handle_reassoc_request(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t pbody;
+       int offset=0; 
+
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       pbody.capability_info = EXTRACT_LE_16BITS(p);
+       offset += 2;
+       pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+       memcpy(&pbody.ap,p+offset,6);
+       offset += 6;
+
+       parse_elements(&pbody,p,offset);
+
+       printf("%s (%s) AP : %s",subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid, etheraddr_string( pbody.ap ));
+       
+       return;
+}
+
+static void handle_reassoc_response(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       /* Same as a Association Reponse */
+       return handle_assoc_response(fc,pmh,p);
+}
+
+static void handle_probe_request(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t  pbody;
+       int offset=0;
+       char buf[128];
+
+       memset(buf,0,128);
+
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       parse_elements(&pbody,p,offset);
+       
+       RATEStoBUF(pbody,buf);
+
+       printf("%s (%s) [%s Mbit] ",subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid,buf);
+
+       return;
+}
+
+static void handle_probe_response(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t  pbody;
+       int offset=0;
+       char buf[128];
+
+       memset(buf,0,128);
+
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       memcpy(&pbody.timestamp,p,8);
+       offset += 8;
+       pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+       pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+       
+       parse_elements(&pbody,p,offset);
+
+       printf("%s (%s) CH: %x %s",subtype_text[FC_SUBTYPE(fc)], pbody.ssid.ssid,pbody.ds.channel,
+               CAPABILITY_PRIVACY(pbody.capability_info) ? ",PRIVACY " : "" );
+
+       return;
+}
+
+static void handle_atim(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       /* the frame body for ATIM is null. */
+       printf("ATIM");
+       return;
+}
+
+static void handle_disassoc(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t  pbody;
+       int offset=0;
+
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       pbody.reason_code = EXTRACT_LE_16BITS(p);
+       offset += 2;
+
+       printf("%s: %s ", subtype_text[FC_SUBTYPE(fc)],
+           pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
+
+       return;
+}
+
+static void handle_auth(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t  pbody;
+       int offset=0;
+
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+
+       pbody.auth_alg = EXTRACT_LE_16BITS(p);
+       offset += 2;
+       pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+       pbody.status_code = EXTRACT_LE_16BITS(p+offset);
+       offset += 2;
+
+       parse_elements(&pbody,p,offset);
+
+
+       if (( pbody.auth_alg == 1) && 
+               ( ( pbody.auth_trans_seq_num == 2) || (pbody.auth_trans_seq_num == 3) ))
+       {
+               printf("%s (%s)-%x [Challenge Text] %s",
+                       subtype_text[FC_SUBTYPE(fc)],
+                       pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" ,
+                       pbody.auth_trans_seq_num,
+                        ((pbody.auth_trans_seq_num % 2) ? 
+                               (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a") : "" )
+                        );
+       }
+       else
+       {
+               printf("%s (%s)-%x: %s",
+                       subtype_text[FC_SUBTYPE(fc)],
+                       pbody.auth_alg < 4 ? auth_alg_text[pbody.auth_alg] : "Reserved" ,
+                       pbody.auth_trans_seq_num, 
+                        ( (pbody.auth_trans_seq_num % 2) ? 
+                               (pbody.status_code < 19 ? status_text[pbody.status_code] : "n/a")  : "")
+                        );
+       }
+
+
+       return;
+}
+
+static void handle_deauth(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p)
+{
+       struct mgmt_body_t  pbody;
+       int offset=0;
+
+       memset(&pbody,0,sizeof(struct mgmt_body_t));
+
+       pbody.reason_code = EXTRACT_LE_16BITS(p);
+       offset += 2;
+       
+       if (eflag)
+       {
+               printf("%s: %s",
+                       subtype_text[FC_SUBTYPE(fc)],
+                       pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
+       }
+       else
+       {
+               printf("%s (%s): %s",
+                       subtype_text[FC_SUBTYPE(fc)],
+                       etheraddr_string(pmh->sa),
+                       pbody.reason_code < 10 ? reason_text[pbody.reason_code] : "Reserved" );
+       }
+               
+       return;
+}
+
+
+/*********************************************************************************
+ * Print Body funcs
+ *********************************************************************************/
+
+
+static void mgmt_body_print(u_int16_t fc, const struct mgmt_header_t *pmh,
+    const u_char *p, u_int length)
+{
+       switch (FC_SUBTYPE(fc))
+       {
+               case ST_ASSOC_REQUEST:
+                       handle_assoc_request(fc,pmh,p);
+                       break;
+               case ST_ASSOC_RESPONSE:
+                       handle_assoc_response(fc,pmh,p);
+                       break;
+               case ST_REASSOC_REQUEST:
+                       handle_reassoc_request(fc,pmh,p);
+                       break;
+               case ST_REASSOC_RESPONSE:
+                       handle_reassoc_response(fc,pmh,p);
+                       break;
+               case ST_PROBE_REQUEST:
+                       handle_probe_request(fc,pmh,p);
+                       break;
+               case ST_PROBE_RESPONSE:
+                       handle_probe_response(fc,pmh,p);
+                       break;
+               case ST_BEACON:
+                       handle_beacon(fc,pmh,p);
+                       break;
+               case ST_ATIM:
+                       handle_atim(fc,pmh,p);
+                       break;
+               case ST_DISASSOC:
+                       handle_disassoc(fc,pmh,p);
+                       break;
+               case ST_AUTH:
+                       if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0))
+                       {
+                               printf("Authentication (Shared-Key)-3 ");
+                               wep_print(p,length);
+                       }
+                       else
+                               handle_auth(fc,pmh,p);
+                       break;
+               case ST_DEAUTH:
+                       handle_deauth(fc,pmh,p);
+                       break;
+               default:
+                       printf("Unhandled Managment subtype(%x)",
+                           FC_SUBTYPE(fc));
+       }
+}
+
+
+/*********************************************************************************
+ * Handles printing all the control frame types
+ *********************************************************************************/
+
+static void ctrl_body_print(u_int16_t fc,const u_char *p, u_int length)
+{
+       switch (FC_SUBTYPE(fc))
+       {
+               case CTRL_PS_POLL:
+                       printf("Power Save-Poll AID(%x)",((u_int16_t)( ((struct ctrl_ps_poll_t *)p)->aid  << 2 )) >> 2 );
+                       break;
+               case CTRL_RTS:
+                       if (eflag)
+                               printf("Request-To-Send");
+                       else
+                               printf("Request-To-Send TA:%s ", etheraddr_string( ((struct ctrl_rts_t *)p)->ta));
+                       break;
+               case CTRL_CTS:
+                       if (eflag)
+                               printf("Clear-To-Send");
+                       else
+                               printf("Clear-To-Send RA:%s ", etheraddr_string( ((struct ctrl_cts_t *)p)->ra));
+                       break;
+               case CTRL_ACK:
+                       if (eflag)
+                               printf("Acknowledgment");
+                       else
+                               printf("Acknowledgment RA:%s ", etheraddr_string( ((struct ctrl_ack_t *)p)->ra));
+                       break;
+               case CTRL_CF_END:
+                       if (eflag)
+                               printf("CF-End");
+                       else
+                               printf("CF-End RA:%s ", etheraddr_string( ((struct ctrl_end_t *)p)->ra));
+                       break;
+               case CTRL_END_ACK:
+                       if (eflag)
+                               printf("CF-End+CF-Ack");
+                       else
+                               printf("CF-End+CF-Ack RA:%s ", etheraddr_string( ((struct ctrl_end_ack_t *)p)->ra));
+                       break;
+               default:
+                       printf("(B) Unknown Ctrl Subtype");
+       }
+}
+
+
+
+/*********************************************************************************
+ * Print Header funcs
+ *********************************************************************************/
+
+/*********************************************************************************
+ *  Data Frame - Address field contents
+ *
+ *  To Ds  | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
+ *    0    |  0      |  DA    | SA     | BSSID  | n/a
+ *    0    |  1      |  DA    | BSSID  | SA     | n/a
+ *    1    |  0      |  BSSID | SA     | DA     | n/a
+ *    1    |  1      |  RA    | TA     | DA     | SA
+ *********************************************************************************/
+
+#define ADDR1  p+4
+#define ADDR2  p+10
+#define ADDR3  p+16
+#define ADDR4  p+24
+
+static void data_header_print(u_int16_t fc,const u_char *p, u_int length)
+{
+       if (!FC_TO_DS(fc))
+       {
+               if (!FC_FROM_DS(fc))
+                       printf("DA:%s SA:%s BSSID:%s ", etheraddr_string( ADDR1),
+                               etheraddr_string( ADDR2), etheraddr_string( ADDR3));
+               else
+                       printf("DA:%s BSSID:%s SA:%s ", etheraddr_string( ADDR1),
+                               etheraddr_string( ADDR2), etheraddr_string( ADDR3));
+       }
+       else 
+       {
+               if (!FC_FROM_DS(fc))
+                       printf("BSSID:%s SA:%s DA:%s ", etheraddr_string( ADDR1),
+                               etheraddr_string( ADDR2), etheraddr_string( ADDR3));
+               else
+                       printf("RA:%s TA:%s DA:%s SA:%s ", etheraddr_string( ADDR1),
+                               etheraddr_string( ADDR2), etheraddr_string( ADDR3),
+                               etheraddr_string( ADDR4));
+       }
+       
+}
+
+
+static void mgmt_header_print(const u_char *p, u_int length)
+{
+       const struct mgmt_header_t *hp=(const struct mgmt_header_t *) p;
+
+       printf("BSSID:%s DA:%s SA:%s ", etheraddr_string( (hp)->bssid),
+                                       etheraddr_string( (hp)->da),
+                                       etheraddr_string( (hp)->sa));
+}
+
+static void ctrl_header_print(u_int16_t fc,const u_char *p, u_int length)
+{
+       switch (FC_SUBTYPE(fc))
+       {
+               case CTRL_PS_POLL:
+                       printf("BSSID:%s TA:%s ", etheraddr_string(  ((struct ctrl_ps_poll_t *)p)->bssid),
+                                               etheraddr_string( ((struct ctrl_ps_poll_t *)p)->ta));
+                       break;
+               case CTRL_RTS:
+                       printf("RA:%s TA:%s ", etheraddr_string( ((struct ctrl_rts_t *)p)->ra),
+                                               etheraddr_string( ((struct ctrl_rts_t *)p)->ta));
+                       break;
+               case CTRL_CTS:
+                       printf("RA:%s ", etheraddr_string( ((struct ctrl_cts_t *)p)->ra));
+                       break;
+               case CTRL_ACK:
+                       printf("RA:%s ", etheraddr_string( ((struct ctrl_ack_t *)p)->ra));
+                       break;
+               case CTRL_CF_END:
+                       printf("RA:%s BSSID:%s ", etheraddr_string( ((struct ctrl_end_t *)p)->ra),
+                                               etheraddr_string( ((struct ctrl_end_t *)p)->bssid));
+                       break;
+               case CTRL_END_ACK:
+                       printf("RA:%s BSSID:%s ", etheraddr_string( ((struct ctrl_end_ack_t *)p)->ra),
+                                               etheraddr_string( ((struct ctrl_end_ack_t *)p)->bssid));
+                       break;
+               default:
+                       printf("(H) Unknown Ctrl Subtype");
+       }
+}
+
+static int GetHeaderLength(u_int16_t fc)
+{
+       int iLength=0;
+
+       switch (FC_TYPE(fc))
+       {
+               case T_MGMT:
+                       iLength=sizeof(struct mgmt_header_t);
+                       break;
+               case T_CTRL:
+                       switch (FC_SUBTYPE(fc))
+                       {
+                               case CTRL_PS_POLL:
+                                       iLength=sizeof(struct ctrl_ps_poll_t);
+                                       break;
+                               case CTRL_RTS:
+                                       iLength=sizeof(struct ctrl_rts_t);
+                                       break;
+                               case CTRL_CTS:
+                                       iLength=sizeof(struct ctrl_cts_t);
+                                       break;
+                               case CTRL_ACK:
+                                       iLength=sizeof(struct ctrl_ack_t);
+                                       break;
+                               case CTRL_CF_END:
+                                       iLength=sizeof(struct ctrl_end_t);
+                                       break;
+                               case CTRL_END_ACK:
+                                       iLength=sizeof(struct ctrl_end_ack_t);
+                                       break;
+                               default:
+                                       iLength=0;
+                                       break;
+                       }
+                       break;
+               case T_DATA:
+                       if (FC_TO_DS(fc) && FC_FROM_DS(fc))
+                               iLength=30;
+                       else
+                               iLength=24;
+                       break;
+               default:
+                       printf("unknown IEEE802.11 frame type (%d)",
+                           FC_TYPE(fc));
+                       break;
+       }
+
+       return iLength;
+}
+
+/*
+ * Print the 802.11 MAC header
+ */
+static inline void
+ieee_802_11_print(u_int16_t fc, const u_char *p, u_int length)
+{
+       switch (FC_TYPE(fc)) {
+
+       case T_MGMT:
+               mgmt_header_print(p,length);
+               break;
+
+       case T_CTRL:
+               ctrl_header_print(fc,p,length);
+               break;
+
+       case T_DATA:
+               data_header_print(fc,p,length);
+               break;
+
+       default:
+               printf("(header) unknown IEEE802.11 frame type (%d)",
+                   FC_TYPE(fc));
+               break;
+       }
+}
+
+/*
+ * This is the top level routine of the printer.  'p' is the points
+ * to the ether header of the packet, 'h->tv' is the timestamp,
+ * 'h->length' is the length of the packet off the wire, and 'h->caplen'
+ * is the number of bytes actually captured.
+ */
+void
+ieee802_11_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       u_int caplen = h->caplen;
+       u_int length = h->len;
+       u_int16_t fc;
+       u_int HEADER_LENGTH;
+       u_short extracted_ethertype;
+
+       ts_print(&h->ts);
+
+       if (caplen < IEEE802_11_FC_LEN) {
+               printf("[|802.11]");
+               goto out;
+       }
+
+       fc=EXTRACT_LE_16BITS(p);
+
+       if (eflag)
+               ieee_802_11_print(fc,p,length);
+
+       /*
+        * Some printers want to get back at the ethernet 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;
+
+       HEADER_LENGTH=GetHeaderLength(fc);
+
+       length -= HEADER_LENGTH;
+       caplen -= HEADER_LENGTH;
+       p += HEADER_LENGTH;
+
+       switch (FC_TYPE(fc)) {
+
+       case T_MGMT:
+               mgmt_body_print(fc,(const struct mgmt_header_t *)packetp,p,length);
+               break;
+
+       case T_CTRL:
+               ctrl_body_print(fc,p,length);
+               break;
+
+       case T_DATA:
+               /* There may be a problem w/ AP not having this bit set */
+               if (FC_WEP(fc))
+                       wep_print(p,length);
+               else {
+                       if (llc_print(p, length, caplen, packetp+10,
+                           packetp+4, &extracted_ethertype) == 0) {
+                               /*
+                                * Some kinds of LLC packet we cannot
+                                * handle intelligently
+                                */
+                               if (!eflag)
+                                       ieee_802_11_print(fc, p - HEADER_LENGTH,
+                                           length + HEADER_LENGTH);
+                               if (extracted_ethertype) {
+                                       printf("(LLC %s) ",
+                               etherproto_string(htons(extracted_ethertype)));
+                               }
+                               if (!xflag && !qflag)
+                                       default_print(p, caplen);
+                       }
+               }
+               break;
+
+       default:
+               printf("(body) unhandled IEEE802.11 frame type (%d)",
+                   FC_TYPE(fc));
+               break;
+       }
+
+       if (xflag)
+               default_print(p, caplen);
+ out:
+       putchar('\n');
+}
index 4903a6233a93aa0c921638f6bb8e92170bbf1910..a28d83d8bfdde61c355fe70408c8bca56f2073aa 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -24,7 +24,7 @@ static const char copyright[] =
     "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\
 The Regents of the University of California.  All rights reserved.\n";
 static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.161 2001-04-30 16:08:43 fenner Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.162 2001-06-12 05:17:18 guy Exp $ (LBL)";
 #endif
 
 /*
@@ -133,6 +133,9 @@ static struct printer printers[] = {
 #endif
 #ifdef DLT_LINUX_SLL
        { sll_if_print,         DLT_LINUX_SLL },
+#endif
+#ifdef DLT_IEEE802_11
+       { ieee802_11_if_print,  DLT_IEEE802_11},
 #endif
        { NULL,                 0 },
 };