📄 ieee80211_wireless.c.svn-base
字号:
range->pmp_flags = IW_POWER_PERIOD; range->pmt_flags = IW_POWER_TIMEOUT; range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R | IW_POWER_ALL_R; } range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 18; range->retry_capa = IW_RETRY_LIMIT; range->retry_flags = IW_RETRY_LIMIT; range->min_retry = 0; range->max_retry = 255; range->num_channels = ic->ic_nchans; range->num_frequency = 0; memset(reported, 0, sizeof(reported)); for (i = 0; i < ic->ic_nchans; i++) { const struct ieee80211_channel *c = &ic->ic_channels[i]; /* discard if previously reported (e.g. b/g) */ if (isclr(reported, c->ic_ieee)) { setbit(reported, c->ic_ieee); range->freq[range->num_frequency].i = c->ic_ieee; range->freq[range->num_frequency].m = ic->ic_channels[i].ic_freq * 100000; range->freq[range->num_frequency].e = 1; if (++range->num_frequency == IW_MAX_FREQUENCIES) break; } } /* Atheros' RSSI value is SNR: 0 -> 60 for old chipsets. Range * for newer chipsets is unknown. This value is arbitarily chosen * to give an indication that full rate will be available and to be * a practicable maximum. */ range->max_qual.qual = 70;#if WIRELESS_EXT >= 19 /* XXX: This should be updated to use the current noise floor. */ /* These are negative full bytes. * Min. quality is noise + 1 */ range->max_qual.updated |= IW_QUAL_DBM; range->max_qual.level = ATH_DEFAULT_NOISE + 1; range->max_qual.noise = ATH_DEFAULT_NOISE;#else /* Values larger than the maximum are assumed to be absolute */ range->max_qual.level = 0; range->max_qual.noise = 0;#endif range->sensitivity = 1; range->max_encoding_tokens = IEEE80211_WEP_NKID; /* XXX query driver to find out supported key sizes */ range->num_encoding_sizes = 3; range->encoding_size[0] = 5; /* 40-bit */ range->encoding_size[1] = 13; /* 104-bit */ range->encoding_size[2] = 16; /* 128-bit */ /* XXX this only works for station mode */ rs = &ni->ni_rates; range->num_bitrates = rs->rs_nrates; if (range->num_bitrates > IW_MAX_BITRATES) range->num_bitrates = IW_MAX_BITRATES; for (i = 0; i < range->num_bitrates; i++) { r = rs->rs_rates[i] & IEEE80211_RATE_VAL; range->bitrate[i] = (r * 1000000) / 2; } /* estimated maximum TCP throughput values (bps) */ range->throughput = 5500000; range->min_rts = 0; range->max_rts = 2347; range->min_frag = 256; range->max_frag = 2346;#if WIRELESS_EXT >= 17 /* Event capability (kernel) */ IW_EVENT_CAPA_SET_KERNEL(range->event_capa); /* Event capability (driver) */ if (vap->iv_opmode == IEEE80211_M_STA || vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_AHDEMO) { /* for now, only ibss, ahdemo, sta has this cap */ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); } if (vap->iv_opmode == IEEE80211_M_STA) { /* for sta only */ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); IW_EVENT_CAPA_SET(range->event_capa, IWEVREGISTERED); IW_EVENT_CAPA_SET(range->event_capa, IWEVEXPIRED); } /* this is used for reporting replay failure, which is used by the different encoding schemes */ IW_EVENT_CAPA_SET(range->event_capa, IWEVCUSTOM);#endif#if WIRELESS_EXT >= 18 /* report supported WPA/WPA2 capabilities to userspace */ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;#endif return 0;}static intieee80211_ioctl_setspy(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra){ /* save the list of node addresses */ struct ieee80211vap *vap = netdev_priv(dev); struct sockaddr address[IW_MAX_SPY]; unsigned int number = data->length; int i; if (number > IW_MAX_SPY) return -E2BIG; /* get the addresses into the driver */ if (data->pointer) { if (copy_from_user(address, data->pointer, sizeof(struct sockaddr) * number)) return -EFAULT; } else return -EINVAL; /* copy the MAC addresses into a list */ if (number > 0) { /* extract the MAC addresses */ for (i = 0; i < number; i++) memcpy(&vap->iv_spy.mac[i * IEEE80211_ADDR_LEN], address[i].sa_data, IEEE80211_ADDR_LEN); /* init rssi timestamps to 0 */ memset(vap->iv_spy.ts_rssi, 0, sizeof(vap->iv_spy.ts_rssi)); } vap->iv_spy.num = number; return 0;}static intieee80211_ioctl_getspy(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra){ /* * locate nodes by mac (ieee80211_find_node()), * copy out rssi, set updated flag appropriately */ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta; struct ieee80211_node *ni; struct ieee80211com *ic = vap->iv_ic; struct sockaddr *address; struct iw_quality *spy_stat; unsigned int number = vap->iv_spy.num; int i; address = (struct sockaddr *)extra; spy_stat = (struct iw_quality *)(extra + number * sizeof(struct sockaddr)); for (i = 0; i < number; i++) { memcpy(address[i].sa_data, &vap->iv_spy.mac[i * IEEE80211_ADDR_LEN], IEEE80211_ADDR_LEN); address[i].sa_family = AF_PACKET; } /* locate a node, read its rssi, check if updated, convert to dBm */ for (i = 0; i < number; i++) { ni = ieee80211_find_node(nt, &vap->iv_spy.mac[i * IEEE80211_ADDR_LEN]); /* check we are associated w/ this vap */ if (ni) { if (ni->ni_vap == vap) { set_quality(&spy_stat[i], ic->ic_rssi_ewma ? ic->ic_node_getrssi(ni) : ni->ni_rssi, ic->ic_channoise); if (ni->ni_rtsf != vap->iv_spy.ts_rssi[i]) { vap->iv_spy.ts_rssi[i] = ni->ni_rtsf; } else { spy_stat[i].updated = 0; } } ieee80211_unref_node(&ni); } else { spy_stat[i].updated = IW_QUAL_ALL_INVALID; } } /* copy results to userspace */ data->length = number; return 0;}#if WIRELESS_EXT >= 16/* Enhanced iwspy support */static intieee80211_ioctl_setthrspy(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct iw_thrspy threshold; if (data->length != 1) return -EINVAL; /* get the threshold values into the driver */ if (data->pointer) { if (copy_from_user(&threshold, data->pointer, sizeof(struct iw_thrspy))) return -EFAULT; } else return -EINVAL; if (threshold.low.level == 0) { /* disable threshold */ vap->iv_spy.thr_low = 0; vap->iv_spy.thr_high = 0; IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, "%s: disabled iw_spy threshold\n", __func__); } else { /* We are passed a signal level/strength - calculate * corresponding RSSI values */ /* XXX: We should use current noise value. */ vap->iv_spy.thr_low = threshold.low.level + ATH_DEFAULT_NOISE; vap->iv_spy.thr_high = threshold.high.level + ATH_DEFAULT_NOISE; IEEE80211_DPRINTF(vap, IEEE80211_MSG_DEBUG, "%s: enabled iw_spy threshold\n", __func__); } return 0;}static intieee80211_ioctl_getthrspy(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; struct iw_thrspy *threshold; threshold = (struct iw_thrspy *)extra; /* set threshold values */ set_quality(&(threshold->low), vap->iv_spy.thr_low, ic->ic_channoise); set_quality(&(threshold->high), vap->iv_spy.thr_high, ic->ic_channoise); /* copy results to userspace */ data->length = 1; return 0;}#endifstatic intieee80211_ioctl_siwmode(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ifmediareq imr; int valid = 0; memset(&imr, 0, sizeof(imr)); vap->iv_media.ifm_status(vap->iv_dev, &imr); if (imr.ifm_active & IFM_IEEE80211_HOSTAP) valid = (*mode == IW_MODE_MASTER); else if (imr.ifm_active & IFM_IEEE80211_MONITOR) valid = (*mode == IW_MODE_MONITOR); else if (imr.ifm_active & IFM_IEEE80211_ADHOC) valid = (*mode == IW_MODE_ADHOC); else if (imr.ifm_active & IFM_IEEE80211_WDS) valid = (*mode == IW_MODE_REPEAT); else valid = (*mode == IW_MODE_INFRA); return valid ? 0 : -EINVAL;}static intieee80211_ioctl_giwmode(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ifmediareq imr; memset(&imr, 0, sizeof(imr)); vap->iv_media.ifm_status(vap->iv_dev, &imr); if (imr.ifm_active & IFM_IEEE80211_HOSTAP) *mode = IW_MODE_MASTER; else if (imr.ifm_active & IFM_IEEE80211_MONITOR) *mode = IW_MODE_MONITOR; else if (imr.ifm_active & IFM_IEEE80211_ADHOC) *mode = IW_MODE_ADHOC; else if (imr.ifm_active & IFM_IEEE80211_WDS) *mode = IW_MODE_REPEAT; else *mode = IW_MODE_INFRA; return 0;}static intieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; /* XXX: These values, flags, and caps do not seem to be used elsewhere * at all? */ if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) return -EOPNOTSUPP; if (wrq->disabled) { ic->ic_flags &= ~IEEE80211_F_PMGTON; } else { switch (wrq->flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: case IW_POWER_ALL_R: case IW_POWER_ON: if (wrq->flags & IW_POWER_PERIOD) { if (IEEE80211_BINTVAL_VALID(wrq->value)) ic->ic_lintval = IEEE80211_MS_TO_TU(wrq->value); else return -EINVAL; } if (wrq->flags & IW_POWER_TIMEOUT) ic->ic_holdover = IEEE80211_MS_TO_TU(wrq->value); ic->ic_flags |= IEEE80211_F_PMGTON; break; default: return -EINVAL; } } return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0;}static intieee80211_ioctl_giwpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; rrq->disabled = (ic->ic_flags & IEEE80211_F_PMGTON) == 0; if (!rrq->disabled) { switch (rrq->flags & IW_POWER_TYPE) { case IW_POWER_TIMEOUT: rrq->flags = IW_POWER_TIMEOUT; rrq->value = IEEE80211_TU_TO_MS(ic->ic_holdover); break; case IW_POWER_PERIOD: rrq->flags = IW_POWER_PERIOD; rrq->value = IEEE80211_TU_TO_MS(ic->ic_lintval); break; } rrq->flags |= IW_POWER_ALL_R; } return 0;}static intieee80211_ioctl_siwretry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; if (rrq->disabled) { if (vap->iv_flags & IEEE80211_F_SWRETRY) { vap->iv_flags &= ~IEEE80211_F_SWRETRY; goto done; } return 0; } if ((vap->iv_caps & IEEE80211_C_SWRETRY) == 0) return -EOPNOTSUPP; if (rrq->flags == IW_RETRY_LIMIT) { if (rrq->value >= 0) { vap->iv_txmin = rrq->value; vap->iv_txmax = rrq->value; /* XXX */ vap->iv_txlifetime = 0; /* XXX */ vap->iv_flags |= IEEE80211_F_SWRETRY; } else { vap->iv_flags &= ~IEEE80211_F_SWRETRY; } return 0; }done: return IS_UP(vap->iv_dev) ? ic->ic_reset(vap->iv_dev) : 0;}static intieee80211_ioctl_giwretry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); rrq->disabled = (vap->iv_flags & IEEE80211_F_SWRETRY) == 0; if (!rrq->disabled) { switch (rrq->flags & IW_RETRY_TYPE) { case IW_RETRY_LIFETIME: rrq->flags = IW_RETRY_LIFETIME; rrq->value = IEEE80211_TU_TO_MS(vap->iv_txlifetime); break; case IW_RETRY_LIMIT: rrq->flags = IW_RETRY_LIMIT; switch (rrq->flags & IW_RETRY_MODIFIER) { case IW_RETRY_MIN: rrq->flags |= IW_RETRY_MAX; rrq->value = vap->iv_txmin; break; case IW_RETRY_MAX: rrq->flags |= IW_RETRY_MAX; rrq->value = vap->iv_txmax; break; } break; } } return 0;}static intieee80211_ioctl_siwtxpow(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; int fixed, disabled; fixed = (ic->ic_flags & IEEE80211_F_TXPOW_FIXED); disabled = (fixed && vap->iv_bss->ni_txpower == 0); if (rrq->disabled) { if (!disabled) { if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) return -EOPNOTSUPP; ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; vap->iv_bss->ni_txpower = 0; goto done; } return 0; } if (rrq->fixed) { if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) return -EOPNOTSUPP; if (rrq->flags != IW_TXPOW_DBM) return -EINVAL; if (ic->ic_bsschan != IEEE80211_CHAN_ANYC) { if ((ic->ic_bsschan->ic_maxregpower >= rrq->value) && (ic->ic_txpowlimit/2 >= rrq->value)) { vap->iv_bss->ni_txpower = 2 * rrq->value; ic->ic_newtxpowlimit = 2 * rrq->value; ic->ic_flags |= IEEE80211_F_TXPOW_FIXED; } else return -EINVAL; } else { /* * No channel set yet
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -