📄 ieee80211.c
字号:
vap->iv_dev = dev; /* back pointer */#ifdef ATH_SUPERG_XR /* * setup XR vap specific flags. * link the XR vap to its normal val. */ if (flags & IEEE80211_VAP_XR) { struct ieee80211vap *vapparent = NULL; vap->iv_unit = -1; vap->iv_flags = ic->ic_flags | IEEE80211_F_XR; /* propagate common flags and add XR flag */ vap->iv_flags_ext = ic->ic_flags_ext; TAILQ_FOREACH(vapparent, &ic->ic_vaps, iv_next) if (vapparent->iv_unit == unit) break; vap->iv_xrvap = vapparent; vap->iv_ath_cap = vapparent->iv_ath_cap; /* Default multicast rate to lowest possible 256 Kbps */ vap->iv_mcast_rate = 256; } else { vap->iv_unit = unit; vap->iv_flags = ic->ic_flags; /* propagate common flags */ vap->iv_flags_ext = ic->ic_flags_ext; vap->iv_xrvap = NULL; vap->iv_ath_cap = ic->ic_ath_cap; /* Default Multicast traffic to lowest rate of 1 Mbps*/ vap->iv_mcast_rate = 1000; }#else vap->iv_unit = unit; vap->iv_flags = ic->ic_flags; /* propagate common flags */ vap->iv_flags_ext = ic->ic_flags_ext; vap->iv_xrvap = NULL; vap->iv_ath_cap = ic->ic_ath_cap; /* Default Multicast traffic to lowest rate of 1000 Kbps*/ vap->iv_mcast_rate = 1000;#endif vap->iv_caps = ic->ic_caps &~ IEEE80211_C_OPMODE; switch (opmode) { case IEEE80211_M_STA: /* WDS/Repeater */ if (flags & IEEE80211_NO_STABEACONS) vap->iv_flags_ext |= IEEE80211_FEXT_SWBMISS; break; case IEEE80211_M_IBSS: vap->iv_caps |= IEEE80211_C_IBSS; vap->iv_ath_cap &= ~IEEE80211_ATHC_XR; break; case IEEE80211_M_AHDEMO: vap->iv_caps |= IEEE80211_C_AHDEMO; vap->iv_ath_cap &= ~IEEE80211_ATHC_XR; break; case IEEE80211_M_HOSTAP: vap->iv_caps |= IEEE80211_C_HOSTAP; vap->iv_ath_cap &= ~IEEE80211_ATHC_TURBOP; if ((vap->iv_flags & IEEE80211_VAP_XR) == 0) vap->iv_ath_cap &= ~IEEE80211_ATHC_XR; break; case IEEE80211_M_MONITOR: vap->iv_caps |= IEEE80211_C_MONITOR; vap->iv_ath_cap &= ~(IEEE80211_ATHC_XR | IEEE80211_ATHC_TURBOP); break; case IEEE80211_M_WDS: vap->iv_caps |= IEEE80211_C_WDS; vap->iv_ath_cap &= ~(IEEE80211_ATHC_XR | IEEE80211_ATHC_TURBOP); vap->iv_flags_ext |= IEEE80211_FEXT_WDS; break; } vap->iv_opmode = opmode; IEEE80211_INIT_TQUEUE(&vap->iv_stajoin1tq, ieee80211_sta_join1_tasklet, vap); vap->iv_chanchange_count = 0; /* * Enable various functionality by default if we're capable. */#ifdef notyet if (vap->iv_caps & IEEE80211_C_WME) vap->iv_flags |= IEEE80211_F_WME;#endif if (vap->iv_caps & IEEE80211_C_FF) vap->iv_flags |= IEEE80211_F_FF; /* NB: bg scanning only makes sense for station mode right now */ if (ic->ic_opmode == IEEE80211_M_STA && (vap->iv_caps & IEEE80211_C_BGSCAN)) vap->iv_flags |= IEEE80211_F_BGSCAN; vap->iv_dtim_period = IEEE80211_DTIM_DEFAULT; vap->iv_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ vap->iv_monitor_crc_errors = 0; vap->iv_monitor_phy_errors = 0; IEEE80211_ADDR_COPY(vap->iv_myaddr, ic->ic_myaddr); /* NB: defer setting dev_addr so driver can override */ ieee80211_crypto_vattach(vap); ieee80211_node_vattach(vap); ieee80211_power_vattach(vap); ieee80211_proto_vattach(vap); ieee80211_scan_vattach(vap); ieee80211_vlan_vattach(vap); ieee80211_ioctl_vattach(vap); ieee80211_sysctl_vattach(vap); return 1;#undef IEEE80211_C_OPMODE}EXPORT_SYMBOL(ieee80211_vap_setup);intieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change, ifm_stat_cb_t media_status){ struct net_device *dev = vap->iv_dev; struct ieee80211com *ic = vap->iv_ic; struct ifmediareq imr; ieee80211_node_latevattach(vap); /* XXX move into vattach */ ieee80211_power_latevattach(vap); /* XXX move into vattach */ memset(vap->wds_mac, 0x00, IEEE80211_ADDR_LEN); (void) ieee80211_media_setup(ic, &vap->iv_media, vap->iv_caps, media_change, media_status); ieee80211_media_status(dev, &imr); ifmedia_set(&vap->iv_media, imr.ifm_active); IEEE80211_LOCK_IRQ(ic); TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next); IEEE80211_UNLOCK_IRQ(ic); IEEE80211_ADDR_COPY(dev->dev_addr, vap->iv_myaddr);#ifdef ATH_SUPERG_XR /* * do not register XR vap device with OS. */ if (vap->iv_flags & IEEE80211_F_XR) return 0; #endif ieee80211_scanner_get(vap->iv_opmode, 1); /* NB: rtnl is held on entry so don't use register_netdev */ if (register_netdevice(dev)) { printk(KERN_ERR "%s: unable to register device\n", dev->name); return 0; } else return 1;}EXPORT_SYMBOL(ieee80211_vap_attach);voidieee80211_vap_detach(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; struct net_device *dev = vap->iv_dev; IEEE80211_CANCEL_TQUEUE(&vap->iv_stajoin1tq); IEEE80211_LOCK_IRQ(ic); TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next); if (TAILQ_EMPTY(&ic->ic_vaps)) /* reset to supported mode */ ic->ic_opmode = IEEE80211_M_STA; IEEE80211_UNLOCK_IRQ(ic); ifmedia_removeall(&vap->iv_media); ieee80211_sysctl_vdetach(vap); ieee80211_proc_cleanup(vap); ieee80211_ioctl_vdetach(vap); ieee80211_vlan_vdetach(vap); ieee80211_scan_vdetach(vap); ieee80211_proto_vdetach(vap); ieee80211_crypto_vdetach(vap); ieee80211_power_vdetach(vap); ieee80211_node_vdetach(vap);#ifdef ATH_SUPERG_XR /* * XR vap is not registered. */ if (!(vap->iv_flags & IEEE80211_F_XR))#endif /* NB: rtnl is held on entry so don't use unregister_netdev */ unregister_netdevice(dev);}EXPORT_SYMBOL(ieee80211_vap_detach);/* * Convert MHz frequency to IEEE channel number. */u_intieee80211_mhz2ieee(u_int freq, u_int flags){ if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ if (freq == 2484) /* Japan */ return 14; if ((freq >= 2412) && (freq < 2484)) /* don't number non-IEEE channels */ return (freq - 2407) / 5; return 0; } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */ if ((freq >= 5150) && (freq <= 5825)) /* don't number non-IEEE channels */ return (freq - 5000) / 5; return 0; } else { /* something is fishy, don't do anything */ return 0; }}EXPORT_SYMBOL(ieee80211_mhz2ieee);/* * Convert channel to IEEE channel number. */u_intieee80211_chan2ieee(struct ieee80211com *ic, const struct ieee80211_channel *c){ if (c == NULL) { if_printf(ic->ic_dev, "invalid channel (NULL)\n"); return 0; /* XXX */ } return (c == IEEE80211_CHAN_ANYC ? IEEE80211_CHAN_ANY : c->ic_ieee);}EXPORT_SYMBOL(ieee80211_chan2ieee);/* * Convert IEEE channel number to MHz frequency. */u_intieee80211_ieee2mhz(u_int chan, u_int flags){ if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ if (chan == 14) return 2484; if (chan < 14) return 2407 + chan * 5; else return 2512 + ((chan - 15) * 20); } else if (flags & IEEE80211_CHAN_5GHZ) /* 5Ghz band */ return 5000 + (chan * 5); else { /* either, guess */ if (chan == 14) return 2484; if (chan < 14) /* 0-13 */ return 2407 + chan * 5; if (chan < 27) /* 15-26 */ return 2512 + ((chan - 15) * 20); return 5000 + (chan * 5); }}EXPORT_SYMBOL(ieee80211_ieee2mhz);/* * Locate a channel given a frequency+flags. We cache * the previous lookup to optimize swithing between two * channels--as happens with dynamic turbo. */struct ieee80211_channel *ieee80211_find_channel(struct ieee80211com *ic, int freq, int flags){ struct ieee80211_channel *c; int i; flags &= IEEE80211_CHAN_ALLTURBO; c = ic->ic_prevchan; if (c != NULL && c->ic_freq == freq && (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags) return c; /* brute force search */ for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; if (c->ic_freq == freq && (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags) return c; } return NULL;}EXPORT_SYMBOL(ieee80211_find_channel);/* * Setup the media data structures according to the channel and * rate tables. This must be called by the driver after * ieee80211_attach and before most anything else. */intieee80211_media_setup(struct ieee80211com *ic, struct ifmedia *media, u_int32_t caps, ifm_change_cb_t media_change, ifm_stat_cb_t media_stat){#define ADD(_media, _s, _o) \ ifmedia_add(_media, IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL) int i, j, mode, rate, maxrate, mword, mopt, r; struct ieee80211_rateset *rs; struct ieee80211_rateset allrates; /* * Fill in media characteristics. */ ifmedia_init(media, 0, media_change, media_stat); maxrate = 0; memset(&allrates, 0, sizeof(allrates)); for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) { static const u_int mopts[] = { IFM_AUTO, IFM_IEEE80211_11A, IFM_IEEE80211_11B, IFM_IEEE80211_11G, IFM_IEEE80211_FH, IFM_IEEE80211_11A | IFM_IEEE80211_TURBO, IFM_IEEE80211_11G | IFM_IEEE80211_TURBO, }; if ((ic->ic_modecaps & (1<<mode)) == 0) continue; mopt = mopts[mode]; ADD(media, IFM_AUTO, mopt); /* e.g. 11a auto */ if (caps & IEEE80211_C_IBSS) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC); if (caps & IEEE80211_C_HOSTAP) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP); if (caps & IEEE80211_C_AHDEMO) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); if (caps & IEEE80211_C_MONITOR) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR); if (caps & IEEE80211_C_WDS) ADD(media, IFM_AUTO, mopt | IFM_IEEE80211_WDS); if (mode == IEEE80211_MODE_AUTO) continue; 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; ADD(media, mword, mopt); if (caps & IEEE80211_C_IBSS) ADD(media, mword, mopt | IFM_IEEE80211_ADHOC); if (caps & IEEE80211_C_HOSTAP) ADD(media, mword, mopt | IFM_IEEE80211_HOSTAP); if (caps & IEEE80211_C_AHDEMO) ADD(media, mword, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); if (caps & IEEE80211_C_MONITOR) ADD(media, mword, mopt | IFM_IEEE80211_MONITOR); if (caps & IEEE80211_C_WDS) ADD(media, mword, mopt | IFM_IEEE80211_WDS); /* * Add rate to the collection of all rates. */ r = rate & IEEE80211_RATE_VAL; for (j = 0; j < allrates.rs_nrates; j++) if (allrates.rs_rates[j] == r) break; if (j == allrates.rs_nrates) { /* unique, add to the set */ allrates.rs_rates[j] = r; allrates.rs_nrates++; } rate = (rate & IEEE80211_RATE_VAL) / 2; if (rate > maxrate) maxrate = rate; } } for (i = 0; i < allrates.rs_nrates; i++) { mword = ieee80211_rate2media(ic, allrates.rs_rates[i], IEEE80211_MODE_AUTO); if (mword == 0) continue; mword = IFM_SUBTYPE(mword); /* remove media options */ ADD(media, mword, 0); if (caps & IEEE80211_C_IBSS) ADD(media, mword, IFM_IEEE80211_ADHOC); if (caps & IEEE80211_C_HOSTAP) ADD(media, mword, IFM_IEEE80211_HOSTAP); if (caps & IEEE80211_C_AHDEMO) ADD(media, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0); if (caps & IEEE80211_C_MONITOR) ADD(media, mword, IFM_IEEE80211_MONITOR); if (caps & IEEE80211_C_WDS) ADD(media, mword, IFM_IEEE80211_WDS); } return maxrate;#undef ADD}voidieee80211_mark_dfs(struct ieee80211com *ic, struct ieee80211_channel *ichan){ struct ieee80211_channel *c=NULL; struct net_device *dev = ic->ic_dev; struct ieee80211vap *vap; int i; if_printf(dev, "Radar found on channel %d (%d MHz)\n", ichan->ic_ieee, ichan->ic_freq); if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* Mark the channel in the ic_chan list */ if (ic->ic_flags_ext & IEEE80211_FEXT_MARKDFS) { for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; if (c->ic_freq != ichan->ic_freq) continue; c->ic_flags |= IEEE80211_CHAN_RADAR; } c = ieee80211_find_channel(ic, ichan->ic_freq, ichan->ic_flags); if (c == NULL) { if_printf(dev,"%s: Couldn't find matching channel for dfs mark (%d, 0x%x)\n", __func__, ichan->ic_freq, ichan->ic_flags); return; } if (ic->ic_curchan->ic_freq == c->ic_freq) { /* get an AP vap */ vap = TAILQ_FIRST(&ic->ic_vaps); while ((vap != NULL) && (vap->iv_state != IEEE80211_S_RUN) && (vap->iv_ic != ic)) { vap = TAILQ_NEXT(vap, iv_next); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -