diff --git a/sys/dev/ic/awi.c b/sys/dev/ic/awi.c index b5725428c9c8..23941294bbe6 100644 --- a/sys/dev/ic/awi.c +++ b/sys/dev/ic/awi.c @@ -1,4 +1,4 @@ -/* $NetBSD: awi.c,v 1.46 2002/09/03 14:54:00 onoe Exp $ */ +/* $NetBSD: awi.c,v 1.47 2002/09/27 05:36:06 onoe Exp $ */ /*- * Copyright (c) 1999,2000,2001 The NetBSD Foundation, Inc. @@ -85,7 +85,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.46 2002/09/03 14:54:00 onoe Exp $"); +__KERNEL_RCSID(0, "$NetBSD: awi.c,v 1.47 2002/09/27 05:36:06 onoe Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -235,17 +235,18 @@ awi_attach(struct awi_softc *sc) memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) - ic->ic_flags = IEEE80211_F_FH; + ic->ic_phytype = IEEE80211_T_FH; else - ic->ic_flags = IEEE80211_F_DS; - ic->ic_flags |= + ic->ic_phytype = IEEE80211_T_DS; + ic->ic_flags = IEEE80211_F_HASWEP | IEEE80211_F_HASIBSS | IEEE80211_F_HASHAP; + ic->ic_opmode = IEEE80211_M_STA; ic->ic_state = IEEE80211_S_INIT; ic->ic_newstate = awi_newstate; ic->ic_chancheck = awi_chan_check; nrate = sc->sc_mib_phy.aSuprt_Data_Rates[1]; memcpy(ic->ic_sup_rates, sc->sc_mib_phy.aSuprt_Data_Rates + 2, nrate); - memcpy(ic->ic_myaddr, sc->sc_mib_addr.aMAC_Address, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_mib_addr.aMAC_Address); printf("%s: IEEE802.11 %s %dMbps (firmware %s)\n", sc->sc_dev.dv_xname, @@ -276,7 +277,7 @@ awi_attach(struct awi_softc *sc) ADD(IFM_AUTO, IFM_IEEE80211_HOSTAP); for (i = 0; i < nrate; i++) { mword = ieee80211_rate2media(ic->ic_sup_rates[i], - (ic->ic_flags & (IEEE80211_F_FH | IEEE80211_F_DS))); + ic->ic_phytype); if (mword == 0) continue; ADD(mword, 0); @@ -468,7 +469,7 @@ awi_init(struct ifnet *ifp) { struct awi_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_bss *bs = &ic->ic_bss; + struct ieee80211_node *ni = &ic->ic_bss; int i, error; DPRINTF(("awi_init: enabled=%d\n", sc->sc_enabled)); @@ -486,9 +487,9 @@ awi_init(struct ifnet *ifp) ic->ic_state = IEEE80211_S_INIT; sc->sc_mib_local.Network_Mode = - (ic->ic_flags & IEEE80211_F_ADHOC) ? 0 : 1; + (ic->ic_opmode == IEEE80211_M_ADHOC) ? 0 : 1; sc->sc_mib_local.Acting_as_AP = - (ic->ic_flags & IEEE80211_F_HOSTAP) ? 1 : 0; + (ic->ic_opmode == IEEE80211_M_HOSTAP) ? 1 : 0; memset(&sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE); sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID; sc->sc_mib_mac.aDesired_ESS_ID[1] = ic->ic_des_esslen; @@ -533,42 +534,42 @@ awi_init(struct ifnet *ifp) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - if (((ic->ic_flags & IEEE80211_F_ADHOC) && sc->sc_no_bssid) || - (ic->ic_flags & IEEE80211_F_HOSTAP)) { - bs->bs_chan = ic->ic_ibss_chan; - bs->bs_intval = ic->ic_lintval; - bs->bs_rssi = 0; - bs->bs_rstamp = 0; - memset(bs->bs_tstamp, 0, sizeof(bs->bs_tstamp)); - bs->bs_nrate = 0; + if ((ic->ic_opmode == IEEE80211_M_ADHOC && sc->sc_no_bssid) || + ic->ic_opmode == IEEE80211_M_HOSTAP) { + ni->ni_chan = ic->ic_ibss_chan; + ni->ni_intval = ic->ic_lintval; + ni->ni_rssi = 0; + ni->ni_rstamp = 0; + memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); + ni->ni_nrate = 0; for (i = 0; i < IEEE80211_RATE_SIZE; i++) { if (ic->ic_sup_rates[i]) - bs->bs_rates[bs->bs_nrate++] = + ni->ni_rates[ni->ni_nrate++] = ic->ic_sup_rates[i]; } - memcpy(bs->bs_macaddr, ic->ic_myaddr, IEEE80211_ADDR_LEN); - if (ic->ic_flags & IEEE80211_F_HOSTAP) { - memcpy(bs->bs_bssid, ic->ic_myaddr, IEEE80211_ADDR_LEN); - bs->bs_esslen = ic->ic_des_esslen; - memcpy(bs->bs_essid, ic->ic_des_essid, bs->bs_esslen); - bs->bs_capinfo = IEEE80211_CAPINFO_ESS; - if (ic->ic_flags & IEEE80211_F_FH) { - bs->bs_fhdwell = 200; /* XXX */ - bs->bs_fhindex = 1; + IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); + if (ic->ic_opmode == IEEE80211_M_HOSTAP) { + IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr); + ni->ni_esslen = ic->ic_des_esslen; + memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); + ni->ni_capinfo = IEEE80211_CAPINFO_ESS; + if (ic->ic_phytype == IEEE80211_T_FH) { + ni->ni_fhdwell = 200; /* XXX */ + ni->ni_fhindex = 1; } } else { - bs->bs_capinfo = IEEE80211_CAPINFO_IBSS; - memset(bs->bs_bssid, 0, IEEE80211_ADDR_LEN); - bs->bs_esslen = 0; + ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; + memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN); + ni->ni_esslen = 0; } if (ic->ic_flags & IEEE80211_F_WEPON) - bs->bs_capinfo |= IEEE80211_CAPINFO_PRIVACY; + ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; ic->ic_flags |= IEEE80211_F_SIBSS; ic->ic_state = IEEE80211_S_SCAN; /*XXX*/ sc->sc_substate = AWI_ST_NONE; ieee80211_new_state(&ic->ic_if, IEEE80211_S_RUN, -1); } else { - bs->bs_chan = sc->sc_cur_chan; + ni->ni_chan = sc->sc_cur_chan; ieee80211_new_state(&ic->ic_if, IEEE80211_S_SCAN, -1); } return 0; @@ -619,6 +620,7 @@ awi_start(struct ifnet *ifp) { struct awi_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_frame *wh; struct mbuf *m, *m0; int len, dowep; u_int32_t txd, frame, ntxd; @@ -675,6 +677,19 @@ awi_start(struct ifnet *ifp) ifp->if_oerrors++; continue; } + wh = mtod(m0, struct ieee80211_frame *); + if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && + ic->ic_opmode != IEEE80211_M_STA && + sc->sc_no_bssid == 0 && + sc->sc_adhoc_ap == 0 && + (ifp->if_flags & IFF_LINK0) == 0 && + (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == + IEEE80211_FC0_TYPE_DATA && + ieee80211_find_node(ic, wh->i_addr1) == NULL) { + m_freem(m0); + ifp->if_oerrors++; + continue; + } } #if NBPFILTER > 0 if (ic->ic_rawbpf) @@ -698,7 +713,7 @@ awi_start(struct ifnet *ifp) if ((ifp->if_flags & IFF_DEBUG) && (ifp->if_flags & IFF_LINK2)) ieee80211_dump_pkt(m0->m_data, m0->m_len, - ic->ic_bss.bs_rates[ic->ic_bss.bs_txrate] & + ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] & IEEE80211_RATE_VAL, -1); for (m = m0, len = 0; m != NULL; m = m->m_next) { @@ -707,7 +722,7 @@ awi_start(struct ifnet *ifp) len += m->m_len; } m_freem(m0); - rate = (ic->ic_bss.bs_rates[ic->ic_bss.bs_txrate] & + rate = (ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] & IEEE80211_RATE_VAL) * 5; awi_write_1(sc, ntxd + AWI_TXD_STATE, 0); awi_write_4(sc, txd + AWI_TXD_START, frame); @@ -840,8 +855,7 @@ awi_media_change(struct ifnet *ifp) if (IFM_SUBTYPE(ime->ifm_media) == IFM_AUTO) { ic->ic_fixed_rate = -1; } else { - rate = ieee80211_media2rate(ime->ifm_media, - (ic->ic_flags & (IEEE80211_F_FH | IEEE80211_F_DS))); + rate = ieee80211_media2rate(ime->ifm_media, ic->ic_phytype); if (rate == 0) return EINVAL; for (i = 0; i < IEEE80211_RATE_SIZE; i++) { @@ -854,24 +868,31 @@ awi_media_change(struct ifnet *ifp) } /* - * ADHOC,-FLAG0 ADHOC|~HOSTAP, !no_bssid, !adhoc_ap IBSS - * ADHOC, FLAG0 ADHOC|~HOSTAP, no_bssid, !adhoc_ap WaveLAN adhoc - * -ADHOC, FLAG0 ADHOC|~HOSTAP, !no_bssid, adhoc_ap Melco old AP - * also LINK0 - * -ADHOC,HOSTAP ~ADHOC|HOSTAP, !no_bssid, !adhoc_ap HostAP - * -ADHOC,-FLAG0 ~ADHOC|~HOSTAP, !no_bssid, !adhoc_ap Infra + * combination of mediaopt + * + * hostap adhoc flag0 opmode no_bssid adhoc_ap comment + * + - - HOSTAP 0 0 HostAP + * - + - ADHOC 0 0 IBSS + * - + + ADHOC 1 0 WaveLAN adhoc + * - - + ADHOC 0 1 Melco old Sta + * also LINK0 + * - - - STA 0 0 Infra Station */ - if (ime->ifm_media & IFM_IEEE80211_ADHOC) { - if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0 || - (ic->ic_flags & IEEE80211_F_IBSSON) == 0 || - (ic->ic_flags & IEEE80211_F_HOSTAP) || - sc->sc_adhoc_ap) { - ic->ic_flags |= IEEE80211_F_ADHOC | IEEE80211_F_IBSSON; - ic->ic_flags &= ~IEEE80211_F_HOSTAP; + if (ime->ifm_media & IFM_IEEE80211_HOSTAP) { + if (ic->ic_opmode != IEEE80211_M_HOSTAP) { + ic->ic_opmode = IEEE80211_M_HOSTAP; + sc->sc_no_bssid = 0; sc->sc_adhoc_ap = 0; error = ENETRESET; } - if (sc->sc_mib_phy.IEEE_PHY_Type != AWI_PHY_TYPE_FH && + } else if (ime->ifm_media & IFM_IEEE80211_ADHOC) { + if (ic->ic_opmode != IEEE80211_M_ADHOC || + sc->sc_adhoc_ap != 0) { + ic->ic_opmode = IEEE80211_M_ADHOC; + sc->sc_adhoc_ap = 0; + error = ENETRESET; + } + if (ic->ic_phytype == IEEE80211_T_DS && (ime->ifm_media & IFM_FLAG0)) { if (sc->sc_no_bssid == 0) { sc->sc_no_bssid = 1; @@ -884,36 +905,16 @@ awi_media_change(struct ifnet *ifp) } } } else if (ime->ifm_media & IFM_FLAG0) { - if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0 || - (ic->ic_flags & IEEE80211_F_IBSSON) || - (ic->ic_flags & IEEE80211_F_HOSTAP) || - sc->sc_no_bssid || !sc->sc_adhoc_ap) { - ic->ic_flags |= IEEE80211_F_ADHOC; - ic->ic_flags &= - ~(IEEE80211_F_IBSSON | IEEE80211_F_HOSTAP); - sc->sc_no_bssid = 0; + if (ic->ic_opmode != IEEE80211_M_ADHOC || + sc->sc_adhoc_ap == 0) { + ic->ic_opmode = IEEE80211_M_ADHOC; sc->sc_adhoc_ap = 1; - error = ENETRESET; - } - } else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) { - if ((ic->ic_flags & IEEE80211_F_ADHOC) || - (ic->ic_flags & IEEE80211_F_IBSSON) || - (ic->ic_flags & IEEE80211_F_HOSTAP) == 0 || - sc->sc_no_bssid || sc->sc_adhoc_ap) { - ic->ic_flags |= IEEE80211_F_HOSTAP; - ic->ic_flags &= - ~(IEEE80211_F_ADHOC | IEEE80211_F_IBSSON); sc->sc_no_bssid = 0; - sc->sc_adhoc_ap = 0; error = ENETRESET; } } else { - if ((ic->ic_flags & IEEE80211_F_ADHOC) || - (ic->ic_flags & IEEE80211_F_IBSSON) || - (ic->ic_flags & IEEE80211_F_HOSTAP) || - sc->sc_no_bssid || sc->sc_adhoc_ap) { - ic->ic_flags &= ~(IEEE80211_F_ADHOC | - IEEE80211_F_IBSSON | IEEE80211_F_HOSTAP); + if (ic->ic_opmode != IEEE80211_M_STA) { + ic->ic_opmode = IEEE80211_M_STA; sc->sc_no_bssid = 0; sc->sc_adhoc_ap = 0; error = ENETRESET; @@ -940,7 +941,7 @@ awi_media_status(struct ifnet *ifp, struct ifmediareq *imr) imr->ifm_status |= IFM_ACTIVE; imr->ifm_active = IFM_IEEE80211; if (ic->ic_state == IEEE80211_S_RUN) - rate = ic->ic_bss.bs_rates[ic->ic_bss.bs_txrate] & + rate = ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] & IEEE80211_RATE_VAL; else { if (ic->ic_fixed_rate == -1) @@ -949,11 +950,11 @@ awi_media_status(struct ifnet *ifp, struct ifmediareq *imr) rate = ic->ic_sup_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; } - imr->ifm_active |= ieee80211_rate2media(rate, - (ic->ic_flags & (IEEE80211_F_FH | IEEE80211_F_DS))); - if (ic->ic_flags & IEEE80211_F_HOSTAP) - imr->ifm_active |= IFM_IEEE80211_HOSTAP; - else if (ic->ic_flags & IEEE80211_F_ADHOC) { + imr->ifm_active |= ieee80211_rate2media(rate, ic->ic_phytype); + switch (ic->ic_opmode) { + case IEEE80211_M_STA: + break; + case IEEE80211_M_ADHOC: if (sc->sc_adhoc_ap) imr->ifm_active |= IFM_FLAG0; else { @@ -961,6 +962,10 @@ awi_media_status(struct ifnet *ifp, struct ifmediareq *imr) if (sc->sc_no_bssid) imr->ifm_active |= IFM_FLAG0; } + break; + case IEEE80211_M_HOSTAP: + imr->ifm_active |= IFM_IEEE80211_HOSTAP; + break; } } @@ -975,7 +980,7 @@ awi_mode_init(struct awi_softc *sc) /* reinitialize muticast filter */ n = 0; sc->sc_mib_local.Accept_All_Multicast_Dis = 0; - if ((sc->sc_ic.ic_flags & IEEE80211_F_HOSTAP) == 0 && + if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP && (ifp->if_flags & IFF_PROMISC)) { sc->sc_mib_mac.aPromiscuous_Enable = 1; goto set_mib; @@ -984,16 +989,16 @@ awi_mode_init(struct awi_softc *sc) ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ec, enm); while (enm != NULL) { if (n == AWI_GROUP_ADDR_SIZE || - memcmp(enm->enm_addrlo, enm->enm_addrhi, IEEE80211_ADDR_LEN) - != 0) + !IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi)) goto set_mib; - memcpy(sc->sc_mib_addr.aGroup_Addresses[n], enm->enm_addrlo, - IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n], + enm->enm_addrlo); n++; ETHER_NEXT_MULTI(step, enm); } for (; n < AWI_GROUP_ADDR_SIZE; n++) - memset(sc->sc_mib_addr.aGroup_Addresses[n], 0, IEEE80211_ADDR_LEN); + memset(sc->sc_mib_addr.aGroup_Addresses[n], 0, + IEEE80211_ADDR_LEN); sc->sc_mib_local.Accept_All_Multicast_Dis = 1; set_mib: @@ -1386,7 +1391,7 @@ awi_chan_check(void *arg, u_char *chanreq) cs->cs_region; memcpy(sc->sc_ic.ic_chan_avail, chanlist, sizeof(sc->sc_ic.ic_chan_avail)); - sc->sc_ic.ic_bss.bs_chan = cs->cs_def; + sc->sc_ic.ic_bss.ni_chan = cs->cs_def; sc->sc_cur_chan = cs->cs_def; return 0; } @@ -1692,7 +1697,7 @@ awi_newstate(void *arg, enum ieee80211_state nstate) { struct awi_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_bss *bs = &ic->ic_bss; + struct ieee80211_node *ni; struct ifnet *ifp = &ic->ic_if; int error; u_int8_t newmode; @@ -1715,7 +1720,7 @@ awi_newstate(void *arg, enum ieee80211_state nstate) awi_drvstate(sc, AWI_DRV_RESET); break; case IEEE80211_S_SCAN: - if (ic->ic_flags & IEEE80211_F_ADHOC) + if (ic->ic_opmode == IEEE80211_M_ADHOC) awi_drvstate(sc, AWI_DRV_ADHSC); else awi_drvstate(sc, AWI_DRV_INFSY); @@ -1727,7 +1732,7 @@ awi_newstate(void *arg, enum ieee80211_state nstate) awi_drvstate(sc, AWI_DRV_INFAUTH); break; case IEEE80211_S_RUN: - if (ic->ic_flags & IEEE80211_F_ADHOC) + if (ic->ic_opmode == IEEE80211_M_ADHOC) awi_drvstate(sc, AWI_DRV_ADHSY); else awi_drvstate(sc, AWI_DRV_INFASSOC); @@ -1757,12 +1762,13 @@ awi_newstate(void *arg, enum ieee80211_state nstate) printf("%s: no recent beacons from %s;" " rescanning\n", ifp->if_xname, - ether_sprintf(ic->ic_bss.bs_bssid)); + ether_sprintf(ic->ic_bss.ni_bssid)); /* FALLTHRU */ case IEEE80211_S_AUTH: case IEEE80211_S_ASSOC: /* timeout restart scan */ - ieee80211_free_scan(ifp); + while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL) + ieee80211_free_node(ic, ni); /* FALLTHRU */ case IEEE80211_S_INIT: ic->ic_flags |= IEEE80211_F_ASCAN; @@ -1790,22 +1796,23 @@ awi_newstate(void *arg, enum ieee80211_state nstate) break; } sc->sc_cmd_inprog = AWI_CMD_SCAN; + ni = &ic->ic_bss; awi_write_2(sc, AWI_CA_SCAN_DURATION, (ic->ic_flags & IEEE80211_F_ASCAN) ? AWI_ASCAN_DURATION : AWI_PSCAN_DURATION); if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { awi_write_1(sc, AWI_CA_SCAN_SET, - IEEE80211_FH_CHANSET(bs->bs_chan)); + IEEE80211_FH_CHANSET(ni->ni_chan)); awi_write_1(sc, AWI_CA_SCAN_PATTERN, - IEEE80211_FH_CHANPAT(bs->bs_chan)); + IEEE80211_FH_CHANPAT(ni->ni_chan)); awi_write_1(sc, AWI_CA_SCAN_IDX, 1); } else { - awi_write_1(sc, AWI_CA_SCAN_SET, bs->bs_chan); + awi_write_1(sc, AWI_CA_SCAN_SET, ni->ni_chan); awi_write_1(sc, AWI_CA_SCAN_PATTERN, 0); awi_write_1(sc, AWI_CA_SCAN_IDX, 0); } awi_write_1(sc, AWI_CA_SCAN_SUSP, 0); - sc->sc_cur_chan = bs->bs_chan; + sc->sc_cur_chan = ni->ni_chan; if ((error = awi_cmd(sc, AWI_CMD_SCAN, AWI_NOWAIT)) != 0) break; @@ -1837,20 +1844,21 @@ awi_newstate(void *arg, enum ieee80211_state nstate) sc->sc_nstate = nstate; /* next state in transition */ sc->sc_substate = AWI_ST_SUB_INIT; } + ni = &ic->ic_bss; switch (sc->sc_substate) { case AWI_ST_SUB_INIT: sc->sc_substate = AWI_ST_SUB_SETSS; - memcpy(&sc->sc_mib_mgt.aCurrent_BSS_ID, bs->bs_bssid, - IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(&sc->sc_mib_mgt.aCurrent_BSS_ID, + ni->ni_bssid); memset(&sc->sc_mib_mgt.aCurrent_ESS_ID, 0, AWI_ESS_ID_SIZE); sc->sc_mib_mgt.aCurrent_ESS_ID[0] = IEEE80211_ELEMID_SSID; - sc->sc_mib_mgt.aCurrent_ESS_ID[1] = bs->bs_esslen; + sc->sc_mib_mgt.aCurrent_ESS_ID[1] = ni->ni_esslen; memcpy(&sc->sc_mib_mgt.aCurrent_ESS_ID[2], - bs->bs_essid, bs->bs_esslen); + ni->ni_essid, ni->ni_esslen); LE_WRITE_2(&sc->sc_mib_mgt.aBeacon_Period, - bs->bs_intval); + ni->ni_intval); if ((error = awi_mib(sc, AWI_CMD_SET_MIB, AWI_MIB_MGT, AWI_NOWAIT)) != 0) break; @@ -1864,15 +1872,15 @@ awi_newstate(void *arg, enum ieee80211_state nstate) sc->sc_cmd_inprog = AWI_CMD_SYNC; if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) { awi_write_1(sc, AWI_CA_SYNC_SET, - IEEE80211_FH_CHANSET(bs->bs_chan)); + IEEE80211_FH_CHANSET(ni->ni_chan)); awi_write_1(sc, AWI_CA_SYNC_PATTERN, - IEEE80211_FH_CHANPAT(bs->bs_chan)); + IEEE80211_FH_CHANPAT(ni->ni_chan)); awi_write_1(sc, AWI_CA_SYNC_IDX, - bs->bs_fhindex); + ni->ni_fhindex); awi_write_2(sc, AWI_CA_SYNC_DWELL, - bs->bs_fhdwell); + ni->ni_fhdwell); } else { - awi_write_1(sc, AWI_CA_SYNC_SET, bs->bs_chan); + awi_write_1(sc, AWI_CA_SYNC_SET, ni->ni_chan); awi_write_1(sc, AWI_CA_SYNC_PATTERN, 0); awi_write_1(sc, AWI_CA_SYNC_IDX, 0); awi_write_2(sc, AWI_CA_SYNC_DWELL, 0); @@ -1884,9 +1892,9 @@ awi_newstate(void *arg, enum ieee80211_state nstate) awi_write_1(sc, AWI_CA_SYNC_STARTBSS, 0); awi_write_2(sc, AWI_CA_SYNC_MBZ, 0); awi_write_bytes(sc, AWI_CA_SYNC_TIMESTAMP, - bs->bs_tstamp, 8); - awi_write_4(sc, AWI_CA_SYNC_REFTIME, bs->bs_rstamp); - sc->sc_cur_chan = bs->bs_chan; + ni->ni_tstamp, 8); + awi_write_4(sc, AWI_CA_SYNC_REFTIME, ni->ni_rstamp); + sc->sc_cur_chan = ni->ni_chan; if ((error = awi_cmd(sc, AWI_CMD_SYNC, AWI_NOWAIT)) != 0) break; @@ -1897,9 +1905,8 @@ awi_newstate(void *arg, enum ieee80211_state nstate) if ((error = awi_mib(sc, AWI_CMD_GET_MIB, AWI_MIB_MGT, AWI_WAIT)) != 0) break; - memcpy(bs->bs_bssid, - &sc->sc_mib_mgt.aCurrent_BSS_ID, - IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(ni->ni_bssid, + &sc->sc_mib_mgt.aCurrent_BSS_ID); } else { if (nstate == IEEE80211_S_RUN) { sc->sc_rx_timer = 10; @@ -1927,7 +1934,7 @@ static struct mbuf * awi_ether_encap(struct awi_softc *sc, struct mbuf *m) { struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_bss *bs = &ic->ic_bss; + struct ieee80211_node *ni = &ic->ic_bss; struct ether_header *eh; struct ieee80211_frame *wh; @@ -1944,22 +1951,21 @@ awi_ether_encap(struct awi_softc *sc, struct mbuf *m) wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; *(u_int16_t *)wh->i_dur = 0; *(u_int16_t *)wh->i_seq = - htole16(bs->bs_txseq << IEEE80211_SEQ_SEQ_SHIFT); - bs->bs_txseq++; - if (ic->ic_flags & IEEE80211_F_ADHOC) { + htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); + ni->ni_txseq++; + if (ic->ic_opmode == IEEE80211_M_ADHOC) { wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; if (sc->sc_adhoc_ap) - memcpy(wh->i_addr1, bs->bs_macaddr, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr); else - memcpy(wh->i_addr1, eh->ether_dhost, - IEEE80211_ADDR_LEN); - memcpy(wh->i_addr2, eh->ether_shost, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr3, bs->bs_bssid, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(wh->i_addr1, eh->ether_dhost); + IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost); + IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); } else { wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; - memcpy(wh->i_addr1, bs->bs_bssid, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr2, eh->ether_shost, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr3, eh->ether_dhost, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid); + IEEE80211_ADDR_COPY(wh->i_addr2, eh->ether_shost); + IEEE80211_ADDR_COPY(wh->i_addr3, eh->ether_dhost); } return m; } @@ -1982,8 +1988,8 @@ awi_ether_modcap(struct awi_softc *sc, struct mbuf *m) return m; memcpy(&eh, mtod(m, caddr_t) + sizeof(wh), sizeof(eh)); m_adj(m, sizeof(eh) - sizeof(*llc)); - if (ic->ic_flags & IEEE80211_F_ADHOC) - memcpy(wh.i_addr2, eh.ether_shost, IEEE80211_ADDR_LEN); + if (ic->ic_opmode == IEEE80211_M_ADHOC) + IEEE80211_ADDR_COPY(wh.i_addr2, eh.ether_shost); memcpy(mtod(m, caddr_t), &wh, sizeof(wh)); llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh)); llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; diff --git a/sys/net/if_ieee80211.h b/sys/net/if_ieee80211.h index b377069fb891..6ea88e2020c5 100644 --- a/sys/net/if_ieee80211.h +++ b/sys/net/if_ieee80211.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_ieee80211.h,v 1.19 2002/09/22 01:56:08 thorpej Exp $ */ +/* $NetBSD: if_ieee80211.h,v 1.20 2002/09/27 05:36:04 onoe Exp $ */ /*- * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -361,6 +361,18 @@ struct ieee80211_bssid { #define IEEE80211_RATE_SIZE 12 #define IEEE80211_KEYBUF_SIZE 16 +enum ieee80211_phytype { + IEEE80211_T_DS, + IEEE80211_T_FH, + IEEE80211_T_OFDM +}; + +enum ieee80211_opmode { + IEEE80211_M_STA = 1, /* infrastructure station */ + IEEE80211_M_ADHOC = 0, /* IBSS (adhoc) station */ + IEEE80211_M_HOSTAP = 6 /* Software Access Point */ +}; + enum ieee80211_state { IEEE80211_S_INIT, /* default state */ IEEE80211_S_SCAN, /* scanning */ @@ -372,40 +384,40 @@ enum ieee80211_state { /* * Node specific information. */ -struct ieee80211_bss { - TAILQ_ENTRY(ieee80211_bss) bs_list; +struct ieee80211_node { + TAILQ_ENTRY(ieee80211_node) ni_list; /* hardware */ - u_int8_t bs_rssi; - u_int32_t bs_rstamp; + u_int8_t ni_rssi; + u_int32_t ni_rstamp; /* header */ - u_int8_t bs_macaddr[IEEE80211_ADDR_LEN]; - u_int8_t bs_bssid[IEEE80211_ADDR_LEN]; + u_int8_t ni_macaddr[IEEE80211_ADDR_LEN]; + u_int8_t ni_bssid[IEEE80211_ADDR_LEN]; /* beacon, probe response */ - u_int8_t bs_tstamp[8]; - u_int16_t bs_intval; - u_int16_t bs_capinfo; - u_int8_t bs_esslen; - u_int8_t bs_essid[IEEE80211_NWID_LEN]; - int bs_nrate; - u_int8_t bs_rates[IEEE80211_RATE_SIZE]; - u_int8_t bs_chan; - u_int16_t bs_fhdwell; /* FH only */ - u_int8_t bs_fhindex; /* FH only */ + u_int8_t ni_tstamp[8]; + u_int16_t ni_intval; + u_int16_t ni_capinfo; + u_int8_t ni_esslen; + u_int8_t ni_essid[IEEE80211_NWID_LEN]; + int ni_nrate; + u_int8_t ni_rates[IEEE80211_RATE_SIZE]; + u_int8_t ni_chan; + u_int16_t ni_fhdwell; /* FH only */ + u_int8_t ni_fhindex; /* FH only */ /* others */ - u_int16_t bs_associd; /* assoc response */ - u_int16_t bs_txseq; /* seq to be transmitted */ - u_int16_t bs_rxseq; /* seq previous received */ - int bs_fails; /* failure count to associate */ - int bs_inact; /* inactivity mark count */ - int bs_txrate; /* index to bs_rates[] */ - void *bs_private; /* driver private */ + u_int16_t ni_associd; /* assoc response */ + u_int16_t ni_txseq; /* seq to be transmitted */ + u_int16_t ni_rxseq; /* seq previous received */ + int ni_fails; /* failure count to associate */ + int ni_inact; /* inactivity mark count */ + int ni_txrate; /* index to ni_rates[] */ + void *ni_private; /* driver private */ }; -/* bs_chan encoding for FH phy */ +/* ni_chan encoding for FH phy */ #define IEEE80211_FH_CHANMOD 80 #define IEEE80211_FH_CHAN(set,pat) (((set)-1)*IEEE80211_FH_CHANMOD+(pat)) #define IEEE80211_FH_CHANSET(chan) ((chan)/IEEE80211_FH_CHANMOD+1) @@ -421,7 +433,7 @@ struct ieee80211com { void (*ic_recv_mgmt[16])(struct ieee80211com *, struct mbuf *, int, u_int32_t); int (*ic_send_mgmt[16])(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); int (*ic_newstate)(void *, enum ieee80211_state); int (*ic_chancheck)(void *, u_char *); u_int8_t ic_myaddr[IEEE80211_ADDR_LEN]; @@ -430,19 +442,23 @@ struct ieee80211com { u_char ic_chan_active[roundup(IEEE80211_CHAN_MAX, NBBY)]; struct ifqueue ic_mgtq; int ic_flags; + enum ieee80211_phytype ic_phytype; + enum ieee80211_opmode ic_opmode; enum ieee80211_state ic_state; caddr_t ic_rawbpf; /* packet filter structure */ - struct ieee80211_bss ic_bss; /* information for this node */ - int ic_bss_privlen; /* size for bs_private */ + struct ieee80211_node ic_bss; /* information for this node */ + int ic_bss_privlen; /* size for ni_private */ u_int8_t ic_ibss_chan; int ic_fixed_rate; /* index to ic_sup_rates[] */ - TAILQ_HEAD(, ieee80211_bss) ic_scan; /* information of all nodes */ + TAILQ_HEAD(, ieee80211_node) ic_node; /* information of all nodes */ u_int16_t ic_lintval; /* listen interval */ int ic_mgt_timer; /* mgmt timeout */ int ic_scan_timer; /* scant wait */ int ic_inact_timer; /* inactivity timer wait */ int ic_des_esslen; u_int8_t ic_des_essid[IEEE80211_NWID_LEN]; + int ic_des_chan; /* desired channel */ + u_int8_t ic_des_bssid[IEEE80211_ADDR_LEN]; struct ieee80211_wepkey ic_nw_keys[IEEE80211_WEP_NKID]; int ic_wep_txkey; /* default tx key index */ void *ic_wep_ctx; @@ -450,28 +466,29 @@ struct ieee80211com { #define ic_if ic_ec.ec_if #define ic_softc ic_ec.ec_if.if_softc -#define IEEE80211_SEND_MGMT(ic,bs,type,arg) do { \ +#define IEEE80211_SEND_MGMT(ic,ni,type,arg) do { \ if ((ic)->ic_send_mgmt[(type)>>IEEE80211_FC0_SUBTYPE_SHIFT] != NULL) \ (*(ic)->ic_send_mgmt[(type)>>IEEE80211_FC0_SUBTYPE_SHIFT]) \ - (ic,bs,type,arg); \ + (ic,ni,type,arg); \ } while (0) +#define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0) +#define IEEE80211_ADDR_COPY(dst,src) memcpy(dst,src,IEEE80211_ADDR_LEN) + +#define IEEE80211_IS_MULTICAST(a) ETHER_IS_MULTICAST(a) + /* ic_flags */ #define IEEE80211_F_ASCAN 0x00000001 /* STATUS: active scan */ #define IEEE80211_F_SIBSS 0x00000002 /* STATUS: start IBSS */ #define IEEE80211_F_WEPON 0x00000100 /* CONF: WEP enabled */ #define IEEE80211_F_IBSSON 0x00000200 /* CONF: IBSS creation enable */ #define IEEE80211_F_PMGTON 0x00000400 /* CONF: Power mgmt enable */ -#define IEEE80211_F_ADHOC 0x00000800 /* CONF: adhoc mode */ -#define IEEE80211_F_SCANAP 0x00001000 /* CONF: scan AP mode */ -#define IEEE80211_F_HOSTAP 0x00002000 /* CONF: AP mode */ +#define IEEE80211_F_DESBSSID 0x00000800 /* CONF: des_bssid is set */ +#define IEEE80211_F_SCANAP 0x00001000 /* CONF: Scanning AP */ #define IEEE80211_F_HASWEP 0x00010000 /* CAPABILITY: WEP available */ #define IEEE80211_F_HASIBSS 0x00020000 /* CAPABILITY: IBSS available */ #define IEEE80211_F_HASPMGT 0x00040000 /* CAPABILITY: Power mgmt */ #define IEEE80211_F_HASHAP 0x00080000 /* CAPABILITY: HOSTAP avail */ -#define IEEE80211_F_FH 0x01000000 /* PHY: FH */ -#define IEEE80211_F_DS 0x02000000 /* PHY: DS */ -#define IEEE80211_F_OFDM 0x04000000 /* PHY: OFDM */ /* flags for ieee80211_fix_rate() */ #define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */ @@ -482,7 +499,7 @@ struct ieee80211com { void ieee80211_ifattach(struct ifnet *); void ieee80211_ifdetach(struct ifnet *); void ieee80211_input(struct ifnet *, struct mbuf *, int, u_int32_t); -int ieee80211_mgmt_output(struct ifnet *, struct ieee80211_bss *, +int ieee80211_mgmt_output(struct ifnet *, struct ieee80211_node *, struct mbuf *, int); struct mbuf *ieee80211_encap(struct ifnet *, struct mbuf *); struct mbuf *ieee80211_decap(struct ifnet *, struct mbuf *); @@ -492,13 +509,14 @@ void ieee80211_dump_pkt(u_int8_t *, int, int, int); void ieee80211_watchdog(struct ifnet *); void ieee80211_next_scan(struct ifnet *); void ieee80211_end_scan(struct ifnet *); -struct ieee80211_bss *ieee80211_alloc_bss(struct ieee80211com *, int); -void ieee80211_free_scan(struct ifnet *); -int ieee80211_fix_rate(struct ieee80211com *, struct ieee80211_bss *, int); +struct ieee80211_node *ieee80211_alloc_node(struct ieee80211com *, int); +struct ieee80211_node *ieee80211_find_node(struct ieee80211com *, u_int8_t *); +void ieee80211_free_node(struct ieee80211com *, struct ieee80211_node *); +int ieee80211_fix_rate(struct ieee80211com *, struct ieee80211_node *, int); int ieee80211_new_state(struct ifnet *, enum ieee80211_state, int); struct mbuf *ieee80211_wep_crypt(struct ifnet *, struct mbuf *, int); -int ieee80211_rate2media(int, int); -int ieee80211_media2rate(int, int); +int ieee80211_rate2media(int, enum ieee80211_phytype); +int ieee80211_media2rate(int, enum ieee80211_phytype); int ieee80211_cfgget(struct ifnet *, u_long, caddr_t); int ieee80211_cfgset(struct ifnet *, u_long, caddr_t); diff --git a/sys/net/if_ieee80211subr.c b/sys/net/if_ieee80211subr.c index d29c6924ba4f..14c2196ff4b8 100644 --- a/sys/net/if_ieee80211subr.c +++ b/sys/net/if_ieee80211subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ieee80211subr.c,v 1.12 2002/09/03 14:54:00 onoe Exp $ */ +/* $NetBSD: if_ieee80211subr.c,v 1.13 2002/09/27 05:36:04 onoe Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_ieee80211subr.c,v 1.12 2002/09/03 14:54:00 onoe Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ieee80211subr.c,v 1.13 2002/09/27 05:36:04 onoe Exp $"); #include "opt_inet.h" #include "bpfilter.h" @@ -87,19 +87,19 @@ int ieee80211_debug = 0; #endif static int ieee80211_send_prreq(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); static int ieee80211_send_prresp(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); static int ieee80211_send_auth(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); static int ieee80211_send_deauth(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); static int ieee80211_send_asreq(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); static int ieee80211_send_asresp(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); static int ieee80211_send_disassoc(struct ieee80211com *, - struct ieee80211_bss *, int, int); + struct ieee80211_node *, int, int); static void ieee80211_recv_beacon(struct ieee80211com *, struct mbuf *, int, u_int32_t); @@ -148,10 +148,11 @@ ieee80211_ifattach(struct ifnet *ifp) } } } + ic->ic_des_chan = -1; ic->ic_fixed_rate = -1; if (ic->ic_lintval == 0) ic->ic_lintval = 100; /* default sleep */ - TAILQ_INIT(&ic->ic_scan); + TAILQ_INIT(&ic->ic_node); rate = 0; for (i = 0; i < IEEE80211_RATE_SIZE; i++) { if (ic->ic_sup_rates[i] != 0) @@ -207,6 +208,7 @@ void ieee80211_ifdetach(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; + struct ieee80211_node *ni; int s; s = splnet(); @@ -215,7 +217,8 @@ ieee80211_ifdetach(struct ifnet *ifp) free(ic->ic_wep_ctx, M_DEVBUF); ic->ic_wep_ctx = NULL; } - ieee80211_free_scan(ifp); + while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL) + ieee80211_free_node(ic, ni); ether_ifdetach(ifp); } @@ -223,7 +226,7 @@ void ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp) { struct ieee80211com *ic = (void *)ifp; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; struct ieee80211_frame *wh; void (*rh)(struct ieee80211com *, struct mbuf *, int, u_int); u_int8_t dir, subtype; @@ -248,70 +251,60 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp) dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; if (ic->ic_state != IEEE80211_S_SCAN) { - if ((ic->ic_flags & IEEE80211_F_ADHOC) || - (ic->ic_flags & IEEE80211_F_HOSTAP)) { + switch (ic->ic_opmode) { + case IEEE80211_M_STA: + ni = &ic->ic_bss; + if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) { + DPRINTF(("ieee80211_input: other bss %s\n", + ether_sprintf(wh->i_addr2))); + /* not interested in */ + goto out; + } + break; + case IEEE80211_M_ADHOC: + case IEEE80211_M_HOSTAP: if (dir == IEEE80211_FC1_DIR_NODS) bssid = wh->i_addr3; else bssid = wh->i_addr1; - if (memcmp(bssid, ic->ic_bss.bs_bssid, - IEEE80211_ADDR_LEN) != 0 && - memcmp(bssid, ifp->if_broadcastaddr, - IEEE80211_ADDR_LEN) != 0) { + if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss.ni_bssid) && + !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) { /* not interested in */ DPRINTF(("ieee80211_input: other bss %s\n", ether_sprintf(wh->i_addr3))); goto out; } - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(wh->i_addr2, bs->bs_macaddr, - IEEE80211_ADDR_LEN) == 0) - break; - } - if (bs == NULL) { + ni = ieee80211_find_node(ic, wh->i_addr2); + if (ni == NULL) { DPRINTF(("ieee80211_input: unknown src %s\n", ether_sprintf(wh->i_addr2))); - bs = &ic->ic_bss; /* XXX allocate? */ - } - } else { - bs = &ic->ic_bss; - if (memcmp(wh->i_addr2, bs->bs_bssid, - IEEE80211_ADDR_LEN) != 0) { - DPRINTF(("ieee80211_input: other bss %s\n", - ether_sprintf(wh->i_addr2))); - /* not interested in */ - goto out; + ni = &ic->ic_bss; /* XXX allocate? */ } + break; } - bs->bs_rssi = rssi; - bs->bs_rstamp = rstamp; - rxseq = bs->bs_rxseq; - bs->bs_rxseq = + ni->ni_rssi = rssi; + ni->ni_rstamp = rstamp; + rxseq = ni->ni_rxseq; + ni->ni_rxseq = le16toh(*(u_int16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT; /* TODO: fragment */ if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) && - rxseq == bs->bs_rxseq) { + rxseq == ni->ni_rxseq) { /* duplicate, silently discarded */ goto out; } - bs->bs_inact = 0; + ni->ni_inact = 0; } switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { case IEEE80211_FC0_TYPE_DATA: - if (ic->ic_flags & IEEE80211_F_ADHOC) { - if (dir != IEEE80211_FC1_DIR_NODS) - goto out; - } else if (ic->ic_flags & IEEE80211_F_HOSTAP) { - if (dir != IEEE80211_FC1_DIR_TODS) - goto out; - } else { + switch (ic->ic_opmode) { + case IEEE80211_M_STA: if (dir != IEEE80211_FC1_DIR_FROMDS) goto out; if ((ifp->if_flags & IFF_SIMPLEX) && - (wh->i_addr1[1] & 0x01) != 0 && - memcmp(wh->i_addr3, ic->ic_myaddr, - IEEE80211_ADDR_LEN) == 0) { + IEEE80211_IS_MULTICAST(wh->i_addr1) && + IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) { /* * In IEEE802.11 network, multicast packet * sent from me is broadcasted from AP. @@ -320,6 +313,15 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp) */ goto out; } + break; + case IEEE80211_M_ADHOC: + if (dir != IEEE80211_FC1_DIR_NODS) + goto out; + break; + case IEEE80211_M_HOSTAP: + if (dir != IEEE80211_FC1_DIR_TODS) + goto out; + break; } if (wh->i_fc[1] & IEEE80211_FC1_WEP) { if (ic->ic_flags & IEEE80211_F_WEPON) { @@ -357,7 +359,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp) subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) goto out; } else { - if (!(ic->ic_flags & IEEE80211_F_ADHOC) && + if (ic->ic_opmode != IEEE80211_M_ADHOC && subtype == IEEE80211_FC0_SUBTYPE_BEACON) goto out; } @@ -372,7 +374,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp) doprint = 1; break; case IEEE80211_FC0_SUBTYPE_PROBE_REQ: - if (ic->ic_flags & IEEE80211_F_ADHOC) + if (ic->ic_opmode == IEEE80211_M_ADHOC) doprint = 1; break; default: @@ -418,15 +420,15 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, int rssi, u_int32_t rstamp) } int -ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_bss *bs, +ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni, struct mbuf *m, int type) { struct ieee80211com *ic = (void *)ifp; struct ieee80211_frame *wh; - if (bs == NULL) - bs = &ic->ic_bss; - bs->bs_inact = 0; + if (ni == NULL) + ni = &ic->ic_bss; + ni->ni_inact = 0; M_PREPEND(m, sizeof(struct ieee80211_frame), M_DONTWAIT); if (m == NULL) return ENOMEM; @@ -435,22 +437,22 @@ ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_bss *bs, wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; *(u_int16_t *)wh->i_dur = 0; *(u_int16_t *)wh->i_seq = - htole16(bs->bs_txseq << IEEE80211_SEQ_SEQ_SHIFT); - bs->bs_txseq++; - memcpy(wh->i_addr1, bs->bs_macaddr, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr2, ic->ic_myaddr, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr3, bs->bs_bssid, IEEE80211_ADDR_LEN); + htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); + ni->ni_txseq++; + IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr); + IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr); + IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); if (ifp->if_flags & IFF_DEBUG) { /* avoid to print too many frames */ - if ((ic->ic_flags & IEEE80211_F_ADHOC) || + if (ic->ic_opmode == IEEE80211_M_ADHOC || (type & IEEE80211_FC0_SUBTYPE_MASK) != IEEE80211_FC0_SUBTYPE_PROBE_RESP) printf("%s: sending %s to %s\n", ifp->if_xname, ieee80211_mgt_subtype_name[ (type & IEEE80211_FC0_SUBTYPE_MASK) >> IEEE80211_FC0_SUBTYPE_SHIFT], - ether_sprintf(bs->bs_macaddr)); + ether_sprintf(ni->ni_macaddr)); } IF_ENQUEUE(&ic->ic_mgtq, m); ifp->if_timer = 1; @@ -465,7 +467,7 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m) struct ether_header eh; struct ieee80211_frame *wh; struct llc *llc; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; if (m->m_len < sizeof(struct ether_header)) { m = m_pullup(m, sizeof(struct ether_header)); @@ -474,23 +476,15 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m) } memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header)); - if ((eh.ether_dhost[0] & 0x01) == 0 && - ((ic->ic_flags & IEEE80211_F_ADHOC) || - (ic->ic_flags & IEEE80211_F_HOSTAP))) { - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(bs->bs_macaddr, eh.ether_dhost, - IEEE80211_ADDR_LEN) == 0) - break; - } - if (bs == NULL || - ((ic->ic_flags & IEEE80211_F_HOSTAP) && - bs->bs_associd == 0)) { - m_freem(m); - return NULL; - } + if (!IEEE80211_IS_MULTICAST(eh.ether_dhost) && + (ic->ic_opmode == IEEE80211_M_ADHOC || + ic->ic_opmode == IEEE80211_M_HOSTAP)) { + ni = ieee80211_find_node(ic, eh.ether_dhost); + if (ni == NULL) + ni = &ic->ic_bss; /*XXX*/ } else - bs = &ic->ic_bss; - bs->bs_inact = 0; + ni = &ic->ic_bss; + ni->ni_inact = 0; m_adj(m, sizeof(struct ether_header) - sizeof(struct llc)); llc = mtod(m, struct llc *); @@ -507,23 +501,27 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m) wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; *(u_int16_t *)wh->i_dur = 0; *(u_int16_t *)wh->i_seq = - htole16(bs->bs_txseq << IEEE80211_SEQ_SEQ_SHIFT); - bs->bs_txseq++; - if (ic->ic_flags & IEEE80211_F_ADHOC) { - wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; - memcpy(wh->i_addr1, eh.ether_dhost, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr2, eh.ether_shost, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr3, bs->bs_bssid, IEEE80211_ADDR_LEN); - } else if (ic->ic_flags & IEEE80211_F_HOSTAP) { - wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS; - memcpy(wh->i_addr1, eh.ether_dhost, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr2, bs->bs_bssid, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr3, eh.ether_shost, IEEE80211_ADDR_LEN); - } else { + htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); + ni->ni_txseq++; + switch (ic->ic_opmode) { + case IEEE80211_M_STA: wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; - memcpy(wh->i_addr1, bs->bs_bssid, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr2, eh.ether_shost, IEEE80211_ADDR_LEN); - memcpy(wh->i_addr3, eh.ether_dhost, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid); + IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost); + IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost); + break; + case IEEE80211_M_ADHOC: + wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; + IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost); + IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost); + IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); + break; + case IEEE80211_M_HOSTAP: + wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS; + IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost); + IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid); + IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost); + break; } return m; } @@ -553,18 +551,19 @@ ieee80211_decap(struct ifnet *ifp, struct mbuf *m) eh = mtod(m, struct ether_header *); switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: - memcpy(eh->ether_dhost, wh.i_addr1, IEEE80211_ADDR_LEN); - memcpy(eh->ether_shost, wh.i_addr2, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); + IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); break; case IEEE80211_FC1_DIR_TODS: - memcpy(eh->ether_dhost, wh.i_addr3, IEEE80211_ADDR_LEN); - memcpy(eh->ether_shost, wh.i_addr2, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3); + IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); break; case IEEE80211_FC1_DIR_FROMDS: - memcpy(eh->ether_dhost, wh.i_addr1, IEEE80211_ADDR_LEN); - memcpy(eh->ether_shost, wh.i_addr3, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); + IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3); break; case IEEE80211_FC1_DIR_DSTODS: + /* not yet supported */ DPRINTF(("ieee80211_decap: DS to DS\n")); m_freem(m); return NULL; @@ -633,7 +632,12 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ieee80211_nwid nwid; struct ieee80211_nwkey *nwkey; struct ieee80211_power *power; + struct ieee80211_bssid *bssid; + struct ieee80211_channel *chan; struct ieee80211_wepkey keys[IEEE80211_WEP_NKID]; + static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; switch (cmd) { case SIOCS80211NWID: @@ -657,8 +661,8 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len); break; default: - nwid.i_len = ic->ic_bss.bs_esslen; - memcpy(nwid.i_nwid, ic->ic_bss.bs_essid, nwid.i_len); + nwid.i_len = ic->ic_bss.ni_esslen; + memcpy(nwid.i_nwid, ic->ic_bss.ni_essid, nwid.i_len); break; } error = copyout(&nwid, ifr->ifr_data, sizeof(nwid)); @@ -756,6 +760,77 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0; power->i_maxsleep = ic->ic_lintval; break; + case SIOCS80211BSSID: + bssid = (struct ieee80211_bssid *)data; + if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr)) + ic->ic_flags &= ~IEEE80211_F_DESBSSID; + else { + ic->ic_flags |= IEEE80211_F_DESBSSID; + IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid); + } + if (ic->ic_opmode == IEEE80211_M_HOSTAP) + break; + switch (ic->ic_state) { + case IEEE80211_S_INIT: + case IEEE80211_S_SCAN: + error = ENETRESET; + break; + default: + if ((ic->ic_flags & IEEE80211_F_DESBSSID) && + !IEEE80211_ADDR_EQ(ic->ic_des_bssid, + ic->ic_bss.ni_bssid)) + error = ENETRESET; + break; + } + break; + case SIOCG80211BSSID: + bssid = (struct ieee80211_bssid *)data; + if (ic->ic_flags & IEEE80211_F_DESBSSID) + IEEE80211_ADDR_COPY(bssid->i_bssid, + ic->ic_bss.ni_bssid); + else + memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN); + break; + case SIOCS80211CHANNEL: + chan = (struct ieee80211_channel *)data; + if (chan->i_channel > IEEE80211_CHAN_MAX || + isclr(ic->ic_chan_active, chan->i_channel)) { + /* invalid channel request to clear current config */ + ic->ic_des_chan = -1; + } else + ic->ic_ibss_chan = ic->ic_des_chan = chan->i_channel; + switch (ic->ic_state) { + case IEEE80211_S_INIT: + case IEEE80211_S_SCAN: + error = ENETRESET; + break; + default: + if (ic->ic_opmode == IEEE80211_M_STA) { + if (ic->ic_des_chan >= 0 && + ic->ic_bss.ni_chan != ic->ic_des_chan) + error = ENETRESET; + } else { + if (ic->ic_bss.ni_chan != ic->ic_ibss_chan) + error = ENETRESET; + } + break; + } + break; + case SIOCG80211CHANNEL: + chan = (struct ieee80211_channel *)data; + switch (ic->ic_state) { + case IEEE80211_S_INIT: + case IEEE80211_S_SCAN: + if (ic->ic_opmode == IEEE80211_M_STA) + chan->i_channel = ic->ic_des_chan; + else + chan->i_channel = ic->ic_ibss_chan; + break; + default: + chan->i_channel = ic->ic_bss.ni_chan; + break; + } + break; case SIOCGIFGENERIC: error = ieee80211_cfgget(ifp, cmd, data); break; @@ -861,7 +936,7 @@ void ieee80211_watchdog(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; - struct ieee80211_bss *bs, *nextbs; + struct ieee80211_node *ni, *nextbs; if (ic->ic_scan_timer) { if (--ic->ic_scan_timer == 0) { @@ -875,26 +950,26 @@ ieee80211_watchdog(struct ifnet *ifp) } if (ic->ic_inact_timer) { if (--ic->ic_inact_timer == 0) { - for (bs = TAILQ_FIRST(&ic->ic_scan); bs != NULL; ) { - if (++bs->bs_inact <= IEEE80211_INACT_MAX) { - bs = TAILQ_NEXT(bs, bs_list); + for (ni = TAILQ_FIRST(&ic->ic_node); ni != NULL; ) { + if (++ni->ni_inact <= IEEE80211_INACT_MAX) { + ni = TAILQ_NEXT(ni, ni_list); continue; } if (ifp->if_flags & IFF_DEBUG) printf("%s: station %s deauthenticate" " (reason %d)\n", ifp->if_xname, - ether_sprintf(bs->bs_macaddr), + ether_sprintf(ni->ni_macaddr), IEEE80211_REASON_AUTH_EXPIRE); - nextbs = TAILQ_NEXT(bs, bs_list); - IEEE80211_SEND_MGMT(ic, bs, + nextbs = TAILQ_NEXT(ni, ni_list); + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_EXPIRE); - TAILQ_REMOVE(&ic->ic_scan, bs, bs_list); - free(bs, M_DEVBUF); - bs = nextbs; + TAILQ_REMOVE(&ic->ic_node, ni, ni_list); + free(ni, M_DEVBUF); + ni = nextbs; } - if (!TAILQ_EMPTY(&ic->ic_scan)) + if (!TAILQ_EMPTY(&ic->ic_node)) ic->ic_inact_timer = IEEE80211_INACT_WAIT; } } @@ -909,19 +984,19 @@ ieee80211_next_scan(struct ifnet *ifp) struct ieee80211com *ic = (void *)ifp; int chan; - chan = ic->ic_bss.bs_chan; + chan = ic->ic_bss.ni_chan; for (;;) { chan = (chan + 1) % (IEEE80211_CHAN_MAX + 1); if (isset(ic->ic_chan_active, chan)) break; - if (chan == ic->ic_bss.bs_chan) { + if (chan == ic->ic_bss.ni_chan) { DPRINTF(("ieee80211_next_scan: no chan available\n")); return; } } DPRINTF(("ieee80211_next_scan: chan %d->%d\n", - ic->ic_bss.bs_chan, chan)); - ic->ic_bss.bs_chan = chan; + ic->ic_bss.ni_chan, chan)); + ic->ic_bss.ni_chan = chan; ieee80211_new_state(ifp, IEEE80211_S_SCAN, -1); } @@ -929,45 +1004,44 @@ void ieee80211_end_scan(struct ifnet *ifp) { struct ieee80211com *ic = (void *)ifp; - struct ieee80211_bss *bs, *nextbs, *selbs; + struct ieee80211_node *ni, *nextbs, *selbs; void *p; u_int8_t rate; int i, fail; - bs = TAILQ_FIRST(&ic->ic_scan); - if (bs == NULL) { + ni = TAILQ_FIRST(&ic->ic_node); + if (ni == NULL) { DPRINTF(("ieee80211_end_scan: no scan candidate\n")); notfound: - if ((ic->ic_flags & IEEE80211_F_ADHOC) && + if (ic->ic_opmode == IEEE80211_M_ADHOC && (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen != 0) { - bs = &ic->ic_bss; + ni = &ic->ic_bss; if (ifp->if_flags & IFF_DEBUG) printf("%s: creating ibss\n", ifp->if_xname); ic->ic_flags |= IEEE80211_F_SIBSS; - bs->bs_nrate = 0; + ni->ni_nrate = 0; for (i = 0; i < IEEE80211_RATE_SIZE; i++) { if (ic->ic_sup_rates[i]) - bs->bs_rates[bs->bs_nrate++] = + ni->ni_rates[ni->ni_nrate++] = ic->ic_sup_rates[i]; } - memcpy(bs->bs_macaddr, ic->ic_myaddr, - IEEE80211_ADDR_LEN); - memcpy(bs->bs_bssid, ic->ic_myaddr, IEEE80211_ADDR_LEN); - bs->bs_bssid[0] |= 0x02; /* local bit for IBSS */ - bs->bs_esslen = ic->ic_des_esslen; - memcpy(bs->bs_essid, ic->ic_des_essid, bs->bs_esslen); - bs->bs_rssi = 0; - bs->bs_rstamp = 0; - memset(bs->bs_tstamp, 0, sizeof(bs->bs_tstamp)); - bs->bs_intval = ic->ic_lintval; - bs->bs_capinfo = IEEE80211_CAPINFO_IBSS; + IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); + IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr); + ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */ + ni->ni_esslen = ic->ic_des_esslen; + memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); + ni->ni_rssi = 0; + ni->ni_rstamp = 0; + memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); + ni->ni_intval = ic->ic_lintval; + ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; if (ic->ic_flags & IEEE80211_F_WEPON) - bs->bs_capinfo |= IEEE80211_CAPINFO_PRIVACY; - bs->bs_chan = ic->ic_ibss_chan; - if (ic->ic_flags & IEEE80211_F_FH) { - bs->bs_fhdwell = 200; /* XXX */ - bs->bs_fhindex = 1; + ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; + ni->ni_chan = ic->ic_ibss_chan; + if (ic->ic_phytype == IEEE80211_T_FH) { + ni->ni_fhdwell = 200; /* XXX */ + ni->ni_fhindex = 1; } ieee80211_new_state(ifp, IEEE80211_S_RUN, -1); return; @@ -983,84 +1057,90 @@ ieee80211_end_scan(struct ifnet *ifp) } selbs = NULL; if (ifp->if_flags & IFF_DEBUG) - printf("%s:\tmacaddr bssid chan rssi rate flag wep essid\n", + printf("%s:\tmacaddr bssid chan rssi rate flag wep essid\n", ifp->if_xname); - for (; bs != NULL; bs = nextbs) { - nextbs = TAILQ_NEXT(bs, bs_list); - if (bs->bs_fails) { + for (; ni != NULL; ni = nextbs) { + nextbs = TAILQ_NEXT(ni, ni_list); + if (ni->ni_fails) { /* * The configuration of the access points may change * during my scan. So delete the entry for the AP * and retry to associate if there is another beacon. */ - if (bs->bs_fails++ > 2) { - TAILQ_REMOVE(&ic->ic_scan, bs, bs_list); - free(bs, M_DEVBUF); + if (ni->ni_fails++ > 2) { + TAILQ_REMOVE(&ic->ic_node, ni, ni_list); + free(ni, M_DEVBUF); } continue; } fail = 0; - if (isclr(ic->ic_chan_active, bs->bs_chan)) + if (isclr(ic->ic_chan_active, ni->ni_chan)) fail |= 0x01; - if (ic->ic_flags & IEEE80211_F_ADHOC) { - if ((bs->bs_capinfo & IEEE80211_CAPINFO_IBSS) == 0) + if (ic->ic_des_chan >= 0 && ni->ni_chan != ic->ic_des_chan) + fail |= 0x01; + if (ic->ic_opmode == IEEE80211_M_ADHOC) { + if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) fail |= 0x02; } else { - if ((bs->bs_capinfo & IEEE80211_CAPINFO_ESS) == 0) + if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0) fail |= 0x02; } if (ic->ic_flags & IEEE80211_F_WEPON) { - if ((bs->bs_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) + if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) fail |= 0x04; } else { - if (bs->bs_capinfo & IEEE80211_CAPINFO_PRIVACY) + if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) fail |= 0x04; } - rate = ieee80211_fix_rate(ic, bs, IEEE80211_F_DONEGO); + rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO); if (rate & IEEE80211_RATE_BASIC) fail |= 0x08; if (ic->ic_des_esslen != 0 && - (bs->bs_esslen != ic->ic_des_esslen || - memcmp(bs->bs_essid, ic->ic_des_essid, + (ni->ni_esslen != ic->ic_des_esslen || + memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen != 0))) fail |= 0x10; + if ((ic->ic_flags & IEEE80211_F_DESBSSID) && + !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid)) + fail |= 0x20; if (ifp->if_flags & IFF_DEBUG) { printf(" %c %s", fail ? '-' : '+', - ether_sprintf(bs->bs_macaddr)); - printf(" %s", ether_sprintf(bs->bs_bssid)); - printf(" %3d%c", bs->bs_chan, fail & 0x01 ? '!' : ' '); - printf(" %+4d", bs->bs_rssi); + ether_sprintf(ni->ni_macaddr)); + printf(" %s%c", ether_sprintf(ni->ni_bssid), + fail & 0x20 ? '!' : ' '); + printf(" %3d%c", ni->ni_chan, fail & 0x01 ? '!' : ' '); + printf(" %+4d", ni->ni_rssi); printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2, fail & 0x08 ? '!' : ' '); printf(" %4s%c", - (bs->bs_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" : - (bs->bs_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : + (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" : + (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : "????", fail & 0x02 ? '!' : ' '); printf(" %3s%c ", - (bs->bs_capinfo & IEEE80211_CAPINFO_PRIVACY) ? + (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ? "wep" : "no", fail & 0x04 ? '!' : ' '); - ieee80211_print_essid(bs->bs_essid, bs->bs_esslen); + ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); printf("%s\n", fail & 0x10 ? "!" : ""); } if (!fail) { - if (selbs == NULL || bs->bs_rssi > selbs->bs_rssi) - selbs = bs; + if (selbs == NULL || ni->ni_rssi > selbs->ni_rssi) + selbs = ni; } } if (selbs == NULL) goto notfound; - p = ic->ic_bss.bs_private; + p = ic->ic_bss.ni_private; ic->ic_bss = *selbs; - ic->ic_bss.bs_private = p; + ic->ic_bss.ni_private = p; if (p != NULL && ic->ic_bss_privlen) - memcpy(p, selbs->bs_private, ic->ic_bss_privlen); - if (ic->ic_flags & IEEE80211_F_ADHOC) { + memcpy(p, selbs->ni_private, ic->ic_bss_privlen); + if (ic->ic_opmode == IEEE80211_M_ADHOC) { ieee80211_fix_rate(ic, &ic->ic_bss, IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (ic->ic_bss.bs_nrate == 0) { - selbs->bs_fails++; + if (ic->ic_bss.ni_nrate == 0) { + selbs->ni_fails++; goto notfound; } ieee80211_new_state(ifp, IEEE80211_S_RUN, -1); @@ -1068,45 +1148,54 @@ ieee80211_end_scan(struct ifnet *ifp) ieee80211_new_state(ifp, IEEE80211_S_AUTH, -1); } -struct ieee80211_bss * -ieee80211_alloc_bss(struct ieee80211com *ic, int copy) +struct ieee80211_node * +ieee80211_alloc_node(struct ieee80211com *ic, int copy) { - struct ieee80211_bss *bs; + struct ieee80211_node *ni; - bs = malloc(sizeof(struct ieee80211_bss) + ic->ic_bss_privlen, + ni = malloc(sizeof(struct ieee80211_node) + ic->ic_bss_privlen, M_DEVBUF, M_NOWAIT); - if (bs == NULL) + if (ni == NULL) return NULL; if (copy) - memcpy(bs, &ic->ic_bss, sizeof(struct ieee80211_bss)); + memcpy(ni, &ic->ic_bss, sizeof(struct ieee80211_node)); else - memset(bs, 0, sizeof(struct ieee80211_bss)); + memset(ni, 0, sizeof(struct ieee80211_node)); if (ic->ic_bss_privlen) { - bs->bs_private = &bs[1]; - memset(bs->bs_private, 0, ic->ic_bss_privlen); + ni->ni_private = &ni[1]; + memset(ni->ni_private, 0, ic->ic_bss_privlen); } - TAILQ_INSERT_TAIL(&ic->ic_scan, bs, bs_list); - if ((ic->ic_flags & IEEE80211_F_HOSTAP) || - (ic->ic_flags & IEEE80211_F_ADHOC)) + TAILQ_INSERT_TAIL(&ic->ic_node, ni, ni_list); + if (ic->ic_opmode == IEEE80211_M_ADHOC || + ic->ic_opmode == IEEE80211_M_HOSTAP) ic->ic_inact_timer = IEEE80211_INACT_WAIT; - return bs; + return ni; +} + +struct ieee80211_node * +ieee80211_find_node(struct ieee80211com *ic, u_int8_t *macaddr) +{ + struct ieee80211_node *ni; + + TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { + if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) + break; + } + return ni; } void -ieee80211_free_scan(struct ifnet *ifp) +ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni) { - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_bss *bs; - while ((bs = TAILQ_FIRST(&ic->ic_scan)) != NULL) { - TAILQ_REMOVE(&ic->ic_scan, bs, bs_list); - free(bs, M_DEVBUF); - } - ic->ic_inact_timer = 0; + TAILQ_REMOVE(&ic->ic_node, ni, ni_list); + free(ni, M_DEVBUF); + if (TAILQ_EMPTY(&ic->ic_node)) + ic->ic_inact_timer = 0; } int -ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_bss *bs, int flags) +ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags) { int i, j, ignore, error; int okrate, badrate; @@ -1114,19 +1203,19 @@ ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_bss *bs, int flags) error = 0; okrate = badrate = 0; - for (i = 0; i < bs->bs_nrate; ) { + for (i = 0; i < ni->ni_nrate; ) { ignore = 0; if (flags & IEEE80211_F_DOSORT) { - for (j = i + 1; j < bs->bs_nrate; j++) { - if ((bs->bs_rates[i] & IEEE80211_RATE_VAL) > - (bs->bs_rates[j] & IEEE80211_RATE_VAL)) { - r = bs->bs_rates[i]; - bs->bs_rates[i] = bs->bs_rates[j]; - bs->bs_rates[j] = r; + for (j = i + 1; j < ni->ni_nrate; j++) { + if ((ni->ni_rates[i] & IEEE80211_RATE_VAL) > + (ni->ni_rates[j] & IEEE80211_RATE_VAL)) { + r = ni->ni_rates[i]; + ni->ni_rates[i] = ni->ni_rates[j]; + ni->ni_rates[j] = r; } } } - r = bs->bs_rates[i] & IEEE80211_RATE_VAL; + r = ni->ni_rates[i] & IEEE80211_RATE_VAL; badrate = r; if (flags & IEEE80211_F_DOFRATE) { if (ic->ic_fixed_rate >= 0 && @@ -1141,22 +1230,22 @@ ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_bss *bs, int flags) break; } if (j == IEEE80211_RATE_SIZE) { - if (bs->bs_rates[i] & IEEE80211_RATE_BASIC) + if (ni->ni_rates[i] & IEEE80211_RATE_BASIC) error++; ignore++; } } if (flags & IEEE80211_F_DODEL) { if (ignore) { - bs->bs_nrate--; - for (j = i; j < bs->bs_nrate; j++) - bs->bs_rates[j] = bs->bs_rates[j + 1]; - bs->bs_rates[j] = 0; + ni->ni_nrate--; + for (j = i; j < ni->ni_nrate; j++) + ni->ni_rates[j] = ni->ni_rates[j + 1]; + ni->ni_rates[j] = 0; continue; } } if (!ignore) - okrate = bs->bs_rates[i]; + okrate = ni->ni_rates[i]; i++; } if (okrate == 0 || error != 0) @@ -1165,7 +1254,7 @@ ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_bss *bs, int flags) } static int -ieee80211_send_prreq(struct ieee80211com *ic, struct ieee80211_bss *bs, +ieee80211_send_prreq(struct ieee80211com *ic, struct ieee80211_node *ni, int type, int dummy) { int i, ret; @@ -1197,18 +1286,18 @@ ieee80211_send_prreq(struct ieee80211com *ic, struct ieee80211_bss *bs, frm += i; m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); - ret = ieee80211_mgmt_output(&ic->ic_if, bs, m, type); + ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type); ic->ic_mgt_timer = IEEE80211_TRANS_WAIT; return ret; } static int -ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_bss *bs0, +ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_node *bs0, int type, int dummy) { struct mbuf *m; u_int8_t *frm; - struct ieee80211_bss *bs = &ic->ic_bss; + struct ieee80211_node *ni = &ic->ic_bss; u_int16_t capinfo; /* @@ -1228,9 +1317,9 @@ ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_bss *bs0, memset(frm, 0, 8); /* timestamp should be filled later */ frm += 8; - *(u_int16_t *)frm = htole16(bs->bs_intval); + *(u_int16_t *)frm = htole16(ni->ni_intval); frm += 2; - if (ic->ic_flags & IEEE80211_F_ADHOC) + if (ic->ic_opmode == IEEE80211_M_ADHOC) capinfo = IEEE80211_CAPINFO_IBSS; else capinfo = IEEE80211_CAPINFO_ESS; @@ -1239,18 +1328,18 @@ ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_bss *bs0, *(u_int16_t *)frm = htole16(capinfo); frm += 2; *frm++ = IEEE80211_ELEMID_SSID; - *frm++ = bs->bs_esslen; - memcpy(frm, bs->bs_essid, bs->bs_esslen); - frm += bs->bs_esslen; + *frm++ = ni->ni_esslen; + memcpy(frm, ni->ni_essid, ni->ni_esslen); + frm += ni->ni_esslen; *frm++ = IEEE80211_ELEMID_RATES; - *frm++ = bs->bs_nrate; - memcpy(frm, bs->bs_rates, bs->bs_nrate); - frm += bs->bs_nrate; - if (ic->ic_flags & IEEE80211_F_ADHOC) { + *frm++ = ni->ni_nrate; + memcpy(frm, ni->ni_rates, ni->ni_nrate); + frm += ni->ni_nrate; + if (ic->ic_opmode == IEEE80211_M_ADHOC) { *frm++ = IEEE80211_ELEMID_IBSSPARMS; *frm++ = 2; *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ - } else { + } else { /* IEEE80211_M_HOSTAP */ /* TODO: TIM */ *frm++ = IEEE80211_ELEMID_TIM; *frm++ = 4; /* length */ @@ -1266,7 +1355,7 @@ ieee80211_send_prresp(struct ieee80211com *ic, struct ieee80211_bss *bs0, } static int -ieee80211_send_auth(struct ieee80211com *ic, struct ieee80211_bss *bs, +ieee80211_send_auth(struct ieee80211com *ic, struct ieee80211_node *ni, int type, int seq) { struct mbuf *m; @@ -1283,15 +1372,14 @@ ieee80211_send_auth(struct ieee80211com *ic, struct ieee80211_bss *bs, frm[0] = htole16(IEEE80211_AUTH_ALG_OPEN); frm[1] = htole16(seq); frm[2] = 0; /* status */ - ret = ieee80211_mgmt_output(&ic->ic_if, bs, m, type); - if ((ic->ic_flags & IEEE80211_F_ADHOC) != 0 && - (ic->ic_flags & IEEE80211_F_HOSTAP) != 0) + ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type); + if (ic->ic_opmode == IEEE80211_M_STA) ic->ic_mgt_timer = IEEE80211_TRANS_WAIT; return ret; } static int -ieee80211_send_deauth(struct ieee80211com *ic, struct ieee80211_bss *bs, +ieee80211_send_deauth(struct ieee80211com *ic, struct ieee80211_node *ni, int type, int reason) { struct ifnet *ifp = &ic->ic_if; @@ -1299,18 +1387,18 @@ ieee80211_send_deauth(struct ieee80211com *ic, struct ieee80211_bss *bs, if (ifp->if_flags & IFF_DEBUG) printf("%s: station %s deauthenticate (reason %d)\n", - ifp->if_xname, ether_sprintf(bs->bs_macaddr), reason); + ifp->if_xname, ether_sprintf(ni->ni_macaddr), reason); MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return ENOMEM; MH_ALIGN(m, 2); m->m_pkthdr.len = m->m_len = 2; *mtod(m, u_int16_t *) = htole16(reason); - return ieee80211_mgmt_output(&ic->ic_if, bs, m, type); + return ieee80211_mgmt_output(&ic->ic_if, ni, m, type); } static int -ieee80211_send_asreq(struct ieee80211com *ic, struct ieee80211_bss *bs, +ieee80211_send_asreq(struct ieee80211com *ic, struct ieee80211_node *ni, int type, int dummy) { struct mbuf *m; @@ -1333,9 +1421,9 @@ ieee80211_send_asreq(struct ieee80211com *ic, struct ieee80211_bss *bs, frm = mtod(m, u_int8_t *); capinfo = 0; - if (ic->ic_flags & IEEE80211_F_ADHOC) + if (ic->ic_opmode == IEEE80211_M_ADHOC) capinfo |= IEEE80211_CAPINFO_IBSS; - else + else /* IEEE80211_M_STA */ capinfo |= IEEE80211_CAPINFO_ESS; if (ic->ic_flags & IEEE80211_F_WEPON) capinfo |= IEEE80211_CAPINFO_PRIVACY; @@ -1346,30 +1434,30 @@ ieee80211_send_asreq(struct ieee80211com *ic, struct ieee80211_bss *bs, frm += 2; if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { - memcpy(frm, ic->ic_bss.bs_bssid, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(frm, ic->ic_bss.ni_bssid); frm += IEEE80211_ADDR_LEN; } *frm++ = IEEE80211_ELEMID_SSID; - *frm++ = bs->bs_esslen; - memcpy(frm, bs->bs_essid, bs->bs_esslen); - frm += bs->bs_esslen; + *frm++ = ni->ni_esslen; + memcpy(frm, ni->ni_essid, ni->ni_esslen); + frm += ni->ni_esslen; *frm++ = IEEE80211_ELEMID_RATES; rates = frm++; /* update later */ for (i = 0; i < IEEE80211_RATE_SIZE; i++) { - if (bs->bs_rates[i] != 0) - *frm++ = bs->bs_rates[i]; + if (ni->ni_rates[i] != 0) + *frm++ = ni->ni_rates[i]; } *rates = frm - (rates + 1); m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); - ret = ieee80211_mgmt_output(&ic->ic_if, bs, m, type); + ret = ieee80211_mgmt_output(&ic->ic_if, ni, m, type); ic->ic_mgt_timer = IEEE80211_TRANS_WAIT; return ret; } static int -ieee80211_send_asresp(struct ieee80211com *ic, struct ieee80211_bss *bs, +ieee80211_send_asresp(struct ieee80211com *ic, struct ieee80211_node *ni, int type, int status) { struct mbuf *m; @@ -1399,29 +1487,29 @@ ieee80211_send_asresp(struct ieee80211com *ic, struct ieee80211_bss *bs, *(u_int16_t *)frm = htole16(status); frm += 2; - if (status == IEEE80211_STATUS_SUCCESS && bs != NULL) - *(u_int16_t *)frm = htole16(bs->bs_associd); + if (status == IEEE80211_STATUS_SUCCESS && ni != NULL) + *(u_int16_t *)frm = htole16(ni->ni_associd); else *(u_int16_t *)frm = htole16(0); frm += 2; *frm++ = IEEE80211_ELEMID_RATES; rates = frm++; /* update later */ - if (bs != NULL) - r = bs->bs_rates; + if (ni != NULL) + r = ni->ni_rates; else - r = ic->ic_bss.bs_rates; + r = ic->ic_bss.ni_rates; for (i = 0; i < IEEE80211_RATE_SIZE; i++, r++) { if (*r != 0) *frm++ = *r; } *rates = frm - (rates + 1); m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); - return ieee80211_mgmt_output(&ic->ic_if, bs, m, type); + return ieee80211_mgmt_output(&ic->ic_if, ni, m, type); } static int -ieee80211_send_disassoc(struct ieee80211com *ic, struct ieee80211_bss *bs, +ieee80211_send_disassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int type, int reason) { struct ifnet *ifp = &ic->ic_if; @@ -1429,14 +1517,14 @@ ieee80211_send_disassoc(struct ieee80211com *ic, struct ieee80211_bss *bs, if (ifp->if_flags & IFF_DEBUG) printf("%s: station %s disassociate (reason %d)\n", - ifp->if_xname, ether_sprintf(bs->bs_macaddr), reason); + ifp->if_xname, ether_sprintf(ni->ni_macaddr), reason); MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return ENOMEM; MH_ALIGN(m, 2); m->m_pkthdr.len = m->m_len = 2; *mtod(m, u_int16_t *) = htole16(reason); - return ieee80211_mgmt_output(&ic->ic_if, bs, m, + return ieee80211_mgmt_output(&ic->ic_if, ni, m, IEEE80211_FC0_SUBTYPE_DISASSOC); } @@ -1445,12 +1533,12 @@ ieee80211_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, int rssi, u_int32_t rstamp) { struct ieee80211_frame *wh; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; u_int8_t *frm, *efrm, *tstamp, *bintval, *capinfo, *ssid, *rates; u_int8_t chan, fhindex; u_int16_t fhdwell; - if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0 && + if (ic->ic_opmode != IEEE80211_M_ADHOC && ic->ic_state != IEEE80211_S_SCAN) { /* XXX: may be useful for background scan */ return; @@ -1472,7 +1560,7 @@ ieee80211_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, int rssi, bintval = frm; frm += 2; capinfo = frm; frm += 2; ssid = rates = NULL; - chan = ic->ic_bss.bs_chan; + chan = ic->ic_bss.ni_chan; fhdwell = 0; fhindex = 0; while (frm < efrm) { @@ -1484,14 +1572,14 @@ ieee80211_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, int rssi, rates = frm; break; case IEEE80211_ELEMID_FHPARMS: - if (ic->ic_flags & IEEE80211_F_FH) { + if (ic->ic_phytype == IEEE80211_T_FH) { fhdwell = (frm[3] << 8) | frm[2]; chan = IEEE80211_FH_CHAN(frm[4], frm[5]); fhindex = frm[6]; } break; case IEEE80211_ELEMID_DSPARMS: - if (ic->ic_flags & IEEE80211_F_DS) + if (ic->ic_phytype == IEEE80211_T_DS) chan = frm[2]; break; } @@ -1507,55 +1595,51 @@ ieee80211_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, int rssi, ssid[1], ether_sprintf(wh->i_addr2))); return; } - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(bs->bs_macaddr, wh->i_addr2, - IEEE80211_ADDR_LEN) == 0 && - memcmp(bs->bs_bssid, wh->i_addr3, - IEEE80211_ADDR_LEN) == 0) - break; - } + ni = ieee80211_find_node(ic, wh->i_addr2); #ifdef IEEE80211_DEBUG if (ieee80211_debug && - (ieee80211_debug > 1 || bs == NULL || + (ieee80211_debug > 1 || ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) { printf("ieee80211_recv_prreq: %sbeacon ", - (bs == NULL ? "new " : "")); + (ni == NULL ? "new " : "")); ieee80211_print_essid(ssid + 2, ssid[1]); printf(" from %s\n", ether_sprintf(wh->i_addr2)); } #endif - if (bs == NULL) { - if ((bs = ieee80211_alloc_bss(ic, 0)) == NULL) + if (ni == NULL) { + if ((ni = ieee80211_alloc_node(ic, 0)) == NULL) return; - memcpy(bs->bs_macaddr, wh->i_addr2, IEEE80211_ADDR_LEN); - memcpy(bs->bs_bssid, wh->i_addr3, IEEE80211_ADDR_LEN); - bs->bs_esslen = ssid[1]; - memset(bs->bs_essid, 0, sizeof(bs->bs_essid)); - memcpy(bs->bs_essid, ssid + 2, ssid[1]); - } else if (ssid[1] != 0) { - /* - * Update ESSID at probe response to adopt hidden AP by - * Lucent/Cisco, which announces null ESSID in beacon. - */ - if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == - IEEE80211_FC0_SUBTYPE_PROBE_RESP) { - bs->bs_esslen = ssid[1]; - memset(bs->bs_essid, 0, sizeof(bs->bs_essid)); - memcpy(bs->bs_essid, ssid + 2, ssid[1]); + IEEE80211_ADDR_COPY(ni->ni_macaddr, wh->i_addr2); + ni->ni_esslen = ssid[1]; + memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); + memcpy(ni->ni_essid, ssid + 2, ssid[1]); + } else { + if (ssid[1] != 0) { + /* + * Update ESSID at probe response to adopt hidden AP by + * Lucent/Cisco, which announces null ESSID in beacon. + */ + if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == + IEEE80211_FC0_SUBTYPE_PROBE_RESP) { + ni->ni_esslen = ssid[1]; + memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); + memcpy(ni->ni_essid, ssid + 2, ssid[1]); + } } } - memset(bs->bs_rates, 0, IEEE80211_RATE_SIZE); - bs->bs_nrate = rates[1]; - memcpy(bs->bs_rates, rates + 2, bs->bs_nrate); - ieee80211_fix_rate(ic, bs, IEEE80211_F_DOSORT); - bs->bs_rssi = rssi; - bs->bs_rstamp = rstamp; - memcpy(bs->bs_tstamp, tstamp, sizeof(bs->bs_tstamp)); - bs->bs_intval = le16toh(*(u_int16_t *)bintval); - bs->bs_capinfo = le16toh(*(u_int16_t *)capinfo); - bs->bs_chan = chan; - bs->bs_fhdwell = fhdwell; - bs->bs_fhindex = fhindex; + IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); + memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE); + ni->ni_nrate = rates[1]; + memcpy(ni->ni_rates, rates + 2, ni->ni_nrate); + ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT); + ni->ni_rssi = rssi; + ni->ni_rstamp = rstamp; + memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp)); + ni->ni_intval = le16toh(*(u_int16_t *)bintval); + ni->ni_capinfo = le16toh(*(u_int16_t *)capinfo); + ni->ni_chan = chan; + ni->ni_fhdwell = fhdwell; + ni->ni_fhindex = fhindex; if (ic->ic_state == IEEE80211_S_SCAN && ic->ic_scan_timer == 0) ieee80211_end_scan(&ic->ic_if); } @@ -1565,13 +1649,12 @@ ieee80211_recv_prreq(struct ieee80211com *ic, struct mbuf *m0, int rssi, u_int32_t rstamp) { struct ieee80211_frame *wh; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; u_int8_t *frm, *efrm, *ssid, *rates; u_int8_t rate; int allocbs; - if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0 && - (ic->ic_flags & IEEE80211_F_HOSTAP) == 0) + if (ic->ic_opmode == IEEE80211_M_STA) return; if (ic->ic_state != IEEE80211_S_RUN) return; @@ -1602,8 +1685,8 @@ ieee80211_recv_prreq(struct ieee80211com *ic, struct mbuf *m0, int rssi, return; } if (ssid[1] != 0 && - (ssid[1] != ic->ic_bss.bs_esslen || - memcmp(ssid + 2, ic->ic_bss.bs_essid, ic->ic_bss.bs_esslen) != 0)) { + (ssid[1] != ic->ic_bss.ni_esslen || + memcmp(ssid + 2, ic->ic_bss.ni_essid, ic->ic_bss.ni_esslen) != 0)) { #ifdef IEEE80211_DEBUG if (ieee80211_debug) { printf("ieee80211_recv_prreq: ssid unmatch "); @@ -1614,40 +1697,32 @@ ieee80211_recv_prreq(struct ieee80211com *ic, struct mbuf *m0, int rssi, return; } - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(bs->bs_macaddr, wh->i_addr2, - IEEE80211_ADDR_LEN) == 0) - break; - } - if (bs == NULL) { - if ((bs = ieee80211_alloc_bss(ic, 1)) == NULL) + ni = ieee80211_find_node(ic, wh->i_addr2); + if (ni == NULL) { + if ((ni = ieee80211_alloc_node(ic, 1)) == NULL) return; DPRINTF(("ieee80211_recv_prreq: new req from %s\n", ether_sprintf(wh->i_addr2))); - memcpy(bs->bs_macaddr, wh->i_addr2, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(ni->ni_macaddr, wh->i_addr2); allocbs = 1; } else allocbs = 0; - memset(bs->bs_rates, 0, IEEE80211_RATE_SIZE); - bs->bs_nrate = rates[1]; - memcpy(bs->bs_rates, rates + 2, bs->bs_nrate); - bs->bs_rssi = rssi; - bs->bs_rstamp = rstamp; - rate = ieee80211_fix_rate(ic, bs, IEEE80211_F_DOSORT | + memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE); + ni->ni_nrate = rates[1]; + memcpy(ni->ni_rates, rates + 2, ni->ni_nrate); + ni->ni_rssi = rssi; + ni->ni_rstamp = rstamp; + rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); if (rate & IEEE80211_RATE_BASIC) { DPRINTF(("ieee80211_recv_prreq: rate negotiation failed: %s\n", ether_sprintf(wh->i_addr2))); } else { - IEEE80211_SEND_MGMT(ic, bs, IEEE80211_FC0_SUBTYPE_PROBE_RESP, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0); } - if (allocbs && (ic->ic_flags & IEEE80211_F_HOSTAP)) { - TAILQ_REMOVE(&ic->ic_scan, bs, bs_list); - free(bs, M_DEVBUF); - if (TAILQ_EMPTY(&ic->ic_scan)) - ic->ic_inact_timer = 0; - } + if (allocbs && (ic->ic_opmode == IEEE80211_M_HOSTAP)) + ieee80211_free_node(ic, ni); } static void @@ -1656,7 +1731,7 @@ ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0, int rssi, { struct ifnet *ifp = &ic->ic_if; struct ieee80211_frame *wh; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; u_int8_t *frm, *efrm; u_int16_t algo, seq, status; int allocbs; @@ -1685,54 +1760,50 @@ ieee80211_recv_auth(struct ieee80211com *ic, struct mbuf *m0, int rssi, algo, ether_sprintf(wh->i_addr2))); return; } - if (ic->ic_flags & IEEE80211_F_ADHOC) { + switch (ic->ic_opmode) { + case IEEE80211_M_ADHOC: if (ic->ic_state != IEEE80211_S_RUN || seq != 1) return; ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH, wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); - return; - } - if (ic->ic_flags & IEEE80211_F_HOSTAP) { + break; + + case IEEE80211_M_HOSTAP: if (ic->ic_state != IEEE80211_S_RUN || seq != 1) return; allocbs = 0; - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(bs->bs_macaddr, wh->i_addr2, - IEEE80211_ADDR_LEN) == 0) - break; - } - if (bs == NULL) { - if ((bs = ieee80211_alloc_bss(ic, 0)) == NULL) + ni = ieee80211_find_node(ic, wh->i_addr2); + if (ni == NULL) { + if ((ni = ieee80211_alloc_node(ic, 0)) == NULL) return; - memcpy(bs->bs_macaddr, wh->i_addr2, IEEE80211_ADDR_LEN); - memcpy(bs->bs_bssid, ic->ic_bss.bs_bssid, - IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(ni->ni_macaddr, wh->i_addr2); + IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss.ni_bssid); allocbs = 1; } - IEEE80211_SEND_MGMT(ic, bs, IEEE80211_FC0_SUBTYPE_AUTH, 2); + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2); if (ifp->if_flags & IFF_DEBUG) printf("%s: station %s %s authenticated\n", ifp->if_xname, (allocbs ? "newly" : "already"), - ether_sprintf(bs->bs_macaddr)); - return; - } - if (ic->ic_state != IEEE80211_S_AUTH || seq != 2) - return; - if (status != 0) { - printf("%s: authentication failed (reason %d) for %s\n", - ic->ic_if.if_xname, status, ether_sprintf(wh->i_addr3)); - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(bs->bs_macaddr, wh->i_addr2, - IEEE80211_ADDR_LEN) == 0) { - bs->bs_fails++; - break; - } + ether_sprintf(ni->ni_macaddr)); + break; + + case IEEE80211_M_STA: + if (ic->ic_state != IEEE80211_S_AUTH || seq != 2) + return; + if (status != 0) { + printf("%s: authentication failed (reason %d) for %s\n", + ic->ic_if.if_xname, status, + ether_sprintf(wh->i_addr3)); + ni = ieee80211_find_node(ic, wh->i_addr2); + if (ni != NULL) + ni->ni_fails++; + return; } - return; + ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC, + wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); + break; } - ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC, - wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); } static void @@ -1741,12 +1812,12 @@ ieee80211_recv_asreq(struct ieee80211com *ic, struct mbuf *m0, int rssi, { struct ifnet *ifp = &ic->ic_if; struct ieee80211_frame *wh; - struct ieee80211_bss *bs = &ic->ic_bss; + struct ieee80211_node *ni = &ic->ic_bss; u_int8_t *frm, *efrm, *ssid, *rates; u_int16_t capinfo, bintval; int reassoc, resp, newassoc; - if ((ic->ic_flags & IEEE80211_F_HOSTAP) == 0 || + if (ic->ic_opmode != IEEE80211_M_HOSTAP || (ic->ic_state != IEEE80211_S_RUN)) return; @@ -1775,7 +1846,7 @@ ieee80211_recv_asreq(struct ieee80211com *ic, struct mbuf *m0, int rssi, return; } - if (memcmp(wh->i_addr3, ic->ic_bss.bs_bssid, IEEE80211_ADDR_LEN) != 0) { + if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss.ni_bssid)) { DPRINTF(("ieee80211_recv_asreq: ignore other bss from %s\n", ether_sprintf(wh->i_addr2))); return; @@ -1806,8 +1877,8 @@ ieee80211_recv_asreq(struct ieee80211com *ic, struct mbuf *m0, int rssi, ssid[1], ether_sprintf(wh->i_addr2))); return; } - if (ssid[1] != ic->ic_bss.bs_esslen || - memcmp(ssid + 2, ic->ic_bss.bs_essid, ssid[1]) != 0) { + if (ssid[1] != ic->ic_bss.ni_esslen || + memcmp(ssid + 2, ic->ic_bss.ni_essid, ssid[1]) != 0) { #ifdef IEEE80211_DEBUG if (ieee80211_debug) { printf("ieee80211_recv_asreq: ssid unmatch "); @@ -1817,48 +1888,44 @@ ieee80211_recv_asreq(struct ieee80211com *ic, struct mbuf *m0, int rssi, #endif return; } - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(bs->bs_macaddr, wh->i_addr2, - IEEE80211_ADDR_LEN) == 0) - break; - } - if (bs == NULL) + ni = ieee80211_find_node(ic, wh->i_addr2); + if (ni == NULL) return; if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 || (capinfo & IEEE80211_CAPINFO_PRIVACY) != ((ic->ic_flags & IEEE80211_F_WEPON) ? IEEE80211_CAPINFO_PRIVACY : 0)) { - bs->bs_associd = 0; - IEEE80211_SEND_MGMT(ic, bs, resp, IEEE80211_STATUS_CAPINFO); + ni->ni_associd = 0; + IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_CAPINFO); return; } - memset(bs->bs_rates, 0, IEEE80211_RATE_SIZE); - bs->bs_nrate = rates[1]; - memcpy(bs->bs_rates, rates + 2, bs->bs_nrate); - ieee80211_fix_rate(ic, bs, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | + memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE); + ni->ni_nrate = rates[1]; + memcpy(ni->ni_rates, rates + 2, ni->ni_nrate); + ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (bs->bs_nrate == 0) { - bs->bs_associd = 0; - IEEE80211_SEND_MGMT(ic, bs, resp, IEEE80211_STATUS_BASIC_RATE); + if (ni->ni_nrate == 0) { + ni->ni_associd = 0; + IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_BASIC_RATE); return; } - bs->bs_rssi = rssi; - bs->bs_rstamp = rstamp; - bs->bs_intval = bintval; - bs->bs_capinfo = capinfo; - bs->bs_chan = ic->ic_bss.bs_chan; - bs->bs_fhdwell = ic->ic_bss.bs_fhdwell; - bs->bs_fhindex = ic->ic_bss.bs_fhindex; - if (bs->bs_associd == 0) { - bs->bs_associd = 0xc000 | ic->ic_bss.bs_associd++; + ni->ni_rssi = rssi; + ni->ni_rstamp = rstamp; + ni->ni_intval = bintval; + ni->ni_capinfo = capinfo; + ni->ni_chan = ic->ic_bss.ni_chan; + ni->ni_fhdwell = ic->ic_bss.ni_fhdwell; + ni->ni_fhindex = ic->ic_bss.ni_fhindex; + if (ni->ni_associd == 0) { + ni->ni_associd = 0xc000 | ic->ic_bss.ni_associd++; newassoc = 1; } else newassoc = 0; - IEEE80211_SEND_MGMT(ic, bs, resp, IEEE80211_STATUS_SUCCESS); + IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS); if (ifp->if_flags & IFF_DEBUG) printf("%s: station %s %s associated\n", ifp->if_xname, (newassoc ? "newly" : "already"), - ether_sprintf(bs->bs_macaddr)); + ether_sprintf(ni->ni_macaddr)); } static void @@ -1867,12 +1934,11 @@ ieee80211_recv_asresp(struct ieee80211com *ic, struct mbuf *m0, int rssi, { struct ifnet *ifp = &ic->ic_if; struct ieee80211_frame *wh; - struct ieee80211_bss *bs = &ic->ic_bss; + struct ieee80211_node *ni = &ic->ic_bss; u_int8_t *frm, *efrm, *rates; int status; - if ((ic->ic_flags & IEEE80211_F_HOSTAP) || - (ic->ic_flags & IEEE80211_F_ADHOC) || + if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_ASSOC) return; @@ -1892,7 +1958,7 @@ ieee80211_recv_asresp(struct ieee80211com *ic, struct mbuf *m0, int rssi, return; } - bs->bs_capinfo = le16toh(*(u_int16_t *)frm); + ni->ni_capinfo = le16toh(*(u_int16_t *)frm); frm += 2; status = le16toh(*(u_int16_t *)frm); @@ -1900,25 +1966,21 @@ ieee80211_recv_asresp(struct ieee80211com *ic, struct mbuf *m0, int rssi, if (status != 0) { printf("%s: association failed (reason %d) for %s\n", ifp->if_xname, status, ether_sprintf(wh->i_addr3)); - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(bs->bs_macaddr, wh->i_addr2, - IEEE80211_ADDR_LEN) == 0) { - bs->bs_fails++; - break; - } - } + ni = ieee80211_find_node(ic, wh->i_addr2); + if (ni != NULL) + ni->ni_fails++; return; } - bs->bs_associd = le16toh(*(u_int16_t *)frm); + ni->ni_associd = le16toh(*(u_int16_t *)frm); frm += 2; rates = frm; - memset(bs->bs_rates, 0, IEEE80211_RATE_SIZE); - bs->bs_nrate = rates[1]; - memcpy(bs->bs_rates, rates + 2, bs->bs_nrate); - ieee80211_fix_rate(ic, bs, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | + memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE); + ni->ni_nrate = rates[1]; + memcpy(ni->ni_rates, rates + 2, ni->ni_nrate); + ieee80211_fix_rate(ic, ni, IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (bs->bs_nrate == 0) + if (ni->ni_nrate == 0) return; ieee80211_new_state(ifp, IEEE80211_S_RUN, wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); @@ -1930,7 +1992,7 @@ ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0, int rssi, { struct ifnet *ifp = &ic->ic_if; struct ieee80211_frame *wh; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; u_int8_t *frm, *efrm; u_int16_t reason; @@ -1947,23 +2009,23 @@ ieee80211_recv_disassoc(struct ieee80211com *ic, struct mbuf *m0, int rssi, return; } reason = le16toh(*(u_int16_t *)frm); - if (ic->ic_flags & IEEE80211_F_HOSTAP) { - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(wh->i_addr2, bs->bs_macaddr, - IEEE80211_ADDR_LEN) == 0) { - if (ifp->if_flags & IFF_DEBUG) - printf("%s: station %s disassociated" - " by peer (reason %d)\n", - ifp->if_xname, - ether_sprintf(bs->bs_macaddr), - reason); - bs->bs_associd = 0; - break; - } - } - } else if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0) + switch (ic->ic_opmode) { + case IEEE80211_M_STA: ieee80211_new_state(&ic->ic_if, IEEE80211_S_ASSOC, wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); + break; + case IEEE80211_M_HOSTAP: + if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) { + if (ifp->if_flags & IFF_DEBUG) + printf("%s: station %s disassociated" + " by peer (reason %d)\n", ifp->if_xname, + ether_sprintf(ni->ni_macaddr), reason); + ni->ni_associd = 0; + } + break; + default: + break; + } } static void @@ -1972,7 +2034,7 @@ ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0, int rssi, { struct ifnet *ifp = &ic->ic_if; struct ieee80211_frame *wh; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; u_int8_t *frm, *efrm; u_int16_t reason; @@ -1989,33 +2051,30 @@ ieee80211_recv_deauth(struct ieee80211com *ic, struct mbuf *m0, int rssi, return; } reason = le16toh(*(u_int16_t *)frm); - if (ic->ic_flags & IEEE80211_F_HOSTAP) { - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(wh->i_addr2, bs->bs_macaddr, - IEEE80211_ADDR_LEN) == 0) { - if (ifp->if_flags & IFF_DEBUG) - printf("%s: station %s deauthenticated" - " by peer (reason %d)\n", - ifp->if_xname, - ether_sprintf(bs->bs_macaddr), - reason); - TAILQ_REMOVE(&ic->ic_scan, bs, bs_list); - free(bs, M_DEVBUF); - if (TAILQ_EMPTY(&ic->ic_scan)) - ic->ic_inact_timer = 0; - break; - } - } - } else if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0) + switch (ic->ic_opmode) { + case IEEE80211_M_STA: ieee80211_new_state(&ic->ic_if, IEEE80211_S_AUTH, wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); + break; + case IEEE80211_M_HOSTAP: + if ((ni = ieee80211_find_node(ic, wh->i_addr2)) != NULL) { + if (ifp->if_flags & IFF_DEBUG) + printf("%s: station %s deauthenticated" + " by peer (reason %d)\n", ifp->if_xname, + ether_sprintf(ni->ni_macaddr), reason); + ieee80211_free_node(ic, ni); + } + break; + default: + break; + } } int ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) { struct ieee80211com *ic = (void *)ifp; - struct ieee80211_bss *bs = &ic->ic_bss; + struct ieee80211_node *ni = &ic->ic_bss; int i, error, ostate; #ifdef IEEE80211_DEBUG static const char *stname[] = @@ -2041,30 +2100,42 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) case IEEE80211_S_INIT: break; case IEEE80211_S_RUN: - if (ic->ic_flags & IEEE80211_F_HOSTAP) { - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (bs->bs_associd == 0) + switch (ic->ic_opmode) { + case IEEE80211_M_STA: + IEEE80211_SEND_MGMT(ic, ni, + IEEE80211_FC0_SUBTYPE_DISASSOC, + IEEE80211_REASON_ASSOC_LEAVE); + break; + case IEEE80211_M_HOSTAP: + TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { + if (ni->ni_associd == 0) continue; - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC, IEEE80211_REASON_ASSOC_LEAVE); } - } else if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0) - IEEE80211_SEND_MGMT(ic, bs, - IEEE80211_FC0_SUBTYPE_DISASSOC, - IEEE80211_REASON_ASSOC_LEAVE); + break; + default: + break; + } /* FALLTHRU */ case IEEE80211_S_ASSOC: - if (ic->ic_flags & IEEE80211_F_HOSTAP) { - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - IEEE80211_SEND_MGMT(ic, bs, + switch (ic->ic_opmode) { + case IEEE80211_M_STA: + IEEE80211_SEND_MGMT(ic, ni, + IEEE80211_FC0_SUBTYPE_DEAUTH, + IEEE80211_REASON_AUTH_LEAVE); + break; + case IEEE80211_M_HOSTAP: + TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH, IEEE80211_REASON_AUTH_LEAVE); } - } else if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0) - IEEE80211_SEND_MGMT(ic, bs, - IEEE80211_FC0_SUBTYPE_DEAUTH, - IEEE80211_REASON_AUTH_LEAVE); + break; + default: + break; + } /* FALLTHRU */ case IEEE80211_S_AUTH: case IEEE80211_S_SCAN: @@ -2075,33 +2146,33 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) free(ic->ic_wep_ctx, M_DEVBUF); ic->ic_wep_ctx = NULL; } - ieee80211_free_scan(ifp); + while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL) + ieee80211_free_node(ic, ni); break; } break; case IEEE80211_S_SCAN: ic->ic_flags &= ~IEEE80211_F_SIBSS; - bs = &ic->ic_bss; + ni = &ic->ic_bss; /* initialize bss for probe request */ - memcpy(bs->bs_macaddr, ifp->if_broadcastaddr, - IEEE80211_ADDR_LEN); - memcpy(bs->bs_bssid, ifp->if_broadcastaddr, IEEE80211_ADDR_LEN); - bs->bs_nrate = 0; - memset(bs->bs_rates, 0, IEEE80211_RATE_SIZE); + IEEE80211_ADDR_COPY(ni->ni_macaddr, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(ni->ni_bssid, ifp->if_broadcastaddr); + ni->ni_nrate = 0; + memset(ni->ni_rates, 0, IEEE80211_RATE_SIZE); for (i = 0; i < IEEE80211_RATE_SIZE; i++) { if (ic->ic_sup_rates[i] != 0) - bs->bs_rates[bs->bs_nrate++] = + ni->ni_rates[ni->ni_nrate++] = ic->ic_sup_rates[i]; } - bs->bs_associd = 0; - bs->bs_rstamp = 0; + ni->ni_associd = 0; + ni->ni_rstamp = 0; switch (ostate) { case IEEE80211_S_INIT: ic->ic_flags |= IEEE80211_F_ASCAN; ic->ic_scan_timer = IEEE80211_ASCAN_WAIT; /* use lowest rate */ - bs->bs_txrate = 0; - IEEE80211_SEND_MGMT(ic, bs, + ni->ni_txrate = 0; + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0); break; case IEEE80211_S_SCAN: @@ -2110,7 +2181,7 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) if (ic->ic_scan_timer == 0) ic->ic_scan_timer = IEEE80211_ASCAN_WAIT; - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0); } else { if (ic->ic_scan_timer == 0) @@ -2125,19 +2196,16 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) printf("%s: no recent beacons from %s;" " rescanning\n", ifp->if_xname, - ether_sprintf(ic->ic_bss.bs_bssid)); - ieee80211_free_scan(ifp); + ether_sprintf(ic->ic_bss.ni_bssid)); + while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL) + ieee80211_free_node(ic, ni); /* FALLTHRU */ case IEEE80211_S_AUTH: case IEEE80211_S_ASSOC: /* timeout restart scan */ - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { - if (memcmp(ic->ic_bss.bs_macaddr, - bs->bs_macaddr, IEEE80211_ADDR_LEN) == 0) { - bs->bs_fails++; - break; - } - } + ni = ieee80211_find_node(ic, ic->ic_bss.ni_macaddr); + if (ni != NULL) + ni->ni_fails++; ic->ic_flags |= IEEE80211_F_ASCAN; ic->ic_scan_timer = IEEE80211_ASCAN_WAIT; IEEE80211_SEND_MGMT(ic, &ic->ic_bss, @@ -2151,7 +2219,7 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) DPRINTF(("ieee80211_new_state: invalid transition\n")); break; case IEEE80211_S_SCAN: - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 1); break; case IEEE80211_S_AUTH: @@ -2159,7 +2227,7 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) switch (mgt) { case IEEE80211_FC0_SUBTYPE_AUTH: /* ??? */ - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2); break; case IEEE80211_FC0_SUBTYPE_DEAUTH: @@ -2170,13 +2238,13 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) case IEEE80211_S_RUN: switch (mgt) { case IEEE80211_FC0_SUBTYPE_AUTH: - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 2); ic->ic_state = ostate; /* stay RUN */ break; case IEEE80211_FC0_SUBTYPE_DEAUTH: /* try to reauth */ - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_AUTH, 1); break; } @@ -2191,11 +2259,11 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) DPRINTF(("ieee80211_new_state: invalid transition\n")); break; case IEEE80211_S_AUTH: - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); break; case IEEE80211_S_RUN: - IEEE80211_SEND_MGMT(ic, bs, + IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); break; } @@ -2211,19 +2279,18 @@ ieee80211_new_state(struct ifnet *ifp, enum ieee80211_state nstate, int mgt) case IEEE80211_S_ASSOC: /* infra mode */ if (ifp->if_flags & IFF_DEBUG) { printf("%s: ", ifp->if_xname); - if ((ic->ic_flags & IEEE80211_F_ADHOC) || - (ic->ic_flags & IEEE80211_F_HOSTAP)) - printf("synchronized "); - else + if (ic->ic_opmode == IEEE80211_M_STA) printf("associated "); + else + printf("synchronized "); printf("with %s ssid ", - ether_sprintf(ic->ic_bss.bs_bssid)); - ieee80211_print_essid(ic->ic_bss.bs_essid, - ic->ic_bss.bs_esslen); - printf(" channel %d\n", ic->ic_bss.bs_chan); + ether_sprintf(ic->ic_bss.ni_bssid)); + ieee80211_print_essid(ic->ic_bss.ni_essid, + ic->ic_bss.ni_esslen); + printf(" channel %d\n", ic->ic_bss.ni_chan); } /* start with highest negotiated rate */ - ic->ic_bss.bs_txrate = ic->ic_bss.bs_nrate - 1; + ic->ic_bss.ni_txrate = ic->ic_bss.ni_nrate - 1; ic->ic_mgt_timer = 0; (*ifp->if_start)(ifp); break; @@ -2443,29 +2510,37 @@ ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len) /* * convert IEEE80211 rate value to ifmedia subtype. * ieee80211 rate is in unit of 0.5Mbps. - * phytype is IEEE80211_F_FH or IEEE80211_F_DS. */ int -ieee80211_rate2media(int rate, int phytype) +ieee80211_rate2media(int rate, enum ieee80211_phytype phytype) { int mword; mword = 0; switch (phytype) { - case IEEE80211_F_FH: + case IEEE80211_T_FH: switch (rate & IEEE80211_RATE_VAL) { + case 0: + mword = IFM_AUTO; + break; case 2: mword = IFM_IEEE80211_FH1; break; case 4: mword = IFM_IEEE80211_FH2; break; + default: + mword = IFM_NONE; + break; } break; - case IEEE80211_F_DS: + case IEEE80211_T_DS: switch (rate & IEEE80211_RATE_VAL) { + case 0: + mword = IFM_AUTO; + break; case 2: mword = IFM_IEEE80211_DS1; break; @@ -2478,19 +2553,27 @@ ieee80211_rate2media(int rate, int phytype) case 22: mword = IFM_IEEE80211_DS11; break; + default: + mword = IFM_NONE; + break; } + break; + + default: + mword = IFM_MANUAL; + break; } return mword; } int -ieee80211_media2rate(int mword, int phytype) +ieee80211_media2rate(int mword, enum ieee80211_phytype phytype) { int rate; rate = 0; switch (phytype) { - case IEEE80211_F_FH: + case IEEE80211_T_FH: switch (IFM_SUBTYPE(mword)) { case IFM_IEEE80211_FH1: rate = 2; @@ -2501,7 +2584,7 @@ ieee80211_media2rate(int mword, int phytype) } break; - case IEEE80211_F_DS: + case IEEE80211_T_DS: switch (IFM_SUBTYPE(mword)) { case IFM_IEEE80211_DS1: rate = 2; @@ -2516,6 +2599,10 @@ ieee80211_media2rate(int mword, int phytype) rate = 22; break; } + break; + + default: + break; } return rate; } @@ -2535,7 +2622,7 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) struct wi_req wreq; struct wi_ltv_keys *keys; struct wi_apinfo *ap; - struct ieee80211_bss *bs; + struct ieee80211_node *ni; #ifdef WICACHE struct wi_sigcache wsc; #endif /* WICACHE */ @@ -2559,10 +2646,10 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) wreq.wi_len = 1; break; } - wreq.wi_val[0] = htole16(ic->ic_bss.bs_esslen); - memcpy(&wreq.wi_val[1], ic->ic_bss.bs_essid, - ic->ic_bss.bs_esslen); - wreq.wi_len = (1 + ic->ic_bss.bs_esslen + 1) / 2; + wreq.wi_val[0] = htole16(ic->ic_bss.ni_esslen); + memcpy(&wreq.wi_val[1], ic->ic_bss.ni_essid, + ic->ic_bss.ni_esslen); + wreq.wi_len = (1 + ic->ic_bss.ni_esslen + 1) / 2; break; case WI_RID_OWN_SSID: case WI_RID_DESIRED_SSID: @@ -2572,8 +2659,7 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) break; case WI_RID_CURRENT_BSSID: if (ic->ic_state == IEEE80211_S_RUN) - memcpy(wreq.wi_val, ic->ic_bss.bs_bssid, - IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss.ni_bssid); else memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN); wreq.wi_len = IEEE80211_ADDR_LEN / 2; @@ -2584,7 +2670,7 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) * Since channel 0 is not available for DS, channel 1 * is assigned to LSB on WaveLAN. */ - if (ic->ic_flags & IEEE80211_F_DS) + if (ic->ic_phytype == IEEE80211_T_DS) i = 1; else i = 0; @@ -2600,12 +2686,12 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) wreq.wi_len = 1; break; case WI_RID_CURRENT_CHAN: - wreq.wi_val[0] = htole16(ic->ic_bss.bs_chan); + wreq.wi_val[0] = htole16(ic->ic_bss.ni_chan); wreq.wi_len = 1; break; case WI_RID_COMMS_QUALITY: wreq.wi_val[0] = 0; /* quality */ - wreq.wi_val[1] = htole16(ic->ic_bss.bs_rssi); /* signal */ + wreq.wi_val[1] = htole16(ic->ic_bss.ni_rssi); /* signal */ wreq.wi_val[2] = 0; /* noise */ wreq.wi_len = 3; break; @@ -2614,12 +2700,11 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) wreq.wi_len = 1; break; case WI_RID_PORTTYPE: - wreq.wi_val[0] = - htole16((ic->ic_flags & IEEE80211_F_ADHOC) ? 4 : 1); + wreq.wi_val[0] = htole16(ic->ic_opmode); wreq.wi_len = 1; break; case WI_RID_MAC_NODE: - memcpy(wreq.wi_val, ic->ic_myaddr, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr); wreq.wi_len = IEEE80211_ADDR_LEN / 2; break; case WI_RID_TX_RATE: @@ -2633,7 +2718,7 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) break; case WI_RID_CUR_TX_RATE: wreq.wi_val[0] = htole16( - (ic->ic_bss.bs_rates[ic->ic_bss.bs_txrate] & + (ic->ic_bss.ni_rates[ic->ic_bss.ni_txrate] & IEEE80211_RATE_VAL) / 2); wreq.wi_len = 1; break; @@ -2667,8 +2752,8 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) wreq.wi_val[0] = htole16(ic->ic_lintval); wreq.wi_len = 1; break; - case WI_RID_OWN_BEACON_INT: - wreq.wi_val[0] = htole16(ic->ic_bss.bs_intval); + case WI_RID_CUR_BEACON_INT: + wreq.wi_val[0] = htole16(ic->ic_bss.ni_intval); wreq.wi_len = 1; break; case WI_RID_WEP_AVAIL: @@ -2714,31 +2799,37 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) /* XXX: should be implemented in lower drivers */ break; case WI_RID_READ_APS: - for (i = 0; i < IEEE80211_PSCAN_WAIT; i++) { - tsleep((caddr_t)ic, PWAIT | PCATCH, "i80211", hz); - if (ic->ic_state != IEEE80211_S_SCAN || - (ic->ic_flags & IEEE80211_F_SCANAP) == 0 || - (ic->ic_flags & IEEE80211_F_ASCAN) == 0) - break; + if (ic->ic_opmode != IEEE80211_M_HOSTAP) { + for (i = 0; i < IEEE80211_PSCAN_WAIT; i++) { + tsleep((caddr_t)ic, PWAIT | PCATCH, "i80211", + hz); + if (ic->ic_state != IEEE80211_S_SCAN || + (ic->ic_flags & IEEE80211_F_SCANAP) == 0 || + (ic->ic_flags & IEEE80211_F_ASCAN) == 0) + break; + } + ic->ic_flags &= ~IEEE80211_F_SCANAP; } - ic->ic_flags &= ~IEEE80211_F_SCANAP; i = 0; ap = (void *)((char *)wreq.wi_val + sizeof(i)); - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { + TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1)) break; memset(ap, 0, sizeof(*ap)); - memcpy(ap->bssid, bs->bs_bssid, IEEE80211_ADDR_LEN); - ap->channel = bs->bs_chan; - ap->signal = bs->bs_rssi; - ap->namelen = bs->bs_esslen; - if (bs->bs_esslen) - memcpy(ap->name, bs->bs_essid, bs->bs_esslen); - ap->capinfo = bs->bs_capinfo; - ap->interval = bs->bs_intval; - for (j = 0; j < bs->bs_nrate; j++) { - if (bs->bs_rates[j] & IEEE80211_RATE_BASIC) { - ap->rate = (bs->bs_rates[j] & + if (ic->ic_opmode == IEEE80211_M_HOSTAP) + IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr); + else + IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid); + ap->channel = ni->ni_chan; + ap->signal = ni->ni_rssi; + ap->namelen = ni->ni_esslen; + if (ni->ni_esslen) + memcpy(ap->name, ni->ni_essid, ni->ni_esslen); + ap->capinfo = ni->ni_capinfo; + ap->interval = ni->ni_intval; + for (j = 0; j < ni->ni_nrate; j++) { + if (ni->ni_rates[j] & IEEE80211_RATE_BASIC) { + ap->rate = (ni->ni_rates[j] & IEEE80211_RATE_VAL) * 5; /* XXX */ } } @@ -2751,12 +2842,12 @@ ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data) #ifdef WICACHE case WI_RID_READ_CACHE: i = 0; - TAILQ_FOREACH(bs, &ic->ic_scan, bs_list) { + TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { if (i == MAXCACHE) break; - memcpy(wsc.macsrc, bs->bs_macaddr, IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr); memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc)); - wsc.signal = bs->rssi; + wsc.signal = ni->rssi; wsc.noise = 0; wsc.quality = 0; memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i, @@ -2819,7 +2910,9 @@ ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) if (wreq.wi_len != 1) return EINVAL; i = le16toh(wreq.wi_val[0]); - if (isclr(ic->ic_chan_active, i)) + if (i < 0 || + i > IEEE80211_CHAN_MAX || + isclr(ic->ic_chan_active, i)) return EINVAL; ic->ic_ibss_chan = i; if (ic->ic_flags & IEEE80211_F_SIBSS) @@ -2847,21 +2940,9 @@ ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) case WI_RID_PORTTYPE: if (wreq.wi_len != 1) return EINVAL; - switch (le16toh(wreq.wi_val[0])) { - case 1: - if (ic->ic_flags & IEEE80211_F_ADHOC) { - ic->ic_flags &= ~IEEE80211_F_ADHOC; - error = ENETRESET; - } - break; - case 2: - if ((ic->ic_flags & IEEE80211_F_ADHOC) == 0) { - ic->ic_flags |= IEEE80211_F_ADHOC; - error = ENETRESET; - } - break; - default: - return EINVAL; + if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) { + ic->ic_opmode = le16toh(wreq.wi_val[0]); + error = ENETRESET; } break; case WI_RID_MAC_NODE: @@ -2902,7 +2983,7 @@ ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) return EINVAL; if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { ic->ic_flags |= IEEE80211_F_IBSSON; - if ((ic->ic_flags & IEEE80211_F_ADHOC) && + if (ic->ic_opmode == IEEE80211_M_ADHOC && ic->ic_state == IEEE80211_S_SCAN) error = ENETRESET; } @@ -2958,7 +3039,7 @@ ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) if (ic->ic_flags & IEEE80211_F_PMGTON) error = ENETRESET; break; - case WI_RID_OWN_BEACON_INT: + case WI_RID_CUR_BEACON_INT: return EPERM; case WI_RID_WEP_AVAIL: return EPERM; @@ -3034,7 +3115,7 @@ ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) * Since channel 0 is not available for DS, channel 1 * is assigned to LSB on WaveLAN. */ - if (ic->ic_flags & IEEE80211_F_DS) + if (ic->ic_phytype == IEEE80211_T_DS) i = 1; else i = 0; @@ -3064,8 +3145,8 @@ ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) break; } } - if (isclr(chanlist, ic->ic_bss.bs_chan)) - ic->ic_bss.bs_chan = ic->ic_ibss_chan; + if (isclr(chanlist, ic->ic_bss.ni_chan)) + ic->ic_bss.ni_chan = ic->ic_ibss_chan; if (wreq.wi_type == WI_RID_CHANNEL_LIST) error = ENETRESET; else {