📄 ieee80211.c
字号:
*/ vap = TAILQ_FIRST(&ic->ic_vaps); while ((vap->iv_state != IEEE80211_S_SCAN) && (vap != NULL) && (vap->iv_ic != ic)) { vap = TAILQ_NEXT(vap, iv_next); } /* * No running/scanning VAP was found, so they're all in * INIT state, no channel change needed */ if (!vap) return; /* is it really Scanning */ /* XXX race condition ?? */ if (ic->ic_flags & IEEE80211_F_SCAN) return; /* it is not scanning , but waiting for ath driver to move the vap to RUN */ } /* * Check the scan results using only cached results */ if (!(ieee80211_check_scan(vap, IEEE80211_SCAN_USECACHE | IEEE80211_SCAN_NOSSID | IEEE80211_SCAN_KEEPMODE, 0, vap->iv_des_nssid, vap->iv_des_ssid, ieee80211_scan_dfs_action))) { /* No channel was found, so call the scan action with no result */ ieee80211_scan_dfs_action(vap, NULL); } } } else { /* Change to a radar free 11a channel for dfstesttime seconds */ ic->ic_chanchange_chan = IEEE80211_RADAR_TEST_MUTE_CHAN; ic->ic_chanchange_tbtt = IEEE80211_RADAR_11HCOUNT; ic->ic_flags |= IEEE80211_F_CHANSWITCH; /* A timer is setup in the radar task if markdfs is not set and * we are in hostap mode. */ } } else { /* Are we in sta mode? If so, send an action msg to ap saying we found a radar? */ }}EXPORT_SYMBOL(ieee80211_mark_dfs);voidieee80211_dfs_test_return(struct ieee80211com *ic, u_int8_t ieeeChan){ struct net_device *dev = ic->ic_dev; /* Return to the original channel we were on before the test mute */ if_printf(dev, "Returning to channel %d\n", ieeeChan); printk("Returning to chan %d\n", ieeeChan); ic->ic_chanchange_chan = ieeeChan; ic->ic_chanchange_tbtt = IEEE80211_RADAR_11HCOUNT; ic->ic_flags |= IEEE80211_F_CHANSWITCH;}EXPORT_SYMBOL(ieee80211_dfs_test_return);voidieee80211_announce(struct ieee80211com *ic){ struct net_device *dev = ic->ic_dev; int i, mode, rate, mword; struct ieee80211_rateset *rs; for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) { if ((ic->ic_modecaps & (1<<mode)) == 0) continue; if_printf(dev, "%s rates: ", ieee80211_phymode_name[mode]); rs = &ic->ic_sup_rates[mode]; for (i = 0; i < rs->rs_nrates; i++) { rate = rs->rs_rates[i]; mword = ieee80211_rate2media(ic, rate, mode); if (mword == 0) continue; printf("%s%d%sMbps", (i != 0 ? " " : ""), (rate & IEEE80211_RATE_VAL) / 2, ((rate & 0x1) != 0 ? ".5" : "")); } printf("\n"); } if_printf(dev, "H/W encryption support:"); if (ic->ic_caps & IEEE80211_C_WEP) printk(" WEP"); if (ic->ic_caps & IEEE80211_C_AES) printk(" AES"); if (ic->ic_caps & IEEE80211_C_AES_CCM) printk(" AES_CCM"); if (ic->ic_caps & IEEE80211_C_CKIP) printk(" CKIP"); if (ic->ic_caps & IEEE80211_C_TKIP) printk(" TKIP"); printk("\n");}EXPORT_SYMBOL(ieee80211_announce);voidieee80211_announce_channels(struct ieee80211com *ic){ const struct ieee80211_channel *c; char type; int i; printf("Chan Freq RegPwr MinPwr MaxPwr\n"); for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; if (IEEE80211_IS_CHAN_ST(c)) type = 'S'; else if (IEEE80211_IS_CHAN_108A(c)) type = 'T'; else if (IEEE80211_IS_CHAN_108G(c)) type = 'G'; else if (IEEE80211_IS_CHAN_A(c)) type = 'a'; else if (IEEE80211_IS_CHAN_ANYG(c)) type = 'g'; else if (IEEE80211_IS_CHAN_B(c)) type = 'b'; else type = 'f'; printf("%4d %4d%c %6d %6d %6d\n" , c->ic_ieee, c->ic_freq, type , c->ic_maxregpower , c->ic_minpower, c->ic_maxpower ); }}EXPORT_SYMBOL(ieee80211_announce_channels);/* * Common code to calculate the media status word * from the operating mode and channel state. */static intmedia_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan){ int status; status = IFM_IEEE80211; switch (opmode) { case IEEE80211_M_STA: break; case IEEE80211_M_AHDEMO: status |= IFM_IEEE80211_ADHOC | IFM_FLAG0; break; case IEEE80211_M_IBSS: status |= IFM_IEEE80211_ADHOC; break; case IEEE80211_M_HOSTAP: status |= IFM_IEEE80211_HOSTAP; break; case IEEE80211_M_MONITOR: status |= IFM_IEEE80211_MONITOR; break; case IEEE80211_M_WDS: status |= IFM_IEEE80211_WDS; break; } if (IEEE80211_IS_CHAN_A(chan)) { status |= IFM_IEEE80211_11A; if (IEEE80211_IS_CHAN_TURBO(chan)) status |= IFM_IEEE80211_TURBO; } else if (IEEE80211_IS_CHAN_B(chan)) { status |= IFM_IEEE80211_11B; } else if (IEEE80211_IS_CHAN_ANYG(chan)) { status |= IFM_IEEE80211_11G; if (IEEE80211_IS_CHAN_TURBO(chan)) status |= IFM_IEEE80211_TURBO; } else if (IEEE80211_IS_CHAN_FHSS(chan)) { status |= IFM_IEEE80211_FH; } /* XXX else complain? */ return status;}/* * Handle a media requests on the base interface. */static voidieee80211com_media_status(struct net_device *dev, struct ifmediareq *imr){ struct ieee80211com *ic = dev->priv; /*XXX*/ imr->ifm_status = IFM_AVALID; if (!TAILQ_EMPTY(&ic->ic_vaps)) imr->ifm_status |= IFM_ACTIVE; imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);}/* * Convert a media specification to an 802.11 phy mode. */static intmedia2mode(const struct ifmedia_entry *ime, enum ieee80211_phymode *mode){ switch (IFM_MODE(ime->ifm_media)) { case IFM_IEEE80211_11A: *mode = IEEE80211_MODE_11A; break; case IFM_IEEE80211_11B: *mode = IEEE80211_MODE_11B; break; case IFM_IEEE80211_11G: *mode = IEEE80211_MODE_11G; break; case IFM_IEEE80211_FH: *mode = IEEE80211_MODE_FH; break; case IFM_AUTO: *mode = IEEE80211_MODE_AUTO; break; default: return 0; } /* * Turbo mode is an ``option''. * XXX: Turbo currently does not apply to AUTO */ if (ime->ifm_media & IFM_IEEE80211_TURBO) { if (*mode == IEEE80211_MODE_11A) *mode = IEEE80211_MODE_TURBO_A; else if (*mode == IEEE80211_MODE_11G) *mode = IEEE80211_MODE_TURBO_G; else return 0; } return 1;}static intieee80211com_media_change(struct net_device *dev){ struct ieee80211com *ic = dev->priv; /*XXX*/ struct ieee80211vap *vap; struct ifmedia_entry *ime = ic->ic_media.ifm_cur; enum ieee80211_phymode newphymode; int j, error = 0; /* XXX is rtnl held here? */ /* * First, identify the phy mode. */ if (!media2mode(ime, &newphymode)) return -EINVAL; /* NB: mode must be supported, no need to check */ /* * Autoselect doesn't make sense when operating as an AP. * If no phy mode has been selected, pick one and lock it * down so rate tables can be used in forming beacon frames * and the like. */ if (ic->ic_opmode == IEEE80211_M_HOSTAP && newphymode == IEEE80211_MODE_AUTO) { for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) if (ic->ic_modecaps & (1 << j)) { newphymode = j; break; } } /* * Handle phy mode change. */ IEEE80211_LOCK_IRQ(ic); if (ic->ic_curmode != newphymode) { /* change phy mode */ error = ieee80211_setmode(ic, newphymode); if (error != 0) { IEEE80211_UNLOCK_IRQ_EARLY(ic); return error; } TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { /* reset WME state */ ieee80211_wme_initparams_locked(vap); /* * Setup an initial rate set according to the * current/default channel selected above. This * will be changed when scanning but must exist * now so drivers have a consistent state. */ KASSERT(vap->iv_bss != NULL, ("no bss node")); vap->iv_bss->ni_rates = ic->ic_sup_rates[newphymode]; } error = ENETRESET; } IEEE80211_UNLOCK_IRQ(ic);#ifdef notdef if (error == 0) ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media);#endif return error;}static intfindrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate){#define IEEERATE(_ic,_m,_i) \ ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) int i, nrates = ic->ic_sup_rates[mode].rs_nrates; for (i = 0; i < nrates; i++) if (IEEERATE(ic, mode, i) == rate) return i; return -1;#undef IEEERATE}/* * Convert a media specification to a rate index and possibly a mode * (if the rate is fixed and the mode is specified as ``auto'' then * we need to lock down the mode so the index is meanginful). */static intcheckrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate){ /* * Check the rate table for the specified/current phy. */ if (mode == IEEE80211_MODE_AUTO) { int i; /* * In autoselect mode search for the rate. */ for (i = IEEE80211_MODE_11A; i < IEEE80211_MODE_MAX; i++) { if ((ic->ic_modecaps & (1 << i)) && findrate(ic, i, rate) != -1) return 1; } return 0; } else { /* * Mode is fixed, check for rate. */ return (findrate(ic, mode, rate) != -1); }}/* * Handle a media change request; the only per-vap * information that is meaningful is the fixed rate * and desired phy mode. */intieee80211_media_change(struct net_device *dev){ struct ieee80211vap *vap = dev->priv; struct ieee80211com *ic = vap->iv_ic; struct ifmedia_entry *ime = vap->iv_media.ifm_cur; enum ieee80211_phymode newmode; int newrate, error; /* * First, identify the desired phy mode. */ if (!media2mode(ime, &newmode)) return -EINVAL; /* * Check for fixed/variable rate. */ if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) { /* * Convert media subtype to rate and potentially * lock down the mode. */ newrate = ieee80211_media2rate(ime->ifm_media); if (newrate == 0 || !checkrate(ic, newmode, newrate)) return -EINVAL; } else newrate = IEEE80211_FIXED_RATE_NONE; /* * Install the rate+mode settings. */ error = 0; if (vap->iv_fixed_rate != newrate) { vap->iv_fixed_rate = newrate; /* fixed tx rate */ error = ENETRESET; } if (vap->iv_des_mode != newmode) { vap->iv_des_mode = newmode; /* desired phymode */ error = ENETRESET; } return error;}EXPORT_SYMBOL(ieee80211_media_change);voidieee80211_media_status(struct net_device *dev, struct ifmediareq *imr){ struct ieee80211vap *vap = dev->priv; struct ieee80211com *ic = vap->iv_ic; enum ieee80211_phymode mode; struct ieee80211_rateset *rs; imr->ifm_status = IFM_AVALID; /* * NB: use the current channel's mode to lock down a xmit * rate only when running; otherwise we may have a mismatch * in which case the rate will not be convertible. */ if (vap->iv_state == IEEE80211_S_RUN) { imr->ifm_status |= IFM_ACTIVE; mode = ieee80211_chan2mode(ic->ic_curchan); } else mode = IEEE80211_MODE_AUTO; imr->ifm_active = media_status(vap->iv_opmode, ic->ic_curchan); /* * Calculate a current rate if possible. */ if (vap->iv_fixed_rate != IEEE80211_FIXED_RATE_NONE) { /* * A fixed rate is set, report that. */ imr->ifm_active |= ieee80211_rate2media(ic,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -