📄 wi_hostap.c
字号:
IEEE80211_REASON_ASSOC_EXPIRE); sta->flags &= ~WI_SIFLAGS_ASSOC;#ifdef WICACHE saveDisassocTime(sc, sta->addr);#endif 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 voidwihap_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; untimeout(wihap_sta_timeout, sta, sta->tmo); whi->asid_inuse_mask[i >> 4] &= ~(1UL << (i & 0xf)); LIST_REMOVE(sta, list); LIST_REMOVE(sta, hash); if (sta->challenge) FREE(sta->challenge, M_TEMP); FREE(sta, M_HAP_STA); whi->n_stations--;}/* 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 wi_softc *sc, u_int8_t *addr){ 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); if (sta == NULL) return(NULL); bzero(sta, sizeof(struct wihap_sta_info)); /* 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; /* 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); return(sta);}/* wihap_sta_find() * * Find station structure given address. */static struct wihap_sta_info *wihap_sta_find(struct wihap_info *whi, u_int8_t *addr){ int i; struct wihap_sta_info *sta; i = sta_hash_func(addr); LIST_FOREACH(sta, &whi->sta_hash[i], hash) if (addr_cmp(addr,sta->addr)) return sta; return (NULL);}static intwihap_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; sta->tx_max_rate = 0; for (i=0; i<rates_len; i++) switch (rates[i] & 0x7f) { case 0x02: sta->rates |= WI_SUPPRATES_1M; break; case 0x04: sta->rates |= WI_SUPPRATES_2M; if (sta->tx_max_rate<1) sta->tx_max_rate = 1; break; case 0x0b: sta->rates |= WI_SUPPRATES_5M; if (sta->tx_max_rate<2) sta->tx_max_rate = 2; break; case 0x16: sta->rates |= WI_SUPPRATES_11M; sta->tx_max_rate = 3; break; } sta->rates &= sc->wi_supprates; sta->tx_curr_rate = sta->tx_max_rate; return (sta->rates == 0 ? -1 : 0);}/* wihap_auth_req() * * Handle incoming authentication request. Only handle OPEN * requests. */static voidwihap_auth_req(struct wi_softc *sc, struct wi_frame *rxfrm, caddr_t pkt, int len){ struct wihap_info *whi = &sc->wi_hostap_info; struct wihap_sta_info *sta; u_int16_t algo; u_int16_t seq; u_int16_t status; int i, challenge_len; u_int32_t challenge[32]; struct wi_80211_hdr *resp_hdr; 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) return; if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_auth_req: station %6D algo=0x%x seq=0x%x\n", rxfrm->wi_addr2, ":", algo, seq); /* Find or create station info. */ sta = wihap_sta_find(whi, rxfrm->wi_addr2); if (sta == NULL) { /* Are we allowing new stations? */ if (whi->apflags & WIHAPFL_MAC_FILT) { status = IEEE80211_STATUS_OTHER; /* XXX */ goto fail; } /* Check for too many stations. */ if (whi->n_stations >= WIHAP_MAX_STATIONS) { status = IEEE80211_STATUS_TOO_MANY_STATIONS; goto fail; } if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_auth_req: new station\n"); /* Create new station. */ sta = wihap_sta_alloc(sc, rxfrm->wi_addr2); if (sta == NULL) { /* Out of memory! */ status = IEEE80211_STATUS_TOO_MANY_STATIONS; goto fail; } } /* Note: it's okay to leave the station info structure around * if the authen fails. It'll be timed out eventually. */ switch (algo) { case IEEE80211_AUTH_ALG_OPEN: if (sc->wi_authmode != IEEE80211_AUTH_OPEN) { seq = 2; status = IEEE80211_STATUS_ALG; goto fail; } if (seq != 1) { seq = 2; status = IEEE80211_STATUS_SEQUENCE; goto fail; } challenge_len = 0; seq = 2; sta->flags |= WI_SIFLAGS_AUTHEN; break; case IEEE80211_AUTH_ALG_SHARED: if (sc->wi_authmode != IEEE80211_AUTH_SHARED) { seq = 2; status = IEEE80211_STATUS_ALG; goto fail; } switch (seq) { case 1: /* Create a challenge frame. */ if (!sta->challenge) { MALLOC(sta->challenge, u_int32_t *, 128, M_TEMP, M_NOWAIT); if (!sta->challenge) return; } for (i = 0; i < 32; i++) challenge[i] = sta->challenge[i] = arc4random(); challenge_len = 128; seq = 2; break; case 3: if (challenge_len != 128 || !sta->challenge || !(le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_WEP)) { status = IEEE80211_STATUS_CHALLENGE; goto fail; } challenge_len = 0; seq = 4; /* Check the challenge text. (Was decrypted by * the adapter.) */ for (i=0; i<32; i++) if (sta->challenge[i] != challenge[i]) { status = IEEE80211_STATUS_CHALLENGE; FREE(sta->challenge, M_TEMP); sta->challenge = NULL; goto fail; } sta->flags |= WI_SIFLAGS_AUTHEN; FREE(sta->challenge, M_TEMP); sta->challenge = NULL; break; default: seq = 2; status = IEEE80211_STATUS_SEQUENCE; goto fail; } /* switch (seq) */ break; default: if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_auth_req: algorithm unsupported: 0x%x\n", algo); status = IEEE80211_STATUS_ALG; goto fail; } /* switch (algo) */ status = IEEE80211_STATUS_SUCCESS;fail: if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_auth_req: returns status=0x%x\n", status); /* Send response. */ resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf; bzero(resp_hdr, 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, seq); put_hword(&pkt, status); if (challenge_len > 0) put_tlv(&pkt, IEEE80211_ELEMID_CHALLENGE, challenge, challenge_len); wi_mgmt_xmit(sc, sc->wi_txbuf, (char *) pkt - (char *) sc->wi_txbuf);}/*! \fn static void wihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm, caddr_t pkt, int len) \brief This functions handles incoming assocation and reassociation requests \param sc Pointer to the wi_softc structure of the specific interface \param rxfrm Pointer to a wi_frame structure containing information about received frame \param pkt Address of the packet \param len Length of the packet A call to saveAssocTime has been added (which is called for both associations, reassociations and association requests when already associated which might occur in case of temporary beacon loss by client station). Also the inactivity timeout is started.*//* wihap_assoc_req() * * Handle incoming association and reassociation requests. */static voidwihap_assoc_req(struct wi_softc *sc, struct wi_frame *rxfrm, caddr_t pkt, int len){ struct wihap_info *whi = &sc->wi_hostap_info; struct wihap_sta_info *sta; struct wi_80211_hdr *resp_hdr; u_int16_t capinfo; u_int16_t lstintvl; u_int8_t rates[8]; int ssid_len, rates_len; char ssid[33]; u_int16_t status; u_int16_t asid = 0; if (len < 8) return; /* Pull out request parameters. */ capinfo = take_hword(&pkt, &len); lstintvl = take_hword(&pkt, &len); if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_STYPE)) == htole16(WI_STYPE_MGMT_REASREQ)) { if (len < 6) return; /* Eat the MAC address of the current AP */ take_hword(&pkt, &len); take_hword(&pkt, &len); take_hword(&pkt, &len); } if ((ssid_len = take_tlv(&pkt, &len, IEEE80211_ELEMID_SSID, ssid, sizeof(ssid) - 1))<0) return; ssid[ssid_len] = '\0'; if ((rates_len = take_tlv(&pkt, &len, IEEE80211_ELEMID_RATES, rates, sizeof(rates)))<0) return; if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_assoc_req: from station %6D\n", rxfrm->wi_addr2, ":"); /* If SSID doesn't match, simply drop. */ if (strcmp(sc->wi_net_name, ssid) != 0) { if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_assoc_req: bad ssid: '%s' != '%s'\n", ssid, sc->wi_net_name); return; } /* Is this station authenticated yet? */ 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); 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. * Refuse stations requesting to be put on CF-polling list. */ 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: " "client using IBSS mode\n"); goto fail; } 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; } 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; } /* Use ASID is allocated by whi_sta_alloc(). */ asid = sta->asid; if (sta->flags & WI_SIFLAGS_ASSOC) { if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_assoc_req: already assoc'ed?\n"); } sta->flags |= WI_SIFLAGS_ASSOC; sta->inactivity_timer = whi->inactivity_time; status = IEEE80211_STATUS_SUCCESS;/* T. Moerland add: set the inactivity timeout also here, after associationbefore it was only reset after first packet received, thus when no packetsare sent, this station will never timeout*/ untimeout(wihap_sta_timeout, sta, sta->tmo); sta->tmo = timeout(wihap_sta_timeout, sta, hz * whi->inactivity_time);#ifdef WICACHE saveAssocTime(sc, rxfrm->wi_addr2);#endiffail: if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_assoc_req: returns status=0x%x\n", status); /* Send response. */ resp_hdr = (struct wi_80211_hdr *) sc->wi_txbuf; bzero(resp_hdr, sizeof(struct wi_80211_hdr)); 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); 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, capinfo); put_hword(&pkt, status); put_hword(&pkt, asid); rates_len = put_rates(&pkt, sc->wi_supprates); wi_mgmt_xmit(sc, sc->wi_txbuf, 8 + rates_len + sizeof(struct wi_80211_hdr));}/* wihap_deauth_req() * * Handle deauthentication requests. Delete the station. */static voidwihap_deauth_req(struct wi_softc *sc, struct wi_frame *rxfrm, caddr_t pkt, int len){ struct wihap_info *whi = &sc->wi_hostap_info; struct wihap_sta_info *sta; u_int16_t reason; if (len<2) return; reason = take_hword(&pkt, &len); sta = wihap_sta_find(whi, rxfrm->wi_addr2); if (sta == NULL) { if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) printf("wihap_deauth_req: unknown station: %6D\n", rxfrm->wi_addr2, ":"); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -