Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pcmcia Add support for 802.11 authentication frames, ...



details:   https://anonhg.NetBSD.org/src/rev/66bb8cbb2122
branches:  trunk
changeset: 500415:66bb8cbb2122
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Mon Dec 11 17:53:19 2000 +0000

description:
Add support for 802.11 authentication frames, required to interoperate
with Aviator Pro cards on Windows.  Written by Steve Weiss for OpenBSD,
ported to NetBSD by me.

diffstat:

 sys/dev/pcmcia/if_ray.c |  150 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 144 insertions(+), 6 deletions(-)

diffs (249 lines):

diff -r b49318549c5e -r 66bb8cbb2122 sys/dev/pcmcia/if_ray.c
--- a/sys/dev/pcmcia/if_ray.c   Mon Dec 11 17:52:43 2000 +0000
+++ b/sys/dev/pcmcia/if_ray.c   Mon Dec 11 17:53:19 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ray.c,v 1.23 2000/11/15 01:02:18 thorpej Exp $      */
+/*     $NetBSD: if_ray.c,v 1.24 2000/12/11 17:53:19 thorpej Exp $      */
 /* 
  * Copyright (c) 2000 Christian E. Hopps
  * All rights reserved.
@@ -47,6 +47,12 @@
  *     N.B. Its unclear yet whether the Aviator 2.4 cards interoperate
  *     with other 802.11 FH 2Mbps cards, since this was also untested.
  *     Given the nature of the buggy build 4 firmware there may be problems.
+ *
+ *     Authentication added by Steve Weiss <srw%alum.mit.edu@localhost> based on
+ *     advice from Corey Thomas (author the the Linux RayLink driver).
+ *     Authentication is currently limited to adhoc networks, and was
+ *     added to support a requirement of the newest Windows drivers for
+ *     the RayLink.  Tested with Aviator Pro (firmware 5.63) on Win98.
  */
 
 #include "opt_inet.h"
@@ -179,6 +185,8 @@
        u_int           sc_txfree;      /* a free count for efficiency */
 
        u_int8_t        sc_bssid[ETHER_ADDR_LEN];       /* current net values */
+       u_int8_t        sc_authid[ETHER_ADDR_LEN];      /* ID of authenticating
+                                                          station */
        struct ieee80211_nwid   sc_cnwid;       /* last nwid */
        struct ieee80211_nwid   sc_dnwid;       /* desired nwid */
        u_int8_t        sc_omode;       /* old operating mode SC_MODE_xx */
@@ -189,7 +197,7 @@
        bus_size_t      sc_txpad;       /* tib size plus "phy" size */
        u_int8_t        sc_deftxrate;   /* default transfer rate */
        u_int8_t        sc_encrypt;
-
+       u_int8_t        sc_authstate;   /* authentication state */
 
        int             sc_promisc;     /* current set value */
        int             sc_running;     /* things we are doing */
@@ -261,6 +269,15 @@
 #define        SC_BUILD_5      0x5
 #define        SC_BUILD_4      0x55
 
+/* sc_authstate */
+#define        RAY_AUTH_UNAUTH         0
+#define        RAY_AUTH_WAITING        1
+#define        RAY_AUTH_AUTH           2
+#define        RAY_AUTH_NEEDED         3
+
+#define        OPEN_AUTH_REQUEST       1
+#define        OPEN_AUTH_RESPONSE      2
+#define        BROADCAST_DEAUTH        0xc0
 
 static int ray_alloc_ccs __P((struct ray_softc *, bus_size_t *, u_int, u_int));
 static bus_size_t ray_fill_in_tx_ccs __P((struct ray_softc *, size_t,
@@ -296,9 +313,11 @@
 static ray_cmd_func_t ray_rccs_intr __P((struct ray_softc *, bus_size_t));
 static void ray_read_region __P((struct ray_softc *, bus_size_t,void *,size_t));
 static void ray_recv __P((struct ray_softc *, bus_size_t));
+static void ray_recv_auth __P((struct ray_softc *, struct ieee80211_frame *));
 static void ray_report_params __P((struct ray_softc *));
 static void ray_reset __P((struct ray_softc *));
 static void ray_reset_resetloop __P((void *));
+static int ray_send_auth __P((struct ray_softc *, u_int8_t *, u_int8_t));
 static void ray_set_pending __P((struct ray_softc *, u_int));
 static void ray_shutdown __P((void *));
 static int ray_simple_cmd __P((struct ray_softc *, u_int, u_int));
@@ -803,6 +822,7 @@
        sc->sc_txfree = RAY_CCS_NTX;
        sc->sc_checkcounters = 0;
        sc->sc_flags &= ~RAY_FLAGS_RESUMEINIT;
+       sc->sc_authstate = RAY_AUTH_UNAUTH;
 
        /* get startup results */
        ep = &sc->sc_ecf_startup;
@@ -1192,20 +1212,32 @@
                return;
        }
 
+       /* Check to see if we need to authenticate before sending packets. */
+       if (sc->sc_authstate == RAY_AUTH_NEEDED) {
+               RAY_DPRINTF(("%s: Sending auth request.\n", ifp->if_xname));
+               sc->sc_authstate = RAY_AUTH_WAITING;
+               ray_send_auth(sc, sc->sc_authid, OPEN_AUTH_REQUEST);
+               return;
+       }
+
        pcount = 0;
        for (;;) {
                /* if we have no descriptors be done */
                if (i == RAY_CCS_LINK_NULL) {
                        i = ray_find_free_tx_ccs(sc, hinti);
                        if (i == RAY_CCS_LINK_NULL) {
+                               RAY_DPRINTF(("%s: no descriptors.\n",
+                                   ifp->if_xname));
                                ifp->if_flags |= IFF_OACTIVE;
                                break;
                        }
                }
 
                IF_DEQUEUE(&ifp->if_snd, m0);
-               if (!m0)
+               if (!m0) {
+                       RAY_DPRINTF(("%s: dry queue.\n", ifp->if_xname));
                        break;
+               }
                RAY_DPRINTF(("%s: gotmbuf 0x%lx\n", ifp->if_xname, (long)m0));
                pktlen = m0->m_pkthdr.len;
                if (pktlen > ETHER_MAX_LEN - ETHER_CRC_LEN) {
@@ -1419,8 +1451,7 @@
            (u_long)pktlen, nofrag));
        RAY_DPRINTF_XMIT(("%s: received packet: len %ld\n", sc->sc_xname,
            (u_long)pktlen));
-       if (pktlen > MCLBYTES
-           || pktlen < (sizeof(*frame) + sizeof(struct llc))) {
+       if (pktlen > MCLBYTES || pktlen < sizeof(*frame)) {
                RAY_DPRINTF(("%s: PKTLEN TOO BIG OR TOO SMALL\n",
                    sc->sc_xname));
                ifp->if_ierrors++;
@@ -1525,13 +1556,41 @@
                m_freem(m);
                return;
        }
-       if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) {
+       if ((fc0 & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MGT) {
+               switch (frame->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
+               case IEEE80211_FC0_SUBTYPE_BEACON:
+                       /* Ignore beacon silently. */
+                       break;
+               case IEEE80211_FC0_SUBTYPE_AUTH:
+                       ray_recv_auth(sc, frame);
+                       break;
+               case IEEE80211_FC0_SUBTYPE_DEAUTH:
+                       sc->sc_authstate = RAY_AUTH_UNAUTH;
+                       break;
+               default:
+                       RAY_DPRINTF(("%s: mgt packet not supported\n",
+                           sc->sc_dev.dv_xname));
+#ifdef RAY_DEBUG
+                       hexdump((const u_int8_t*)frame, pktlen, 16, 4, 0);
+#endif
+                       RAY_DPRINTF(("\n"));
+                       break;
+               }
+               m_freem(m);
+       } else if ((fc0 & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) {
                RAY_DPRINTF(("%s: pkt not type data fc0 0x%x\n",
                    sc->sc_xname, fc0));
                m_freem(m);
                return;
        }
 
+       if (pktlen < sizeof(*frame) + sizeof(struct llc)) {
+               RAY_DPRINTF(("%s: pkt too small for llc (%d)\n",
+                   sc->sc_xname, pktlen));
+               m_freem(m);
+               return;
+       }
+
        if (!memcmp(frame + 1, llc_snapid, sizeof(llc_snapid)))
                issnap = 1;
        else {
@@ -1590,6 +1649,85 @@
        (*ifp->if_input)(ifp, m);
 }
 
+/*
+ * receive an auth packet
+ */
+static void
+ray_recv_auth(sc, frame)
+       struct ray_softc *sc;
+       struct ieee80211_frame *frame;
+{
+       u_int8_t *var = (u_int8_t *)(frame + 1);
+
+       if (sc->sc_mode == SC_MODE_ADHOC) {
+               RAY_DPRINTF(("%s: recv auth packet:\n", sc->sc_dev.dv_xname));
+#ifdef RAY_DEBUG
+               hexdump((const u_int8_t *)frame, sizeof(*frame) + 6, 16, 4, 0);
+#endif
+               RAY_DPRINTF(("\n"));
+
+               if (var[2] == OPEN_AUTH_REQUEST) {
+                       RAY_DPRINTF(("%s: Sending authentication response.\n",
+                           sc->sc_dev.dv_xname));
+                       if (ray_send_auth(sc, frame->i_addr2,
+                           OPEN_AUTH_RESPONSE) == 0) {
+                               sc->sc_authstate = RAY_AUTH_NEEDED;
+                               memcpy(sc->sc_authid, frame->i_addr2,
+                                   ETHER_ADDR_LEN);
+                       }
+               } else if (var[2] == OPEN_AUTH_RESPONSE) {
+                       RAY_DPRINTF(("%s: Authenticated!\n",
+                           sc->sc_dev.dv_xname));
+                       sc->sc_authstate = RAY_AUTH_AUTH;
+               }
+       }
+}
+
+/*
+ * send an auth packet
+ */
+static int
+ray_send_auth(sc, dest, auth_type)
+       struct ray_softc *sc;
+       u_int8_t *dest;
+       u_int8_t auth_type;
+{
+       u_int8_t packet[sizeof(struct ieee80211_frame) + ETHER_ADDR_LEN], *var;
+       struct ieee80211_frame *frame;
+       bus_size_t bufp;
+       int ccsindex;
+
+       ccsindex = ray_find_free_tx_ccs(sc, RAY_CCS_TX_FIRST);
+       if (ccsindex == RAY_CCS_LINK_NULL) {
+               RAY_DPRINTF(("%s: send auth failed -- no free tx slots\n",
+                   sc->sc_dev.dv_xname));
+               return (ENOMEM);
+       }
+
+       bufp = ray_fill_in_tx_ccs(sc, sizeof(packet), ccsindex,
+           RAY_CCS_LINK_NULL);
+       frame = (struct ieee80211_frame *) packet;
+       frame->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_SUBTYPE_AUTH;
+       frame->i_fc[1] = 0;
+       memcpy(frame->i_addr1, dest, ETHER_ADDR_LEN);
+       memcpy(frame->i_addr2, sc->sc_ecf_startup.e_station_addr,
+           ETHER_ADDR_LEN);
+       memcpy(frame->i_addr3, sc->sc_bssid, ETHER_ADDR_LEN);
+
+       var = (u_int8_t *)(frame + 1);
+       memset(var, 0, ETHER_ADDR_LEN);
+       var[2] = auth_type;
+
+       ray_write_region(sc, bufp, packet, sizeof(packet));
+
+       SRAM_WRITE_1(sc, RAY_SCB_CCSI, ccsindex);
+       RAY_ECF_START_CMD(sc);
+
+       RAY_DPRINTF_XMIT(("%s: sent auth packet: len %lu\n",
+           sc->sc_dev.dv_xname, (u_long) sizeof(packet)));
+
+       return (0);
+}
 
 /*
  * scan for free buffers



Home | Main Index | Thread Index | Old Index