📄 ieee80211.c
字号:
vap->iv_fixed_rate, mode); } else if (vap->iv_opmode == IEEE80211_M_STA) { /* * In station mode report the current transmit rate. */ rs = &vap->iv_bss->ni_rates; imr->ifm_active |= ieee80211_rate2media(ic, rs->rs_rates[vap->iv_bss->ni_txrate], mode); } else imr->ifm_active |= IFM_AUTO;}EXPORT_SYMBOL(ieee80211_media_status);/* * Set the current phy mode. */intieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode){#if 0 /* * Potentially invalidate the bss channel. */ /* XXX not right/too conservative */ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && mode != ieee80211_chan2mode(ic->ic_bsschan)) ic->ic_bsschan = IEEE80211_CHAN_ANYC; /* invalidate */#endif ieee80211_reset_erp(ic, mode); /* reset ERP state */ ic->ic_curmode = mode; /* NB: must do post reset_erp */ return 0;}EXPORT_SYMBOL(ieee80211_setmode);/* * Return the phy mode for with the specified channel. */enum ieee80211_phymodeieee80211_chan2mode(const struct ieee80211_channel *chan){ /* * Callers should handle this case properly, rather than * just relying that this function returns a sane value. * XXX Probably needs to be revised. */ KASSERT(chan != IEEE80211_CHAN_ANYC, ("channel not setup")); if (IEEE80211_IS_CHAN_108G(chan)) return IEEE80211_MODE_TURBO_G; else if (IEEE80211_IS_CHAN_TURBO(chan)) return IEEE80211_MODE_TURBO_A; else if (IEEE80211_IS_CHAN_A(chan)) return IEEE80211_MODE_11A; else if (IEEE80211_IS_CHAN_ANYG(chan)) return IEEE80211_MODE_11G; else if (IEEE80211_IS_CHAN_B(chan)) return IEEE80211_MODE_11B; else if (IEEE80211_IS_CHAN_FHSS(chan)) return IEEE80211_MODE_FH; /* NB: should not get here */ printk("%s: cannot map channel to mode; freq %u flags 0x%x\n", __func__, chan->ic_freq, chan->ic_flags); return IEEE80211_MODE_11B;}EXPORT_SYMBOL(ieee80211_chan2mode);/* * convert IEEE80211 rate value to ifmedia subtype. * ieee80211 rate is in unit of 0.5Mbps. */intieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode mode){#define N(a) (sizeof(a) / sizeof(a[0])) static const struct { u_int m; /* rate + mode */ u_int r; /* if_media rate */ } rates[] = { { 2 | IFM_IEEE80211_FH, IFM_IEEE80211_FH1 }, { 4 | IFM_IEEE80211_FH, IFM_IEEE80211_FH2 }, { 2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 }, { 4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 }, { 11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 }, { 22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 }, { 44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 }, { 3 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM1_50 }, { 4 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM2_25 }, { 6 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM3 }, { 9 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM4_50 }, { 12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 }, { 18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 }, { 24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 }, { 27 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM13_5 }, { 36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 }, { 48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 }, { 54 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM27 }, { 72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 }, { 96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 }, { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 }, { 2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 }, { 4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 }, { 11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 }, { 22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 }, { 12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 }, { 18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 }, { 24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 }, { 36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 }, { 48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 }, { 72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 }, { 96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 }, { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 }, /* NB: OFDM72 doesn't really exist so we don't handle it */ }; u_int mask, i; mask = rate & IEEE80211_RATE_VAL; switch (mode) { case IEEE80211_MODE_11A: case IEEE80211_MODE_TURBO_A: mask |= IFM_IEEE80211_11A; break; case IEEE80211_MODE_11B: mask |= IFM_IEEE80211_11B; break; case IEEE80211_MODE_FH: mask |= IFM_IEEE80211_FH; break; case IEEE80211_MODE_AUTO: /* NB: ic may be NULL for some drivers */ if (ic && ic->ic_phytype == IEEE80211_T_FH) { mask |= IFM_IEEE80211_FH; break; } /* NB: hack, 11g matches both 11b+11a rates */ /* fall thru... */ case IEEE80211_MODE_11G: case IEEE80211_MODE_TURBO_G: mask |= IFM_IEEE80211_11G; break; } for (i = 0; i < N(rates); i++) if (rates[i].m == mask) return rates[i].r; return IFM_AUTO;#undef N}EXPORT_SYMBOL(ieee80211_rate2media);intieee80211_media2rate(int mword){#define N(a) (sizeof(a) / sizeof(a[0])) static const int ieeerates[] = { -1, /* IFM_AUTO */ 0, /* IFM_MANUAL */ 0, /* IFM_NONE */ 2, /* IFM_IEEE80211_FH1 */ 4, /* IFM_IEEE80211_FH2 */ 2, /* IFM_IEEE80211_DS1 */ 4, /* IFM_IEEE80211_DS2 */ 11, /* IFM_IEEE80211_DS5 */ 22, /* IFM_IEEE80211_DS11 */ 44, /* IFM_IEEE80211_DS22 */ 3, /* IFM_IEEE80211_OFDM1_50 */ 4, /* IFM_IEEE80211_OFDM2_25 */ 6, /* IFM_IEEE80211_OFDM3 */ 9, /* IFM_IEEE80211_OFDM4_50 */ 12, /* IFM_IEEE80211_OFDM6 */ 18, /* IFM_IEEE80211_OFDM9 */ 24, /* IFM_IEEE80211_OFDM12 */ 27, /* IFM_IEEE80211_OFDM13_5 */ 36, /* IFM_IEEE80211_OFDM18 */ 48, /* IFM_IEEE80211_OFDM24 */ 54, /* IFM_IEEE80211_OFDM27 */ 72, /* IFM_IEEE80211_OFDM36 */ 96, /* IFM_IEEE80211_OFDM48 */ 108, /* IFM_IEEE80211_OFDM54 */ 144, /* IFM_IEEE80211_OFDM72 */ }; return IFM_SUBTYPE(mword) < N(ieeerates) ? ieeerates[IFM_SUBTYPE(mword)] : 0;#undef N}EXPORT_SYMBOL(ieee80211_media2rate);/* * Return netdevice statistics. */static struct net_device_stats *ieee80211_getstats(struct net_device *dev){ struct ieee80211vap *vap = dev->priv; struct net_device_stats *stats = &vap->iv_devstats; /* XXX total guess as to what to count where */ /* update according to private statistics */ stats->tx_errors = vap->iv_stats.is_tx_nodefkey + vap->iv_stats.is_tx_noheadroom + vap->iv_stats.is_crypto_enmicfail; stats->tx_dropped = vap->iv_stats.is_tx_nobuf + vap->iv_stats.is_tx_nonode + vap->iv_stats.is_tx_unknownmgt + vap->iv_stats.is_tx_badcipher + vap->iv_stats.is_tx_nodefkey; stats->rx_errors = vap->iv_stats.is_rx_tooshort + vap->iv_stats.is_rx_wepfail + vap->iv_stats.is_rx_decap + vap->iv_stats.is_rx_nobuf + vap->iv_stats.is_rx_decryptcrc + vap->iv_stats.is_rx_ccmpmic + vap->iv_stats.is_rx_tkipmic + vap->iv_stats.is_rx_tkipicv; stats->rx_crc_errors = 0; return stats;}static intieee80211_change_mtu(struct net_device *dev, int mtu){ if (!(IEEE80211_MTU_MIN < mtu && mtu <= IEEE80211_MTU_MAX)) return -EINVAL; dev->mtu = mtu; /* XXX coordinate with parent device */ return 0;}static voidieee80211_set_multicast_list(struct net_device *dev){ struct ieee80211vap *vap = dev->priv; struct ieee80211com *ic = vap->iv_ic; struct net_device *parent = ic->ic_dev; IEEE80211_LOCK_IRQ(ic); if (dev->flags & IFF_PROMISC) { if ((vap->iv_flags & IEEE80211_F_PROMISC) == 0) { vap->iv_flags |= IEEE80211_F_PROMISC; ic->ic_promisc++; parent->flags |= IFF_PROMISC; } } else { if (vap->iv_flags & IEEE80211_F_PROMISC) { vap->iv_flags &= ~IEEE80211_F_PROMISC; ic->ic_promisc--; parent->flags &= ~IFF_PROMISC; } } if (dev->flags & IFF_ALLMULTI) { if ((vap->iv_flags & IEEE80211_F_ALLMULTI) == 0) { vap->iv_flags |= IEEE80211_F_ALLMULTI; ic->ic_allmulti++; parent->flags |= IFF_ALLMULTI; } } else { if (vap->iv_flags & IEEE80211_F_ALLMULTI) { vap->iv_flags &= ~IEEE80211_F_ALLMULTI; ic->ic_allmulti--; parent->flags &= ~IFF_ALLMULTI; } } IEEE80211_UNLOCK_IRQ(ic); /* XXX merge multicast list into parent device */ parent->set_multicast_list(ic->ic_dev);}voidieee80211_build_countryie(struct ieee80211com *ic){#define N(a) (sizeof (a) / sizeof (a[0])) int i, j, chanflags, found; struct net_device *dev = ic->ic_dev; struct ieee80211_channel *c; u_int8_t chanlist[IEEE80211_CHAN_MAX + 1]; u_int8_t chancnt = 0; u_int8_t *cur_runlen, *cur_chan, *cur_pow, prevchan; /* * Fill in country IE. */ memset(&ic->ic_country_ie, 0, sizeof(ic->ic_country_ie)); ic->ic_country_ie.country_id = IEEE80211_ELEMID_COUNTRY; ic->ic_country_ie.country_len = 0; /* init needed by following code */ /* initialize country IE */ found = 0; for (i = 0; i < N(country_strings); i++) { if (country_strings[i].iso_code == ic->ic_country_code) { ic->ic_country_ie.country_str[0] = country_strings[i].iso_name[0]; ic->ic_country_ie.country_str[1] = country_strings[i].iso_name[1]; found = 1; break; } } if (!found) { if_printf(dev, "bad country string ignored: %d\n", ic->ic_country_code); ic->ic_country_ie.country_str[0] = ' '; ic->ic_country_ie.country_str[1] = ' '; } /* * indoor/outdoor portion if country string. * NB: this is not quite right, since we should have one of: * 'I' indoor only * 'O' outdoor only * ' ' all enviroments * we currently can only provide 'I' or ' '. */ ic->ic_country_ie.country_str[2] = 'I'; if (ic->ic_country_outdoor) ic->ic_country_ie.country_str[2] = ' '; /* * runlength encoded channel max tx power info. */ cur_runlen = &ic->ic_country_ie.country_triplet[1]; cur_chan = &ic->ic_country_ie.country_triplet[0]; cur_pow = &ic->ic_country_ie.country_triplet[2]; prevchan = 0; ic->ic_country_ie.country_len = 3; /* invalid, but just initialize */ if ((ic->ic_flags_ext & IEEE80211_FEXT_REGCLASS) && ic->ic_nregclass) { /* Add regulatory triplets. * chan/no_of_chans/tx power triplet is overridden as * as follows: * cur_chan == REGULATORY EXTENSION ID. * cur_runlen = Regulatory class. * cur_pow = coverage class. */ for (i=0; i < ic->ic_nregclass; i++) { *cur_chan = IEEE80211_REG_EXT_ID; *cur_runlen = ic->ic_regclassids[i]; *cur_pow = ic->ic_coverageclass; cur_runlen +=3; cur_chan += 3; cur_pow += 3; ic->ic_country_ie.country_len += 3; } } else { if ((ic->ic_curmode == IEEE80211_MODE_11A) || (ic->ic_curmode == IEEE80211_MODE_TURBO_A)) chanflags = IEEE80211_CHAN_5GHZ; else chanflags = IEEE80211_CHAN_2GHZ; memset(&chanlist[0], 0, sizeof(chanlist)); /* XXX not right due to duplicate entries */ for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; /* Does channel belong to current operation mode */ if (!(c->ic_flags & chanflags)) continue; /* Skip previously reported channels */ for (j = 0; j < chancnt; j++) if (c->ic_ieee == chanlist[j]) break; if (j != chancnt) /* found a match */ continue; chanlist[chancnt] = c->ic_ieee; chancnt++; /* Skip turbo channels */ if (IEEE80211_IS_CHAN_TURBO(c)) continue; /* Skip half/quarter rate channels */ if (IEEE80211_IS_CHAN_HALF(c) || IEEE80211_IS_CHAN_QUARTER(c)) continue; if (*cur_runlen == 0) { (*cur_runlen)++; *cur_pow = c->ic_maxregpower; *cur_chan = c->ic_ieee; prevchan = c->ic_ieee; ic->ic_country_ie.country_len += 3; } else if (*cur_pow == c->ic_maxregpower && c->ic_ieee == prevchan + 1) { (*cur_runlen)++; prevchan = c->ic_ieee; } else { cur_runlen +=3; cur_chan += 3; cur_pow += 3; (*cur_runlen)++; *cur_pow = c->ic_maxregpower; *cur_chan = c->ic_ieee; prevchan = c->ic_ieee; ic->ic_country_ie.country_len += 3; } } } /* pad */ if (ic->ic_country_ie.country_len & 1) ic->ic_country_ie.country_len++;#if 0 ic->ic_country_ie.country_len=8; ic->ic_country_ie.country_triplet[0] = 10; ic->ic_country_ie.country_triplet[1] = 11; ic->ic_country_ie.country_triplet[2] = 12;#endif#undef N}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -