📄 wi_hostap.c
字号:
wihap_sta_delete(sta);}/*! \fn static void wihap_disassoc_req(struct wi_softc *sc, struct wi_frame *rxfrm, caddr_t pkt, int len) \brief This functions handles incoming disassocation 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 Just resets the assoc flag. Station resources are freed up when a deauth request is sent or after inactivity timeout. A call to saveDisassocTime has been added.*//* wihap_disassoc_req() * * Handle disassociation requests. Just reset the assoc flag. * We'll free up the station resources when we get a deauth * request or when it times out. */static voidwihap_disassoc_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_disassoc_req: unknown station: %6D\n", rxfrm->wi_addr2, ":"); } else if (!(sta->flags & WI_SIFLAGS_AUTHEN)) { /* * If station is not authenticated, send deauthentication * frame. */ wihap_sta_deauth(sc, rxfrm->wi_addr2, IEEE80211_REASON_NOT_AUTHED); return; } else { sta->flags &= ~WI_SIFLAGS_ASSOC;#ifdef WICACHE saveDisassocTime(sc, sta->addr);#endif }}/* wihap_debug_frame_type() * * Print out frame type. Used in early debugging. */static __inline voidwihap_debug_frame_type(struct wi_frame *rxfrm){ printf("wihap_mgmt_input: len=%d ", le16toh(rxfrm->wi_dat_len)); if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_FTYPE)) == htole16(WI_FTYPE_MGMT)) { printf("MGMT: "); switch (le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE) { case WI_STYPE_MGMT_ASREQ: printf("assoc req: \n"); break; case WI_STYPE_MGMT_ASRESP: printf("assoc resp: \n"); break; case WI_STYPE_MGMT_REASREQ: printf("reassoc req: \n"); break; case WI_STYPE_MGMT_REASRESP: printf("reassoc resp: \n"); break; case WI_STYPE_MGMT_PROBEREQ: printf("probe req: \n"); break; case WI_STYPE_MGMT_PROBERESP: printf("probe resp: \n"); break; case WI_STYPE_MGMT_BEACON: printf("beacon: \n"); break; case WI_STYPE_MGMT_ATIM: printf("ann traf ind \n"); break; case WI_STYPE_MGMT_DISAS: printf("disassociation: \n"); break; case WI_STYPE_MGMT_AUTH: printf("auth: \n"); break; case WI_STYPE_MGMT_DEAUTH: printf("deauth: \n"); break; default: printf("unknown (stype=0x%x)\n", 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)); }}/* wihap_mgmt_input: * * Called for each management frame received in host ap mode. * wihap_mgmt_input() is expected to free the mbuf. */voidwihap_mgmt_input(struct wi_softc *sc, struct wi_frame *rxfrm, struct mbuf *m){ caddr_t pkt; int s, len; if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) wihap_debug_frame_type(rxfrm); pkt = mtod(m, caddr_t) + WI_802_11_OFFSET_RAW; len = m->m_len - WI_802_11_OFFSET_RAW; if ((rxfrm->wi_frame_ctl & htole16(WI_FCTL_FTYPE)) == htole16(WI_FTYPE_MGMT)) { /* any of the following will mess w/ the station list */ s = splnet(); switch (le16toh(rxfrm->wi_frame_ctl) & WI_FCTL_STYPE) { case WI_STYPE_MGMT_ASREQ: wihap_assoc_req(sc, rxfrm, pkt, len); break; case WI_STYPE_MGMT_ASRESP: break; case WI_STYPE_MGMT_REASREQ: wihap_assoc_req(sc, rxfrm, pkt, len); break; case WI_STYPE_MGMT_REASRESP: break; case WI_STYPE_MGMT_PROBEREQ: break; case WI_STYPE_MGMT_PROBERESP: break; case WI_STYPE_MGMT_BEACON: break; case WI_STYPE_MGMT_ATIM: break; case WI_STYPE_MGMT_DISAS: wihap_disassoc_req(sc, rxfrm, pkt, len); break; case WI_STYPE_MGMT_AUTH: wihap_auth_req(sc, rxfrm, pkt, len); break; case WI_STYPE_MGMT_DEAUTH: wihap_deauth_req(sc, rxfrm, pkt, len); break; } splx(s); } m_freem(m);}/* wihap_sta_is_assoc() * * Determine if a station is assoc'ed. Update its activity * counter as a side-effect. */static intwihap_sta_is_assoc(struct wihap_info *whi, u_int8_t addr[]){ struct wihap_sta_info *sta; int retval, s; s = splnet(); retval = 0; sta = wihap_sta_find(whi, addr); if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) { /* Keep it active. */ untimeout(wihap_sta_timeout, sta, sta->tmo); sta->tmo = timeout(wihap_sta_timeout, sta, hz * whi->inactivity_time); retval = 1; } splx(s); return (retval);}/* wihap_check_tx() * * Determine if a station is assoc'ed, get its tx rate, and update * its activity. */intwihap_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; if (addr[0] & 0x01) { *txrate = 0; /* XXX: multicast rate? */ return(1); } s = splnet(); sta = wihap_sta_find(whi, addr); if (sta != NULL && (sta->flags & WI_SIFLAGS_ASSOC)) { /* Keep it active. */ untimeout(wihap_sta_timeout, sta, sta->tmo); 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);}/* * wihap_data_input() * * Handle all data input on interface when in Host AP mode. * Some packets are destined for this machine, others are * repeated to other stations. * * If wihap_data_input() returns a non-zero, it has processed * the packet and will free the mbuf. */intwihap_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, s; /* TODS flag must be set. */ 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, ":"); m_freem(m); return(1); } /* Check BSSID. (Is this necessary?) */ if (!addr_cmp(rxfrm->wi_addr1, sc->arpcom.ac_enaddr)) { if (ifp->if_flags & IFF_DEBUG) printf("wihap_data_input: incorrect bss: %6D\n", rxfrm->wi_addr1, ":"); m_freem(m); return (1); } s = splnet(); /* Find source station. */ sta = wihap_sta_find(whi, rxfrm->wi_addr2); /* Source station must be associated. */ 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, ":"); wihap_sta_disassoc(sc, rxfrm->wi_addr2, IEEE80211_REASON_ASSOC_LEAVE); splx(s); m_freem(m); return(1); } untimeout(wihap_sta_timeout, sta, sta->tmo); 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; if (mcast || wihap_sta_is_assoc(whi, rxfrm->wi_addr3)) { /* If it's multicast, make a copy. */ if (mcast) { m = m_copym(m, 0, M_COPYALL, M_DONTWAIT); if (m == NULL) return(0); m->m_flags |= M_MCAST; /* XXX */ } /* Queue up for repeating. */ IF_HANDOFF(&ifp->if_snd, m, ifp); return (!mcast); } return(0);}/*! \fn int wihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data) \brief This function handles HostAP specific ioctl calls. \param sc Pointer to the wi_softc structure of the specific interface \param command The ioctl request type \param data Address of ioctl data (to be read or written to) \note Function is called from wi_ioctl() in if_wi.c Handles SIOCHOSTAP_<FOO> calls. Added two calls:\n SIOCHOSTAP_DISASSOC to disassociate a station (send disassociation frame, clear association flag) SIOCHOSTAP_DEL to disassociate, deauthenticate a station and free it's resources (memory structures). In both cases saveDisassocTime is called (thus the cache timeout is started).*//* wihap_ioctl() * * Handle Host AP specific ioctls. Called from wi_ioctl(). */intwihap_ioctl(struct wi_softc *sc, u_long command, caddr_t data){ 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 s, error = 0, n, flag;#if __FreeBSD_version >= 500000 struct thread *td = curthread;#else struct proc *td = curproc; /* Little white lie */#endif if (!(sc->arpcom.ac_if.if_flags & IFF_RUNNING)) return ENODEV; switch (command) { case SIOCHOSTAP_DISASSOC: case SIOCHOSTAP_DEL: if ((error = suser(td))) break; if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta)))) break; s = splnet(); 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); sta->flags &= ~WI_SIFLAGS_ASSOC;#ifdef WICACHE if (sc->arpcom.ac_if.if_flags & IFF_DEBUG) device_printf(sc->dev, "SIOCHOSTAP_DISASSOC/DEL: saving disassoc time\n"); saveDisassocTime(sc, reqsta.addr);#endif if (command == SIOCHOSTAP_DISASSOC) { goto end_DISASSOC_case; } /* Deauth station. */ if (sta->flags & WI_SIFLAGS_AUTHEN) wihap_sta_deauth(sc, sta->addr, IEEE80211_REASON_AUTH_LEAVE); wihap_sta_delete(sta); } end_DISASSOC_case: splx(s); break; case SIOCHOSTAP_GET: if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta)))) break; s = splnet(); sta = wihap_sta_find(whi, reqsta.addr); if (sta == NULL) { error = ENOENT; splx(s); } else { reqsta.flags = sta->flags; reqsta.asid = sta->asid; reqsta.capinfo = sta->capinfo; reqsta.sig_info = sta->sig_info; reqsta.rates = sta->rates; splx(s); error = copyout(&reqsta, ifr->ifr_data, sizeof(reqsta)); } break; case SIOCHOSTAP_ADD: if ((error = suser(td))) break; if ((error = copyin(ifr->ifr_data, &reqsta, sizeof(reqsta)))) break; s = splnet(); 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(sc, reqsta.addr); sta->flags = reqsta.flags; sta->tmo = timeout(wihap_sta_timeout, sta, hz * whi->inactivity_time); splx(s); break; case SIOCHOSTAP_SFLAGS: if ((error = suser(td))) break; if ((error = copyin(ifr->ifr_data, &flag, sizeof(int)))) break; whi->apflags = (whi->apflags & WIHAPFL_CANTCHANGE) | (flag & ~WIHAPFL_CANTCHANGE); break; case SIOCHOSTAP_GFLAGS: flag = (int) whi->apflags; error = copyout(&flag, ifr->ifr_data, sizeof(int)); break; case SIOCHOSTAP_GETALL: if ((error = copyin(ifr->ifr_data, &reqall, sizeof(reqall)))) break; reqall.nstations = whi->n_stations; n = 0; s = splnet(); sta = LIST_FIRST(&whi->sta_list); while (sta && reqall.size >= n+sizeof(struct hostap_sta)) { bcopy(sta->addr, stabuf.addr, ETHER_ADDR_LEN); stabuf.asid = sta->asid; stabuf.flags = sta->flags; stabuf.capinfo = sta->capinfo; stabuf.sig_info = sta->sig_info; stabuf.rates = sta->rates; error = copyout(&stabuf, (caddr_t) reqall.addr + n, 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)); break; default: printf("wihap_ioctl: i shouldn't get other ioctls!\n"); error = EINVAL; } return(error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -