Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic Snapshot of work-in-progress: Add AP support for ...



details:   https://anonhg.NetBSD.org/src/rev/8843de692cce
branches:  trunk
changeset: 535137:8843de692cce
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun Aug 11 06:13:53 2002 +0000

description:
Snapshot of work-in-progress: Add AP support for Prism2-based boards.
WEP for APs is not yet implemented, but without WEP, this works well
enough for my laptop to associate with an AP running this code.

Adapted from OpenBSD.

diffstat:

 sys/dev/ic/wi.c        |   248 +++++++-
 sys/dev/ic/wi_hostap.c |  1276 ++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/ic/wi_hostap.h |   134 +++++
 sys/dev/ic/wi_ieee.h   |    11 +-
 sys/dev/ic/wireg.h     |     3 +-
 sys/dev/ic/wivar.h     |    12 +-
 6 files changed, 1635 insertions(+), 49 deletions(-)

diffs (truncated from 1983 to 300 lines):

diff -r 1fd079ac1747 -r 8843de692cce sys/dev/ic/wi.c
--- a/sys/dev/ic/wi.c   Sun Aug 11 06:12:45 2002 +0000
+++ b/sys/dev/ic/wi.c   Sun Aug 11 06:13:53 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wi.c,v 1.78 2002/08/11 01:35:10 thorpej Exp $  */
+/*     $NetBSD: wi.c,v 1.79 2002/08/11 06:13:53 thorpej Exp $  */
 
 /*
  * Copyright (c) 1997, 1998, 1999
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.78 2002/08/11 01:35:10 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.79 2002/08/11 06:13:53 thorpej Exp $");
 
 #define WI_HERMES_AUTOINC_WAR  /* Work around data write autoinc bug. */
 #define WI_HERMES_STATS_WAR    /* Work around stats counter bug. */
@@ -128,7 +128,6 @@
 static void wi_wait_scan       __P((void *));
 static int wi_setdef           __P((struct wi_softc *, struct wi_req *));
 static int wi_getdef           __P((struct wi_softc *, struct wi_req *));
-static int wi_mgmt_xmit                __P((struct wi_softc *, caddr_t, int));
 
 static int wi_media_change __P((struct ifnet *));
 static void wi_media_status __P((struct ifnet *, struct ifmediareq *));
@@ -341,6 +340,9 @@
        if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
                    IFM_IEEE80211_IBSSMASTER, 0), 0);
+       if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
+               ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
+                   IFM_IEEE80211_HOSTAP, 0), 0);
        if (sc->wi_supprates & WI_SUPPRATES_1M) {
                PRINT("1Mbps");
                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
@@ -352,6 +354,9 @@
                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
                            IFM_IEEE80211_IBSSMASTER, 0), 0);
+               if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
+                       ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
+                           IFM_IEEE80211_HOSTAP, 0), 0);
        }
        if (sc->wi_supprates & WI_SUPPRATES_2M) {
                PRINT("2Mbps");
@@ -364,6 +369,9 @@
                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
                            IFM_IEEE80211_IBSSMASTER, 0), 0);
+               if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
+                       ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
+                           IFM_IEEE80211_HOSTAP, 0), 0);
        }
        if (sc->wi_supprates & WI_SUPPRATES_5M) {
                PRINT("5.5Mbps");
@@ -376,6 +384,9 @@
                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
                            IFM_IEEE80211_IBSSMASTER, 0), 0);
+               if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
+                       ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
+                           IFM_IEEE80211_HOSTAP, 0), 0);
        }
        if (sc->wi_supprates & WI_SUPPRATES_11M) {
                PRINT("11Mbps");
@@ -388,6 +399,9 @@
                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
                            IFM_IEEE80211_IBSSMASTER, 0), 0);
+               if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
+                       ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
+                           IFM_IEEE80211_HOSTAP, 0), 0);
                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
        }
        if (sc->wi_supprates != 0)
@@ -458,6 +472,42 @@
        eh = mtod(m, struct ether_header *);
        m->m_pkthdr.rcvif = ifp;
 
