📄 ieee80211_wireless.c.svn-base
字号:
vap->iv_fragthreshold = val; if (IS_UP(ic->ic_dev)) return ic->ic_reset(ic->ic_dev); } return 0;}static intieee80211_ioctl_giwfrag(struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); rts->value = vap->iv_fragthreshold; rts->disabled = (rts->value == 2346); rts->fixed = 1; return 0;}static intieee80211_ioctl_siwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); /* NB: should not be set when in AP mode */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) return -EOPNOTSUPP; if (vap->iv_opmode == IEEE80211_M_WDS) IEEE80211_ADDR_COPY(vap->wds_mac, &ap_addr->sa_data); /* * zero address corresponds to 'iwconfig ath0 ap off', which means * enable automatic choice of AP without actually forcing a * reassociation. * * broadcast address corresponds to 'iwconfig ath0 ap any', which * means scan for the current best AP. * * anything else specifies a particular AP. */ vap->iv_flags &= ~IEEE80211_F_DESBSSID; if (!IEEE80211_ADDR_NULL(&ap_addr->sa_data)) { if (!IEEE80211_ADDR_EQ(&ap_addr->sa_data, vap->iv_dev->broadcast)) vap->iv_flags |= IEEE80211_F_DESBSSID; IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data); if (IS_UP_AUTO(vap)) ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); } return 0;}static intieee80211_ioctl_giwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); if (vap->iv_flags & IEEE80211_F_DESBSSID) IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_des_bssid); else { if (vap->iv_state == IEEE80211_S_RUN) if (vap->iv_opmode != IEEE80211_M_WDS) IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_bssid); else IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->wds_mac); else IEEE80211_ADDR_SET_NULL(&ap_addr->sa_data); } ap_addr->sa_family = ARPHRD_ETHER; return 0;}static intieee80211_ioctl_siwnickn(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname){ struct ieee80211vap *vap = netdev_priv(dev); if (data->length > IEEE80211_NWID_LEN) return -E2BIG; memset(vap->iv_nickname, 0, IEEE80211_NWID_LEN); memcpy(vap->iv_nickname, nickname, data->length); vap->iv_nicknamelen = data->length; return 0;}static intieee80211_ioctl_giwnickn(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nickname){ struct ieee80211vap *vap = netdev_priv(dev); if (data->length > vap->iv_nicknamelen + 1) data->length = vap->iv_nicknamelen + 1; if (data->length > 0) { memcpy(nickname, vap->iv_nickname, data->length - 1); /* XXX: strcpy? */ nickname[data->length-1] = '\0'; } return 0;}static intfind11gchannel(struct ieee80211com *ic, int i, int freq){ for (; i < ic->ic_nchans; i++) { const struct ieee80211_channel *c = &ic->ic_channels[i]; if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) return 1; } return 0;}static struct ieee80211_channel *findchannel(struct ieee80211com *ic, int ieee, int mode){ static const u_int chanflags[] = { 0, /* IEEE80211_MODE_AUTO */ IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */ IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ IEEE80211_CHAN_ST, /* IEEE80211_MODE_TURBO_STATIC_A */ }; u_int modeflags; unsigned int i; modeflags = chanflags[mode]; for (i = 0; i < ic->ic_nchans; i++) { struct ieee80211_channel *c = &ic->ic_channels[i]; if (c->ic_ieee != ieee) continue; if (mode == IEEE80211_MODE_AUTO) { /* ignore turbo channels for autoselect */ if (!(ic->ic_ath_cap & IEEE80211_ATHC_TURBOP) && IEEE80211_IS_CHAN_TURBO(c)) continue; /* * XXX special-case 11b/g channels so we * always select the g channel if both * are present. */ if (!IEEE80211_IS_CHAN_B(c) || !find11gchannel(ic, i + 1, c->ic_freq)) return c; } else { if ((c->ic_flags & modeflags) == modeflags) return c; } } return NULL;}#define IEEE80211_MODE_TURBO_STATIC_A IEEE80211_MODE_MAXstatic intieee80211_check_mode_consistency(struct ieee80211com *ic, int mode, struct ieee80211_channel *c){ if (c == IEEE80211_CHAN_ANYC) return 0; switch (mode) { case IEEE80211_MODE_11B: if (IEEE80211_IS_CHAN_B(c)) return 0; else return 1; break; case IEEE80211_MODE_11G: if (IEEE80211_IS_CHAN_ANYG(c)) return 0; else return 1; break; case IEEE80211_MODE_11A: if (IEEE80211_IS_CHAN_A(c)) return 0; else return 1; break; case IEEE80211_MODE_TURBO_STATIC_A: if (IEEE80211_IS_CHAN_A(c) && IEEE80211_IS_CHAN_STURBO(c)) return 0; else return 1; break; case IEEE80211_MODE_AUTO: return 0; break; } return 1;}#undef IEEE80211_MODE_TURBO_STATIC_Astatic intieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; struct ieee80211_channel *c, *c2; int i; if (freq->e > 1) return -EINVAL; if (freq->e == 1) i = (ic->ic_mhz2ieee)(ic, freq->m / 100000, 0); else i = freq->m; if ((i != 0) && (i != -1)) { if (i > IEEE80211_CHAN_MAX) return -EINVAL; c = findchannel(ic, i, vap->iv_des_mode); if (c == NULL) { c = findchannel(ic, i, IEEE80211_MODE_AUTO); if (c == NULL) /* no channel */ return -EINVAL; } /* * Fine tune channel selection based on desired mode: * if 11b is requested, find the 11b version of any * 11g channel returned, * if static turbo, find the turbo version of any * 11a channel return, * otherwise we should be ok with what we've got. */ switch (vap->iv_des_mode) { case IEEE80211_MODE_11B: if (IEEE80211_IS_CHAN_ANYG(c)) { c2 = findchannel(ic, i, IEEE80211_MODE_11B); /* NB: should not happen, =>'s 11g w/o 11b */ if (c2 != NULL) c = c2; } break; case IEEE80211_MODE_TURBO_A: if (IEEE80211_IS_CHAN_A(c)) { c2 = findchannel(ic, i, IEEE80211_MODE_TURBO_A); if (c2 != NULL) c = c2; } break; default: /* NB: no static turboG */ break; } if (ieee80211_check_mode_consistency(ic, vap->iv_des_mode, c)) { if (vap->iv_opmode == IEEE80211_M_HOSTAP) return -EINVAL; } if ((vap->iv_state == IEEE80211_S_RUN) && (c == vap->iv_des_chan)) return 0; /* no change, return */ /* Don't allow to change to channel with radar found */ if (c->ic_flags & IEEE80211_CHAN_RADAR) return -EINVAL; /* * Mark desired channel and if running force a * radio change. */ vap->iv_des_chan = c; } else { /* * Interpret channel 0 to mean "no desired channel"; * otherwise there's no way to undo fixing the desired * channel. */ if (vap->iv_des_chan == IEEE80211_CHAN_ANYC) return 0; vap->iv_des_chan = IEEE80211_CHAN_ANYC; }#if 0 if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) { int mode = ieee80211_chan2mode(vap->iv_des_chan); if (mode != ic->ic_curmode) ieee80211_setmode(ic, mode); }#endif if ((vap->iv_opmode == IEEE80211_M_MONITOR || vap->iv_opmode == IEEE80211_M_WDS) && vap->iv_des_chan != IEEE80211_CHAN_ANYC) { /* Monitor and wds modes can switch directly. */ ic->ic_curchan = vap->iv_des_chan; if (vap->iv_state == IEEE80211_S_RUN) { ic->ic_set_channel(ic); } } else if (vap->iv_opmode == IEEE80211_M_HOSTAP) { /* Need to use channel switch announcement on beacon if we are * up and running. We use ic_set_channel directly if we are * "running" but not "up". Otherwise, iv_des_chan will take * effect when we are transitioned to RUN state later. */ if (IS_UP(vap->iv_dev) && (0 == (vap->iv_des_chan->ic_flags & CHANNEL_DFS))) { pre_announced_chanswitch(dev, ieee80211_chan2ieee(ic, vap->iv_des_chan), IEEE80211_DEFAULT_CHANCHANGE_TBTT_COUNT); } else if (vap->iv_state == IEEE80211_S_RUN) { ic->ic_curchan = vap->iv_des_chan; ic->ic_set_channel(ic); } } else { /* Need to go through the state machine in case we need * to reassociate or the like. The state machine will * pickup the desired channel and avoid scanning. */ if (IS_UP_AUTO(vap)) ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); } return 0;}static intieee80211_ioctl_giwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; if (vap->iv_state == IEEE80211_S_RUN && vap->iv_opmode != IEEE80211_M_MONITOR) { /* * NB: use curchan for monitor mode so you can see * manual scanning by apps like kismet. */ KASSERT(ic->ic_bsschan != IEEE80211_CHAN_ANYC, ("bss channel not set")); freq->m = ic->ic_bsschan->ic_freq; } else if (vap->iv_state != IEEE80211_S_INIT) /* e.g. when scanning */ freq->m = ic->ic_curchan->ic_freq; else if (vap->iv_des_chan != IEEE80211_CHAN_ANYC) freq->m = vap->iv_des_chan->ic_freq; else freq->m = 0; freq->m *= 100000; freq->e = 1; return 0;}#ifdef ATH_SUPERG_XR/* * Copy desired ssid state from one vap to another. */static voidcopy_des_ssid(struct ieee80211vap *dst, const struct ieee80211vap *src){ dst->iv_des_nssid = src->iv_des_nssid; memcpy(dst->iv_des_ssid, src->iv_des_ssid, src->iv_des_nssid * sizeof(src->iv_des_ssid[0]));}#endif /* ATH_SUPERG_XR */static intieee80211_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid){ struct ieee80211vap *vap = netdev_priv(dev); if (vap->iv_opmode == IEEE80211_M_WDS) return -EOPNOTSUPP; if (data->flags == 0) /* ANY */ vap->iv_des_nssid = 0; else { if (data->length > IEEE80211_NWID_LEN) data->length = IEEE80211_NWID_LEN; /* NB: always use entry 0 */ memcpy(vap->iv_des_ssid[0].ssid, ssid, data->length); vap->iv_des_ssid[0].len = data->length; vap->iv_des_nssid = 1;#if WIRELESS_EXT < 21 /* * Deduct a trailing \0 since iwconfig passes a string * length that includes this. Unfortunately this means * that specifying a string with multiple trailing \0's * won't be handled correctly. Not sure there's a good * solution; the API is botched (the length should be * exactly those bytes that are meaningful and not include * extraneous stuff). */ /* The API was fixed in WE21 */ if (data->length > 0 && vap->iv_des_ssid[0].ssid[data->length - 1] == '\0') vap->iv_des_ssid[0].len--;#endif /* WIRELESS_EXT < 21 */ }#ifdef ATH_SUPERG_XR if (vap->iv_xrvap != NULL && !(vap->iv_flags & IEEE80211_F_XR)) { if (data->flags == 0) vap->iv_des_nssid = 0; else copy_des_ssid(vap->iv_xrvap, vap); }#endif return IS_UP_AUTO(vap) ? ieee80211_init(vap->iv_dev, RESCAN) : 0;}static intieee80211_ioctl_giwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid){ struct ieee80211vap *vap = netdev_priv(dev); if (vap->iv_opmode == IEEE80211_M_WDS) return -EOPNOTSUPP; data->flags = 1; /* active */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) { if (vap->iv_des_nssid > 0) { if (data->length > vap->iv_des_ssid[0].len) data->length = vap->iv_des_ssid[0].len; memcpy(essid, vap->iv_des_ssid[0].ssid, data->length); } else data->length = 0; } else { if (vap->iv_des_nssid == 0) { if (data->length > vap->iv_bss->ni_esslen) data->length = vap->iv_bss->ni_esslen; memcpy(essid, vap->iv_bss->ni_essid, data->length); } else { if (data->length > vap->iv_des_ssid[0].len) data->length = vap->iv_des_ssid[0].len; memcpy(essid, vap->iv_des_ssid[0].ssid, data->length); } } return 0;}static intieee80211_ioctl_giwrange(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 ieee80211_node *ni = vap->iv_bss; struct iw_range *range = (struct iw_range *)extra; struct ieee80211_rateset *rs; u_int8_t reported[IEEE80211_CHAN_BYTES]; /* XXX stack usage? */ int i, r; int step = 0; data->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); /* txpower (128 values, but will print out only IW_MAX_TXPOWER) */ range->num_txpower = (ic->ic_txpowlimit >= 8) ? IW_MAX_TXPOWER : ic->ic_txpowlimit; step = ic->ic_txpowlimit / (2 * (IW_MAX_TXPOWER - 1)); range->txpower[0] = 0; for (i = 1; i < IW_MAX_TXPOWER; i++) range->txpower[i] = (ic->ic_txpowlimit/2) - (IW_MAX_TXPOWER - i - 1) * step; range->txpower_capa = IW_TXPOW_DBM; if (vap->iv_opmode == IEEE80211_M_STA || vap->iv_opmode == IEEE80211_M_IBSS) { range->min_pmp = 1 * 1024; range->max_pmp = 65535 * 1024; range->min_pmt = 1 * 1024; range->max_pmt = 1000 * 1024;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -