summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2002-04-16 07:45:30 +0000
committerimp <imp@FreeBSD.org>2002-04-16 07:45:30 +0000
commit37bc817098c906e79d7266109cf861c9963bf150 (patch)
tree2501c22213ae97acb64f20ceb4d6424d3628b13d /sys/dev
parentca41daa96dffea7c5f4cdce6e17d62bf9e6f3e59 (diff)
downloadFreeBSD-src-37bc817098c906e79d7266109cf861c9963bf150.zip
FreeBSD-src-37bc817098c906e79d7266109cf861c9963bf150.tar.gz
Merge from OpenBSD's fixes:
o move timeout from wihap_info to wihap_sta_info o sprinkle spls into the code (need to use proper -current locking) o better use of le16toh and htole16 o fix a few leaks m_freem(m) o minor knf o minor de-knf to match OpenBSD o de__P
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/wi/wi_hostap.c536
-rw-r--r--sys/dev/wi/wi_hostap.h20
2 files changed, 278 insertions, 278 deletions
diff --git a/sys/dev/wi/wi_hostap.c b/sys/dev/wi/wi_hostap.c
index 64a3933..8497095 100644
--- a/sys/dev/wi/wi_hostap.c
+++ b/sys/dev/wi/wi_hostap.c
@@ -81,6 +81,26 @@
MALLOC_DEFINE(M_HAP_STA, "hostap_sta", "if_wi host AP mode station entry");
+static void wihap_sta_timeout(void *v);
+static struct wihap_sta_info *wihap_sta_alloc(struct wi_softc *sc,
+ u_int8_t *addr);
+static void wihap_sta_delete(struct wihap_sta_info *sta);
+static struct wihap_sta_info *wihap_sta_find(struct wihap_info *whi,
+ u_int8_t *addr);
+static int wihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[]);
+static void wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
+ caddr_t pkt, int len);
+static void wihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[],
+ u_int16_t reason);
+static void wihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
+ caddr_t pkt, int len);
+static void wihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,
+ caddr_t pkt, int len);
+static void wihap_sta_disassoc(struct wi_softc *sc,
+ struct wihap_sta_info *sta, u_int16_t reason);
+static void wihap_disassoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,
+ caddr_t pkt, int len);
+
/*
* take_hword()
*
@@ -96,8 +116,7 @@ take_hword(caddr_t *ppkt, int *plen)
return s;
}
-/*
- * take_tlv()
+/* take_tlv()
*
* Parse out TLV element from a packet, check for underflow of packet
* or overflow of buffer, update pkt/len.
@@ -116,15 +135,14 @@ take_tlv(caddr_t *ppkt, int *plen, int id_expect, void *dst, int maxlen)
if (id != id_expect || *plen < len+2 || maxlen < len)
return -1;
- bcopy(*ppkt+2, dst, len);
- *plen -= 2+len;
- *ppkt += 2+len;
+ bcopy(*ppkt + 2, dst, len);
+ *plen -= 2 + len;
+ *ppkt += 2 + len;
- return len;
+ return (len);
}
-/*
- * put_hword()
+/* put_hword()
* Put half-word element into management frames.
*/
static __inline void
@@ -134,8 +152,7 @@ put_hword(caddr_t *ppkt, u_int16_t s)
*ppkt += sizeof(u_int16_t);
}
-/*
- * put_tlv()
+/* put_tlv()
* Put TLV elements into management frames.
*/
static void
@@ -143,15 +160,15 @@ put_tlv(caddr_t *ppkt, u_int8_t id, void *src, u_int8_t len)
{
(*ppkt)[0] = id;
(*ppkt)[1] = len;
- bcopy(src, (*ppkt)+2, len);
- *ppkt += 2+len;
+ bcopy(src, (*ppkt) + 2, len);
+ *ppkt += 2 + len;
}
static int
put_rates(caddr_t *ppkt, u_int16_t rates)
{
- int len = 0;
u_int8_t ratebuf[8];
+ int len = 0;
if (rates & WI_SUPPRATES_1M)
ratebuf[len++] = 0x82;
@@ -166,8 +183,7 @@ put_rates(caddr_t *ppkt, u_int16_t rates)
return len;
}
-/*
- * wihap_init()
+/* wihap_init()
*
* Initialize host AP data structures. Called even if port type is
* not AP.
@@ -189,27 +205,25 @@ wihap_init(struct wi_softc *sc)
whi->apflags = WIHAPFL_ACTIVE;
LIST_INIT(&whi->sta_list);
- for (i=0; i<WI_STA_HASH_SIZE; i++)
+ for (i = 0; i < WI_STA_HASH_SIZE; i++)
LIST_INIT(&whi->sta_hash[i]);
whi->inactivity_time = WIHAP_DFLT_INACTIVITY_TIME;
- whi->hostap_ch = timeout(wihap_timer, sc, hz * WIHAP_INTERVAL);
}
-/*
- * wihap_sta_disassoc()
+/* wihap_sta_disassoc()
*
* Send a disassociation frame to a specified station.
*/
static void
-wihap_sta_disassoc(struct wi_softc *sc, u_int8_t sta_addr[],
- u_int16_t reason)
+wihap_sta_disassoc(struct wi_softc *sc,
+ struct wihap_sta_info *sta, u_int16_t reason)
{
- struct wi_80211_hdr *resp_hdr;
+ struct wi_80211_hdr *resp_hdr;
caddr_t pkt;
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
- printf("Sending disassoc to sta %6D\n", sta_addr, ":");
+ printf("Sending disassoc to sta %6D\n", sta->addr, ":");
/* Send disassoc packet. */
resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf;
@@ -217,25 +231,24 @@ wihap_sta_disassoc(struct wi_softc *sc, u_int8_t sta_addr[],
resp_hdr->frame_ctl = WI_FTYPE_MGMT | WI_STYPE_MGMT_DISAS;
pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr);
- bcopy(sta_addr, resp_hdr->addr1, ETHER_ADDR_LEN);
+ bcopy(sta->addr, resp_hdr->addr1, ETHER_ADDR_LEN);
bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN);
bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN);
put_hword(&pkt, reason);
- wi_mgmt_xmit(sc, sc->wi_txbuf, 2+sizeof(struct wi_80211_hdr));
+ wi_mgmt_xmit(sc, sc->wi_txbuf, 2 + sizeof(struct wi_80211_hdr));
}
-/*
- * wihap_sta_deauth()
+/* wihap_sta_deauth()
*
* Send a deauthentication message to a specified station.
*/
static void
wihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[],
- u_int16_t reason)
+ u_int16_t reason)
{
- struct wi_80211_hdr *resp_hdr;
+ struct wi_80211_hdr *resp_hdr;
caddr_t pkt;
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
@@ -253,39 +266,39 @@ wihap_sta_deauth(struct wi_softc *sc, u_int8_t sta_addr[],
put_hword(&pkt, reason);
- wi_mgmt_xmit(sc, sc->wi_txbuf, 2+sizeof(struct wi_80211_hdr));
+ wi_mgmt_xmit(sc, sc->wi_txbuf, 2 + sizeof(struct wi_80211_hdr));
}
-/*
- * wihap_shutdown()
+/* wihap_shutdown()
*
* Disassociate all stations and free up data structures.
*/
void
wihap_shutdown(struct wi_softc *sc)
{
- struct wihap_info *whi = &sc->wi_hostap_info;
- struct wihap_sta_info *sta, *next;
+ struct wihap_info *whi = &sc->wi_hostap_info;
+ struct wihap_sta_info *sta, *next;
+ int s;
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
printf("wihap_shutdown: sc=0x%x whi=0x%x\n",
- (int)sc, (int)whi);
+ (int)sc, (int)whi);
if (!(whi->apflags & WIHAPFL_ACTIVE))
return;
- /*
- * XXX: I read somewhere you can deauth all the stations with
+ /* XXX: I read somewhere you can deauth all the stations with
* a single broadcast. Maybe try that someday.
*/
+ s = splimp();
sta = LIST_FIRST(&whi->sta_list);
while (sta) {
-
+ untimeout(wihap_sta_timeout, sta, sta->tmo);
if (!sc->wi_gone) {
/* Disassociate station. */
if (sta->flags & WI_SIFLAGS_ASSOC)
- wihap_sta_disassoc(sc, sta->addr,
+ wihap_sta_disassoc(sc, sta,
IEEE80211_REASON_ASSOC_LEAVE);
/* Deauth station. */
if (sta->flags & WI_SIFLAGS_AUTHEN)
@@ -295,19 +308,16 @@ wihap_shutdown(struct wi_softc *sc)
/* Delete the structure. */
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
- printf("wihap_shutdown: FREE(sta=0x%x)\n", (int) sta);
+ printf("wihap_shutdown: FREE(sta=0x%x)\n", (int)sta);
next = LIST_NEXT(sta, list);
FREE(sta, M_HAP_STA);
sta = next;
}
- untimeout(wihap_timer, sc, whi->hostap_ch);
-
whi->apflags = 0;
}
-/*
- * sta_hash_func()
+/* sta_hash_func()
* Hash function for finding stations from ethernet address.
*/
static __inline int
@@ -316,26 +326,65 @@ sta_hash_func(u_int8_t addr[])
return ((addr[3] + addr[4] + addr[5]) % WI_STA_HASH_SIZE);
}
-/*
- * addr_cmp():
- * Maybe this is a faster way to compare addresses?
- */
+/* addr_cmp(): Maybe this is a faster way to compare addresses? */
static __inline int
addr_cmp(u_int8_t a[], u_int8_t b[])
{
- return (*(u_int16_t *)(a+4) == *(u_int16_t *)(b+4) &&
- *(u_int32_t *)a == *(u_int32_t *)b);
+ return (*(u_int16_t *)(a + 4) == *(u_int16_t *)(b + 4) &&
+ *(u_int32_t *)(a ) == *(u_int32_t *)(b));
}
-/*
- * wihap_sta_delete()
+void
+wihap_sta_timeout(void *v)
+{
+ struct wihap_sta_info *sta = v;
+ struct wi_softc *sc = sta->sc;
+ struct wihap_info *whi = &sc->wi_hostap_info;
+ int s;
+
+ s = splnet();
+ if (sta->flags & WI_SIFLAGS_ASSOC) {
+ if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
+ device_printf(sc->dev, "inactivity disassoc: %6D\n",
+ sta->addr, ":");
+
+ /* Disassoc station. */
+ wihap_sta_disassoc(sc, sta, IEEE80211_REASON_ASSOC_EXPIRE);
+ sta->flags &= ~WI_SIFLAGS_ASSOC;
+
+ sta->tmo = timeout(wihap_sta_timeout, sta,
+ hz * whi->inactivity_time);
+
+ } else if (sta->flags & WI_SIFLAGS_AUTHEN) {
+
+ if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
+ device_printf(sc->dev, "inactivity disassoc: %6D\n",
+ sta->addr, ":");
+
+ /* Deauthenticate station. */
+ wihap_sta_deauth(sc, sta->addr, IEEE80211_REASON_AUTH_EXPIRE);
+ sta->flags &= ~WI_SIFLAGS_AUTHEN;
+
+ /* Delete the station if it's not permanent. */
+ if (!(sta->flags & WI_SIFLAGS_PERM))
+ wihap_sta_delete(sta);
+ }
+ splx(s);
+}
+
+/* wihap_sta_delete()
* Delete a single station and free up its data structure.
*/
static void
-wihap_sta_delete(struct wihap_info *whi, struct wihap_sta_info *sta)
+wihap_sta_delete(struct wihap_sta_info *sta)
{
+ struct wi_softc *sc = sta->sc;
+ struct wihap_info *whi = &sc->wi_hostap_info;
int i = sta->asid - 0xc001;
- whi->asid_inuse_mask[i>>4] &= ~(1ul<<(i&0xf));
+
+ untimeout(wihap_sta_timeout, sta, sta->tmo);
+
+ whi->asid_inuse_mask[i >> 4] &= ~(1UL << (i & 0xf));
LIST_REMOVE(sta, list);
LIST_REMOVE(sta, hash);
@@ -343,22 +392,21 @@ wihap_sta_delete(struct wihap_info *whi, struct wihap_sta_info *sta)
whi->n_stations--;
}
-/*
- * wihap_sta_alloc()
+/* wihap_sta_alloc()
*
* Create a new station data structure and put it in the list
* and hash table.
*/
static struct wihap_sta_info *
-wihap_sta_alloc(struct wihap_info *whi, u_int8_t *addr)
+wihap_sta_alloc(struct wi_softc *sc, u_int8_t *addr)
{
- int i;
- int hash = sta_hash_func(addr);
- struct wihap_sta_info *sta;
+ struct wihap_info *whi = &sc->wi_hostap_info;
+ struct wihap_sta_info *sta;
+ int i, hash = sta_hash_func(addr);
/* Allocate structure. */
MALLOC(sta, struct wihap_sta_info *, sizeof(struct wihap_sta_info),
- M_HAP_STA, M_NOWAIT);
+ M_HAP_STA, M_NOWAIT);
if (sta == NULL)
return(NULL);
@@ -366,15 +414,16 @@ wihap_sta_alloc(struct wihap_info *whi, u_int8_t *addr)
/* Allocate an ASID. */
i=hash<<4;
- while (whi->asid_inuse_mask[i>>4] & (1ul<<(i&0xf)))
- i = (i==(WI_STA_HASH_SIZE<<4)-1) ? 0 : (i+1);
- whi->asid_inuse_mask[i>>4] |= (1ul<<(i&0xf));
- sta->asid = 0xc001+i;
+ while (whi->asid_inuse_mask[i >> 4] & (1UL << (i & 0xf)))
+ i = (i == (WI_STA_HASH_SIZE << 4) - 1) ? 0 : (i + 1);
+ whi->asid_inuse_mask[i >> 4] |= (1UL << (i & 0xf));
+ sta->asid = 0xc001 + i;
/* Insert in list and hash list. */
LIST_INSERT_HEAD(&whi->sta_list, sta, list);
LIST_INSERT_HEAD(&whi->sta_hash[hash], sta, hash);
+ sta->sc = sc;
whi->n_stations++;
bcopy(addr, &sta->addr, ETHER_ADDR_LEN);
sta->inactivity_timer = whi->inactivity_time;
@@ -382,8 +431,7 @@ wihap_sta_alloc(struct wihap_info *whi, u_int8_t *addr)
return(sta);
}
-/*
- * wihap_sta_find()
+/* wihap_sta_find()
*
* Find station structure given address.
*/
@@ -398,80 +446,13 @@ wihap_sta_find(struct wihap_info *whi, u_int8_t *addr)
if (addr_cmp(addr,sta->addr))
return sta;
- return(NULL);
-}
-
-/*
- * wihap_timer()
- *
- * Called every WIHAP_INTERVAL seconds. Look for inactive
- * stations and disassociate them.
- */
-void
-wihap_timer(void *xsc)
-{
- int s;
- struct wihap_sta_info *sta, *next;
- struct wi_softc *sc = (struct wi_softc *) xsc;
- struct wihap_info *whi = &sc->wi_hostap_info;
-
- s = splimp();
-
- sta = LIST_FIRST(&whi->sta_list);
- while (sta) {
-
- /* Grab next station now just in case we delete it. */
- next = LIST_NEXT(sta, list);
-
- if (sta->inactivity_timer >= 0) {
- if (--sta->inactivity_timer == 0) {
-
- if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
- printf("wihap_timer: disassoc due to "
- "inactivity: %6D\n",
- sta->addr, ":");
-
- if (sta->flags & WI_SIFLAGS_ASSOC) {
- /* Disassoc station. */
- wihap_sta_disassoc(sc, sta->addr,
- IEEE80211_REASON_ASSOC_EXPIRE);
-
- sta->flags &= ~WI_SIFLAGS_ASSOC;
- }
- }
- else if (sta->inactivity_timer == -1) {
-
- if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
- printf("wihap_timer: deauth due to "
- "inactivity: %6D\n",
- sta->addr, ":");
-
- if (sta->flags & WI_SIFLAGS_AUTHEN) {
- /* Deauthenticate station. */
- wihap_sta_deauth(sc, sta->addr,
- IEEE80211_REASON_AUTH_EXPIRE);
-
- sta->flags &= ~WI_SIFLAGS_AUTHEN;
- }
-
- /* Delete the station if it's not permanent. */
- if (!(sta->flags & WI_SIFLAGS_PERM))
- wihap_sta_delete(whi, sta);
- }
- }
-
- sta = next;
- }
-
- splx(s);
-
- whi->hostap_ch = timeout(wihap_timer, sc, hz * WIHAP_INTERVAL);
+ return (NULL);
}
static int
-wihap_check_rates(struct wi_softc *sc, struct wihap_sta_info *sta,
- u_int8_t rates[], int rates_len)
+wihap_check_rates(struct wihap_sta_info *sta, u_int8_t rates[], int rates_len)
{
+ struct wi_softc *sc = sta->sc;
int i;
sta->rates = 0;
@@ -504,15 +485,14 @@ wihap_check_rates(struct wi_softc *sc, struct wihap_sta_info *sta,
}
-/*
- * wihap_auth_req()
+/* wihap_auth_req()
*
* Handle incoming authentication request. Only handle OPEN
* requests.
*/
static void
wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
- caddr_t pkt, int len)
+ caddr_t pkt, int len)
{
struct wihap_info *whi = &sc->wi_hostap_info;
struct wihap_sta_info *sta;
@@ -523,24 +503,23 @@ wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
int challenge_len;
u_int8_t challenge[128];
- struct wi_80211_hdr *resp_hdr;
+ struct wi_80211_hdr *resp_hdr;
- if (len<6)
+ if (len < 6)
return;
/* Break open packet. */
algo = take_hword(&pkt, &len);
seq = take_hword(&pkt, &len);
status = take_hword(&pkt, &len);
- challenge_len=0;
- if (len>0 && (challenge_len=take_tlv(&pkt, &len,
- IEEE80211_ELEMID_CHALLENGE,
- challenge, sizeof(challenge)))<0)
+ challenge_len = 0;
+ if (len > 0 && (challenge_len = take_tlv(&pkt, &len,
+ IEEE80211_ELEMID_CHALLENGE, challenge, sizeof(challenge))) < 0)
return;
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
printf("wihap_auth_req: from station: %6D\n",
- rxfrm->wi_addr2, ":");
+ rxfrm->wi_addr2, ":");
switch (algo) {
case IEEE80211_AUTH_ALG_OPEN:
@@ -548,14 +527,14 @@ wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
status = IEEE80211_STATUS_SEQUENCE;
goto fail;
}
- challenge_len=0;
+ challenge_len = 0;
break;
case IEEE80211_AUTH_ALG_SHARED:
/* NOT YET */
default:
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
printf("wihap_auth_req: algorithm unsupported: %d\n",
- algo);
+ algo);
status = IEEE80211_STATUS_ALG;
goto fail;
}
@@ -581,7 +560,7 @@ wihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
printf("wihap_auth_req: new station\n");
/* Create new station. */
- sta = wihap_sta_alloc(whi, rxfrm->wi_addr2);
+ sta = wihap_sta_alloc(sc, rxfrm->wi_addr2);
if (sta == NULL) {
/* Out of memory! */
status = IEEE80211_STATUS_TOO_MANY_STATIONS;
@@ -600,28 +579,25 @@ fail:
/* Send response. */
resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf;
bzero(resp_hdr, sizeof(struct wi_80211_hdr));
- resp_hdr->frame_ctl = WI_FTYPE_MGMT | WI_STYPE_MGMT_AUTH;
- pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr);
-
+ resp_hdr->frame_ctl = htole16(WI_FTYPE_MGMT | WI_STYPE_MGMT_AUTH);
bcopy(rxfrm->wi_addr2, resp_hdr->addr1, ETHER_ADDR_LEN);
bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr2, ETHER_ADDR_LEN);
bcopy(sc->arpcom.ac_enaddr, resp_hdr->addr3, ETHER_ADDR_LEN);
+ pkt = &sc->wi_txbuf[sizeof(struct wi_80211_hdr)];
put_hword(&pkt, algo);
put_hword(&pkt, 2);
put_hword(&pkt, status);
if (challenge_len>0)
put_tlv(&pkt, IEEE80211_ELEMID_CHALLENGE,
- challenge, challenge_len);
+ challenge, challenge_len);
- wi_mgmt_xmit(sc, sc->wi_txbuf,
- 6 + sizeof(struct wi_80211_hdr) +
- (challenge_len>0 ? challenge_len+2 : 0) );
+ wi_mgmt_xmit(sc, sc->wi_txbuf, 6 + sizeof(struct wi_80211_hdr) +
+ (challenge_len > 0 ? challenge_len + 2 : 0) );
}
-/*
- * wihap_assoc_req()
+/* wihap_assoc_req()
*
* Handle incoming association and reassociation requests.
*/
@@ -631,49 +607,45 @@ wihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,
{
struct wihap_info *whi = &sc->wi_hostap_info;
struct wihap_sta_info *sta;
-
- struct wi_80211_hdr *resp_hdr;
-
+ struct wi_80211_hdr *resp_hdr;
u_int16_t capinfo;
u_int16_t lstintvl;
u_int8_t rates[8];
- int rates_len;
- int ssid_len;
- char ssid[33];
-
-
+ int ssid_len, rates_len;
+ struct ieee80211_nwid ssid;
u_int16_t status;
u_int16_t asid = 0;
- if (len<8)
+ if (len < 8)
return;
/* Pull out request parameters. */
capinfo = take_hword(&pkt, &len);
lstintvl = take_hword(&pkt, &len);
- if ((ssid_len=take_tlv(&pkt, &len, IEEE80211_ELEMID_SSID,
- ssid, sizeof(ssid)-1))<0)
+ if ((ssid_len = take_tlv(&pkt, &len, IEEE80211_ELEMID_SSID,
+ ssid.i_nwid, sizeof(ssid)))<0)
return;
- ssid[ssid_len] = '\0';
- if ((rates_len=take_tlv(&pkt, &len, IEEE80211_ELEMID_RATES,
- rates, sizeof(rates)))<0)
+ ssid.i_len = ssid_len;
+ if ((rates_len = take_tlv(&pkt, &len, IEEE80211_ELEMID_RATES,
+ rates, sizeof(rates)))<0)
return;
- if ((rxfrm->wi_frame_ctl & WI_FCTL_STYPE) == WI_STYPE_MGMT_REASREQ) {
- /* Reassociation Request--
- * Current AP. (Ignore?)
- */
- if (len<6)
+
+ if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_STYPE)) ==
+ htole16(WI_STYPE_MGMT_REASREQ)) {
+ /* Reassociation Request-- * Current AP. (Ignore?) */
+ if (len < 6)
return;
}
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
printf("wihap_assoc_req: from station %6D\n",
- rxfrm->wi_addr2, ":");
+ rxfrm->wi_addr2, ":");
/* If SSID doesn't match, simply drop. */
- if (strcmp(sc->wi_net_name, ssid) != 0) {
+ if (strcmp(sc->wi_net_name, ssid.i_nwid) != 0) {
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
- printf("wihap_assoc_req: bad ssid: '%s'\n", ssid);
+ printf("wihap_assoc_req: bad ssid: '%s' != '%s'\n",
+ ssid.i_nwid, sc->wi_net_name);
return;
}
@@ -681,36 +653,43 @@ wihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,
sta = wihap_sta_find(whi, rxfrm->wi_addr2);
if (sta == NULL || !(sta->flags & WI_SIFLAGS_AUTHEN)) {
wihap_sta_deauth(sc, rxfrm->wi_addr2,
- IEEE80211_REASON_NOT_AUTHED);
+ IEEE80211_REASON_NOT_AUTHED);
return;
}
+ /* Check supported rates against ours. */
+ if (wihap_check_rates(sta, rates, rates_len) < 0) {
+ status = IEEE80211_STATUS_RATES;
+ goto fail;
+ }
+
/* Check capinfo.
* Check for ESS, not IBSS.
- * Check WEP/PRIVACY flags match. XXX: WEP doesn't work for host AP.
+ * Check WEP/PRIVACY flags match.
* Refuse stations requesting to be put on CF-polling list.
*/
- if ((capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) !=
- IEEE80211_CAPINFO_ESS ||
- (sc->wi_use_wep && !(capinfo & IEEE80211_CAPINFO_PRIVACY)) ||
- (!sc->wi_use_wep && (capinfo & IEEE80211_CAPINFO_PRIVACY)) ||
- (capinfo & (IEEE80211_CAPINFO_CF_POLLABLE|
- IEEE80211_CAPINFO_CF_POLLREQ)) ==
- IEEE80211_CAPINFO_CF_POLLABLE) {
-
+ sta->capinfo = capinfo;
+ status = IEEE80211_STATUS_CAPINFO;
+ if ((capinfo & (IEEE80211_CAPINFO_ESS | IEEE80211_CAPINFO_IBSS)) !=
+ IEEE80211_CAPINFO_ESS) {
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
printf("wihap_assoc_req: capinfo mismatch: "
- "capinfo=0x%x\n", capinfo);
+ "client using IBSS mode\n");
+ goto fail;
- status = IEEE80211_STATUS_CAPINFO;
+ }
+ if ((sc->wi_use_wep && !(capinfo & IEEE80211_CAPINFO_PRIVACY)) ||
+ (!sc->wi_use_wep && (capinfo & IEEE80211_CAPINFO_PRIVACY))) {
+ if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
+ printf("wihap_assoc_req: capinfo mismatch: client "
+ "%susing WEP\n", sc->wi_use_wep ? "not " : "");
goto fail;
}
- sta->capinfo = capinfo;
-
-
- /* Check supported rates against ours. */
- if (wihap_check_rates(sc, sta, rates, rates_len)<0) {
- status = IEEE80211_STATUS_RATES;
+ if ((capinfo & (IEEE80211_CAPINFO_CF_POLLABLE |
+ IEEE80211_CAPINFO_CF_POLLREQ)) == IEEE80211_CAPINFO_CF_POLLABLE) {
+ if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
+ printf("wihap_assoc_req: capinfo mismatch: "
+ "client requested CF polling\n");
goto fail;
}
@@ -733,7 +712,7 @@ fail:
/* Send response. */
resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf;
bzero(resp_hdr, sizeof(struct wi_80211_hdr));
- resp_hdr->frame_ctl = WI_FTYPE_MGMT | WI_STYPE_MGMT_ASRESP;
+ resp_hdr->frame_ctl = htole16(WI_FTYPE_MGMT | WI_STYPE_MGMT_ASRESP);
pkt = sc->wi_txbuf + sizeof(struct wi_80211_hdr);
bcopy(rxfrm->wi_addr2, resp_hdr->addr1, ETHER_ADDR_LEN);
@@ -743,14 +722,13 @@ fail:
put_hword(&pkt, capinfo);
put_hword(&pkt, status);
put_hword(&pkt, asid);
- rates_len=put_rates(&pkt, sc->wi_supprates);
+ rates_len = put_rates(&pkt, sc->wi_supprates);
wi_mgmt_xmit(sc, sc->wi_txbuf,
- 8+rates_len+sizeof(struct wi_80211_hdr));
+ 8 + rates_len + sizeof(struct wi_80211_hdr));
}
-/*
- * wihap_deauth_req()
+/* wihap_deauth_req()
*
* Handle deauthentication requests. Delete the station.
*/
@@ -760,7 +738,7 @@ wihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
{
struct wihap_info *whi = &sc->wi_hostap_info;
struct wihap_sta_info *sta;
- u_int16_t reason;
+ u_int16_t reason;
if (len<2)
return;
@@ -771,14 +749,13 @@ wihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
if (sta == NULL) {
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
printf("wihap_deauth_req: unknown station: 6D\n",
- rxfrm->wi_addr2, ":");
+ rxfrm->wi_addr2, ":");
}
else
- wihap_sta_delete(whi, sta);
+ wihap_sta_delete(sta);
}
-/*
- * wihap_disassoc_req()
+/* wihap_disassoc_req()
*
* Handle disassociation requests. Just reset the assoc flag.
* We'll free up the station resources when we get a deauth
@@ -786,13 +763,13 @@ wihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm,
*/
static void
wihap_disassoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,
- caddr_t pkt, int len)
+ caddr_t pkt, int len)
{
struct wihap_info *whi = &sc->wi_hostap_info;
struct wihap_sta_info *sta;
- u_int16_t reason;
+ u_int16_t reason;
- if (len<2)
+ if (len < 2)
return;
reason = take_hword(&pkt, &len);
@@ -801,31 +778,32 @@ wihap_disassoc_req(struct wi_softc *sc, struct wi_frame *rxfrm,
if (sta == NULL) {
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
printf("wihap_disassoc_req: unknown station: 6D\n",
- rxfrm->wi_addr2, ":");
+ rxfrm->wi_addr2, ":");
}
else if (!(sta->flags & WI_SIFLAGS_AUTHEN)) {
- /* If station is not authenticated, send deauthentication
+ /*
+ * If station is not authenticated, send deauthentication
* frame.
*/
wihap_sta_deauth(sc, rxfrm->wi_addr2,
- IEEE80211_REASON_NOT_AUTHED);
+ IEEE80211_REASON_NOT_AUTHED);
return;
}
else
sta->flags &= ~WI_SIFLAGS_ASSOC;
}
-/*
- * wihap_debug_frame_type()
+/* wihap_debug_frame_type()
*
* Print out frame type. Used in early debugging.
*/
-static void
+static __inline void
wihap_debug_frame_type(struct wi_frame *rxfrm)
{
- printf("wihap_mgmt_input: len=%d ", rxfrm->wi_dat_len);
+ printf("wihap_mgmt_input: len=%d ", le16toh(rxfrm->wi_dat_len));
- if ((le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_FTYPE) == WI_FTYPE_MGMT) {
+ if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_FTYPE)) ==
+ htole16(WI_FTYPE_MGMT)) {
printf("MGMT: ");
@@ -865,19 +843,18 @@ wihap_debug_frame_type(struct wi_frame *rxfrm)
break;
default:
printf("unknown (stype=0x%x)\n",
- le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE);
+ le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE);
}
}
else {
printf("ftype=0x%x (ctl=0x%x)\n",
- le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_FTYPE,
- le16toh(rxfrm->wi_frame_ctl));
+ le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_FTYPE,
+ le16toh(rxfrm->wi_frame_ctl));
}
}
-/*
- * wihap_mgmt_input:
+/* wihap_mgmt_input:
*
* Called for each management frame received in host ap mode.
* wihap_mgmt_input() is expected to free the mbuf.
@@ -885,8 +862,8 @@ wihap_debug_frame_type(struct wi_frame *rxfrm)
void
wihap_mgmt_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m)
{
- caddr_t pkt;
- int len;
+ caddr_t pkt;
+ int s, len;
if (sc->arpcom.ac_if.if_flags & IFF_DEBUG)
wihap_debug_frame_type(rxfrm);
@@ -894,8 +871,11 @@ wihap_mgmt_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m)
pkt = mtod(m, caddr_t) + WI_802_11_OFFSET_RAW;
len = m->m_len - WI_802_11_OFFSET_RAW;
- if ((rxfrm->wi_frame_ctl & WI_FCTL_FTYPE) == WI_FTYPE_MGMT) {
+ if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_FTYPE)) ==
+ htole16(WI_FTYPE_MGMT)) {
+ /* any of the following will mess w/ the station list */
+ s = splsoftclock();
switch (le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE) {
case WI_STYPE_MGMT_ASREQ:
wihap_assoc_req(sc, rxfrm, pkt, len);
@@ -925,14 +905,13 @@ wihap_mgmt_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m)
wihap_deauth_req(sc, rxfrm, pkt, len);
break;
}
-
+ splx(s);
}
m_freem(m);
}
-/*
- * wihap_sta_is_assoc()
+/* wihap_sta_is_assoc()
*
* Determine if a station is assoc'ed. Update its activity
* counter as a side-effect.
@@ -943,17 +922,18 @@ wihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[])
struct wihap_sta_info *sta;
sta = wihap_sta_find(whi, addr);
- if (sta!=NULL && (sta->flags & WI_SIFLAGS_ASSOC)) {
+ if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) {
/* Keep it active. */
sta->inactivity_timer = whi->inactivity_time;
+ sta->tmo = timeout(wihap_sta_timeout, sta,
+ hz * whi->inactivity_time);
return(1);
}
else
return(0);
}
-/*
- * wihap_check_tx()
+/* wihap_check_tx()
*
* Determine if a station is assoc'ed, get its tx rate, and update
* its activity.
@@ -963,18 +943,24 @@ wihap_check_tx(struct wihap_info *whi, u_int8_t addr[], u_int8_t *txrate)
{
struct wihap_sta_info *sta;
static u_int8_t txratetable[] = { 10, 20, 55, 110 };
+ int s;
+ s = splclock();
if (addr[0] & 0x01) {
*txrate = 0; /* XXX: multicast rate? */
return(1);
}
sta = wihap_sta_find(whi, addr);
- if (sta!=NULL && (sta->flags & WI_SIFLAGS_ASSOC)) {
+ if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) {
/* Keep it active. */
- sta->inactivity_timer = whi->inactivity_time;
+ sta->tmo = timeout(wihap_sta_timeout, sta,
+ hz * whi->inactivity_time);
*txrate = txratetable[ sta->tx_curr_rate ];
+ splx(s);
return(1);
}
+ splx(s);
+
return(0);
}
@@ -993,14 +979,15 @@ wihap_data_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
struct wihap_info *whi = &sc->wi_hostap_info;
- struct wihap_sta_info *sta;
- int mcast;
+ struct wihap_sta_info *sta;
+ int mcast, s;
/* TODS flag must be set. */
- if (!(le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_TODS)) {
+ if (!(rxfrm->wi_frame_ctl & htole16(WI_FCTL_TODS))) {
if (ifp->if_flags & IFF_DEBUG)
printf("wihap_data_input: no TODS src=%6D\n",
- rxfrm->wi_addr2, ":");
+ rxfrm->wi_addr2, ":");
+ m_freem(m);
return(1);
}
@@ -1009,9 +996,12 @@ wihap_data_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m)
if (ifp->if_flags & IFF_DEBUG)
printf("wihap_data_input: incorrect bss: %6D\n",
rxfrm->wi_addr1, ":");
- return(1);
+ m_freem(m);
+ return (1);
}
+ s = splsoftclock();
+
/* Find source station. */
sta = wihap_sta_find(whi, rxfrm->wi_addr2);
@@ -1019,12 +1009,17 @@ wihap_data_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m)
if (sta == NULL || !(sta->flags & WI_SIFLAGS_ASSOC)) {
if (ifp->if_flags & IFF_DEBUG)
printf("wihap_data_input: dropping unassoc src %6D\n",
- rxfrm->wi_addr2, ":");
+ rxfrm->wi_addr2, ":");
+ splx(s);
+ m_freem(m);
return(1);
}
- sta->inactivity_timer = whi->inactivity_time;
- sta->sig_info = rxfrm->wi_q_info;
+ sta->tmo = timeout(wihap_sta_timeout, sta,
+ hz * whi->inactivity_time);
+ sta->sig_info = le16toh(rxfrm->wi_q_info);
+
+ splx(s);
/* Repeat this packet to BSS? */
mcast = (rxfrm->wi_addr3[0] & 0x01) != 0;
@@ -1045,26 +1040,23 @@ wihap_data_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m)
return (!mcast);
}
- return (0);
+ return(0);
}
-/*
- * wihap_ioctl()
+/* wihap_ioctl()
*
* Handle Host AP specific ioctls. Called from wi_ioctl().
*/
int
wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data)
{
- int error = 0;
struct ifreq *ifr = (struct ifreq *) data;
- struct wihap_info *whi = &sc->wi_hostap_info;
- struct wihap_sta_info *sta;
- struct hostap_getall reqall;
- struct hostap_sta reqsta;
- struct hostap_sta stabuf;
- int n;
- int flag;
+ struct wihap_info *whi = &sc->wi_hostap_info;
+ struct wihap_sta_info *sta;
+ struct hostap_getall reqall;
+ struct hostap_sta reqsta;
+ struct hostap_sta stabuf;
+ int s, error = 0, n, flag;
if (!(sc->arpcom.ac_if.if_flags & IFF_RUNNING))
return ENODEV;
@@ -1075,26 +1067,29 @@ wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data)
break;
if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta))))
break;
+ s = splimp();
sta = wihap_sta_find(whi, reqsta.addr);
if (sta == NULL)
error = ENOENT;
else {
/* Disassociate station. */
if (sta->flags & WI_SIFLAGS_ASSOC)
- wihap_sta_disassoc(sc, sta->addr,
- IEEE80211_REASON_ASSOC_LEAVE);
+ wihap_sta_disassoc(sc, sta,
+ IEEE80211_REASON_ASSOC_LEAVE);
/* Deauth station. */
if (sta->flags & WI_SIFLAGS_AUTHEN)
wihap_sta_deauth(sc, sta->addr,
- IEEE80211_REASON_AUTH_LEAVE);
+ IEEE80211_REASON_AUTH_LEAVE);
- wihap_sta_delete(whi, sta);
+ wihap_sta_delete(sta);
}
+ splx(s);
break;
case SIOCHOSTAP_GET:
if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta))))
break;
+ s = splimp();
sta = wihap_sta_find(whi, reqsta.addr);
if (sta == NULL)
error = ENOENT;
@@ -1106,8 +1101,9 @@ wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data)
reqsta.rates = sta->rates;
error = copyout(&reqsta, ifr->ifr_data,
- sizeof(reqsta));
+ sizeof(reqsta));
}
+ splx(s);
break;
case SIOCHOSTAP_ADD:
@@ -1115,18 +1111,23 @@ wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data)
break;
if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta))))
break;
+ s = splimp();
sta = wihap_sta_find(whi, reqsta.addr);
if (sta != NULL) {
error = EEXIST;
+ splx(s);
break;
}
if (whi->n_stations >= WIHAP_MAX_STATIONS) {
error = ENOSPC;
+ splx(s);
break;
}
- sta = wihap_sta_alloc(whi, reqsta.addr);
+ sta = wihap_sta_alloc(sc, reqsta.addr);
sta->flags = reqsta.flags;
- sta->inactivity_timer = whi->inactivity_time;
+ sta->tmo = timeout(wihap_sta_timeout, sta,
+ hz * whi->inactivity_time);
+ splx(s);
break;
case SIOCHOSTAP_SFLAGS:
@@ -1135,9 +1136,8 @@ wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data)
if ((error = copyin(ifr->ifr_data, &flag, sizeof(int))))
break;
- whi->apflags =
- (whi->apflags & WIHAPFL_CANTCHANGE) |
- (flag & ~WIHAPFL_CANTCHANGE);
+ whi->apflags = (whi->apflags & WIHAPFL_CANTCHANGE) |
+ (flag & ~WIHAPFL_CANTCHANGE);
break;
case SIOCHOSTAP_GFLAGS:
@@ -1151,6 +1151,7 @@ wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data)
reqall.nstations = whi->n_stations;
n = 0;
+ s = splimp();
sta = LIST_FIRST(&whi->sta_list);
while (sta && reqall.size >= n+sizeof(struct hostap_sta)) {
@@ -1162,17 +1163,18 @@ wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data)
stabuf.rates = sta->rates;
error = copyout(&stabuf, (caddr_t) reqall.addr + n,
- sizeof(struct hostap_sta));
+ sizeof(struct hostap_sta));
if (error)
break;
sta = LIST_NEXT(sta, list);
n += sizeof(struct hostap_sta);
}
+ splx(s);
if (!error)
error = copyout(&reqall, ifr->ifr_data,
- sizeof(reqall));
+ sizeof(reqall));
break;
default:
printf("wihap_ioctl: i shouldn't get other ioctls!\n");
diff --git a/sys/dev/wi/wi_hostap.h b/sys/dev/wi/wi_hostap.h
index 493b5ad..4338499 100644
--- a/sys/dev/wi/wi_hostap.h
+++ b/sys/dev/wi/wi_hostap.h
@@ -77,6 +77,7 @@ struct wihap_sta_info {
LIST_ENTRY(wihap_sta_info) list;
LIST_ENTRY(wihap_sta_info) hash;
+ struct wi_softc *sc;
u_int8_t addr[6];
u_short flags;
int inactivity_timer;
@@ -87,6 +88,7 @@ struct wihap_sta_info {
u_int8_t rates;
u_int8_t tx_curr_rate;
u_int8_t tx_max_rate;
+ struct callout_handle tmo;
};
#define WI_SIFLAGS_ASSOC HOSTAP_FLAGS_ASSOC
@@ -112,7 +114,6 @@ struct wihap_info {
u_int16_t asid_inuse_mask[WI_STA_HASH_SIZE];
int inactivity_time;
- struct callout_handle hostap_ch;
};
#define WIHAP_INTERVAL 5
@@ -121,16 +122,13 @@ struct wihap_info {
struct wi_softc;
struct wi_frame;
-void wihap_timer __P((void *));
-void wihap_mgmt_input __P((struct wi_softc *, struct wi_frame *,
- struct mbuf *));
-int wihap_data_input __P((struct wi_softc *, struct wi_frame *,
- struct mbuf *));
-int wihap_check_tx __P((struct wihap_info *, u_int8_t [],
- u_int8_t *));
-void wihap_init __P((struct wi_softc *));
-void wihap_shutdown __P((struct wi_softc *));
-int wihap_ioctl __P((struct wi_softc *, u_long, caddr_t));
+void wihap_timer(void *);
+void wihap_mgmt_input(struct wi_softc *, struct wi_frame *, struct mbuf *);
+int wihap_data_input(struct wi_softc *, struct wi_frame *, struct mbuf *);
+int wihap_check_tx(struct wihap_info *, u_int8_t [], u_int8_t *);
+void wihap_init(struct wi_softc *);
+void wihap_shutdown(struct wi_softc *);
+int wihap_ioctl(struct wi_softc *, u_long, caddr_t);
#endif /* _KERNEL */
#endif /* __WI_HOSTAP_H__ */
OpenPOWER on IntegriCloud