+       if ((le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_MGMT &&
+           sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
+               if ((le16toh(rx_frame.wi_dat_len) + WI_802_11_OFFSET_RAW + 2) >
+                   MCLBYTES) {
+                       printf("%s: oversized packet received in "
+                           "Host-AP mode (wi_dat_len=%d, wi_status=0x%x)\n",
+                           sc->sc_dev.dv_xname,
+                           le16toh(rx_frame.wi_dat_len),
+                           le16toh(rx_frame.wi_status));
+                       m_freem(m);
+                       ifp->if_ierrors++;
+                       return;
+               }
+
+               /* Put the whole header in there. */
+               memcpy(mtod(m, void *), &rx_frame, sizeof(rx_frame));
+               if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
+                   mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
+                   le16toh(rx_frame.wi_dat_len) + 2)) {
+                       m_freem(m);
+                       if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
+                               printf("%s: Host-AP: failed to copy header\n",
+                                   sc->sc_dev.dv_xname);
+                       ifp->if_ierrors++;
+                       return;
+               }
+
+               m->m_pkthdr.len = m->m_len =
+                   WI_802_11_OFFSET_RAW + le16toh(rx_frame.wi_dat_len);
+
+               /* XXX Consider giving packet to bhp? */
+
+               wihap_mgmt_input(sc, &rx_frame, m);
+               return;
+       }
+
        if ((le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_1042 ||
            (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_TUNNEL ||
            (le16toh(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) == WI_STAT_WMP_MSG) {
@@ -511,6 +561,16 @@
 
        ifp->if_ipackets++;
 
+       if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
+               /* 
+                * Give Host-AP first crack at data packets.  If it
+                * decides to handle it (or drop it), it will return
+                * non-zero.  Otherwise, it is destined for this host.
+                */
+               if (wihap_data_input(sc, &rx_frame, m))
+                       return;
+       }
+
 #if NBPFILTER > 0
        /* Handle BPF listeners. */
        if (ifp->if_bpf)
@@ -1060,7 +1120,7 @@
                        oltv->wi_len = 2;
                        oltv->wi_val = ltv->wi_val;
                        break;
-               case WI_RID_AUTH_CNTL:
+               case WI_RID_CNFAUTHMODE:
                        oltv->wi_len = 2;
                        if (le16toh(ltv->wi_val) & 0x01)
                                oltv->wi_val = htole16(1);
@@ -1114,10 +1174,14 @@
                case WI_RID_ENCRYPTION:
                        p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
                        p2ltv.wi_len = 2;
-                       if (le16toh(ltv->wi_val))
-                               p2ltv.wi_val = htole16(PRIVACY_INVOKED |
-                                                      EXCLUDE_UNENCRYPTED);
-                       else
+                       if (le16toh(ltv->wi_val)) {
+                               uint16_t val = PRIVACY_INVOKED |
+                                   EXCLUDE_UNENCRYPTED;
+                               /* Tx encryption is broken in Host-AP mode. */
+                               if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
+                                       val |= HOST_ENCRYPT;
+                               p2ltv.wi_val = htole16(val);
+                       } else
                                p2ltv.wi_val =
                                    htole16(HOST_ENCRYPT | HOST_DECRYPT);
                        ltv = &p2ltv;
@@ -1150,8 +1214,8 @@
                        }
                        return 0;
                    }
-               case WI_RID_AUTH_CNTL:
-                       p2ltv.wi_type = WI_RID_AUTH_CNTL;
+               case WI_RID_CNFAUTHMODE:
+                       p2ltv.wi_type = WI_RID_CNFAUTHMODE;
                        p2ltv.wi_len = 2;
                        if (le16toh(ltv->wi_val) == 1)
                                p2ltv.wi_val = htole16(0x01);
@@ -1439,7 +1503,7 @@
        case WI_RID_MAX_SLEEP:
                sc->wi_max_sleep = le16toh(wreq->wi_val[0]);
                break;
-       case WI_RID_AUTH_CNTL:
+       case WI_RID_CNFAUTHMODE:
                sc->wi_authtype = le16toh(wreq->wi_val[0]);
                break;
        case WI_RID_ROAMING_MODE:
@@ -1521,7 +1585,7 @@
        case WI_RID_MAX_SLEEP:
                wreq->wi_val[0] = htole16(sc->wi_max_sleep);
                break;
-       case WI_RID_AUTH_CNTL:
+       case WI_RID_CNFAUTHMODE:
                wreq->wi_val[0] = htole16(sc->wi_authtype);
                break;
        case WI_RID_ROAMING_MODE:
@@ -1587,18 +1651,17 @@
                        if (ifp->if_flags & IFF_RUNNING &&
                            ifp->if_flags & IFF_PROMISC &&
                            !(sc->wi_if_flags & IFF_PROMISC)) {
-                               WI_SETVAL(WI_RID_PROMISC, 1);
+                               if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
+                                       WI_SETVAL(WI_RID_PROMISC, 1);
                        } else if (ifp->if_flags & IFF_RUNNING &&
                            !(ifp->if_flags & IFF_PROMISC) &&
                            sc->wi_if_flags & IFF_PROMISC) {
-                               WI_SETVAL(WI_RID_PROMISC, 0);
-                       }
-                       wi_init(ifp);
-               } else {
-                       if (ifp->if_flags & IFF_RUNNING) {
-                               wi_stop(ifp, 0);
-                       }
-               }
+                               if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
+                                       WI_SETVAL(WI_RID_PROMISC, 0);
+                       } else
+                               wi_init(ifp);
+               } else if (ifp->if_flags & IFF_RUNNING)
+                       wi_stop(ifp, 0);
                sc->wi_if_flags = ifp->if_flags;
 
                if (!(ifp->if_flags & IFF_UP)) {
@@ -1789,6 +1852,15 @@
        case SIOCG80211POWER:
                error = wi_get_pm(sc, (struct ieee80211_power *)data);
                break;
+       case SIOCHOSTAP_ADD:
+       case SIOCHOSTAP_DEL:
+       case SIOCHOSTAP_GET:
+       case SIOCHOSTAP_GETALL:
+       case SIOCHOSTAP_GFLAGS:
+       case SIOCHOSTAP_SFLAGS:
+               /* Send all Host-AP specific ioctls to the Host-AP code. */
+               error = wihap_ioctl(sc, command, data);
+               break;
 
        default:
                error = EINVAL;
@@ -1853,7 +1925,8 @@
 
        /* Specify the IBSS name */
        if (sc->wi_netid.i_len != 0 &&
-           (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS))
+           (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
+            (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
                wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_netid);
        else
                wi_write_ssid(sc, WI_RID_OWN_SSID, &wreq, &sc->wi_ibssid);
@@ -1870,8 +1943,16 @@
        memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
        wi_write_record(sc, (struct wi_ltv_gen *)&mac);
 
-       /* Initialize promisc mode. */
-       if (ifp->if_flags & IFF_PROMISC) {
+       /*
+        * Initialize promisc mode.
+        *      Being in the Host-AP mode causes a great
+        *      deal of pain if primisc mode is set.
+        *      Therefore we avoid confusing the firmware
+        *      and always reset promisc mode in Host-AP
+        *      mode.  Host-AP sees all the packets anyway.
+        */
+       if (sc->wi_ptype != WI_PORTTYPE_HOSTAP &&
+           (ifp->if_flags & IFF_PROMISC) != 0) {
                WI_SETVAL(WI_RID_PROMISC, 1);
        } else {
                WI_SETVAL(WI_RID_PROMISC, 0);
@@ -1899,7 +1980,7 @@
                                /* firm ver < 0.8 variant 2 */
                                WI_SETVAL(WI_RID_PROMISC, 1);
                        }
-                       WI_SETVAL(WI_RID_AUTH_CNTL, sc->wi_authtype);
+                       WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
                }
        }
 
@@ -1932,6 +2013,8 @@
        /* Enable interrupts */
        CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
 
+       wihap_init(sc);
+
        ifp->if_flags |= IFF_RUNNING;
        ifp->if_flags &= ~IFF_OACTIVE;
 
@@ -1947,6 +2030,16 @@
 }
 
 static void
+wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
+{
+
+       if (sc->wi_icv_flag == 0) {
+               sc->wi_icv = arc4random();
+               sc->wi_icv_flag++;
+       }
+}
+
+static void
 wi_start(ifp)
        struct ifnet            *ifp;
 {



Home | Main Index | Thread Index | Old Index