📄 ieee80211_wireless.c
字号:
return 0;}static intieee80211_ioctl_giwrts(struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra){ struct ieee80211vap *vap = dev->priv; rts->value = vap->iv_rtsthreshold; rts->disabled = (rts->value == IEEE80211_RTS_MAX); rts->fixed = 1; return 0;}static intieee80211_ioctl_siwfrag(struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra){ struct ieee80211vap *vap = dev->priv; struct ieee80211com *ic = vap->iv_ic; u16 val; if (rts->disabled) val = 2346; else if (rts->value < 256 || rts->value > 2346) return -EINVAL; else val = (rts->value & ~0x1); if (val != vap->iv_fragthreshold) { 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 = dev->priv; 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){ static const u_int8_t zero_bssid[IEEE80211_ADDR_LEN]; static const u_int8_t broadcast_bssid[IEEE80211_ADDR_LEN] = "\xff\xff\xff\xff\xff\xff"; struct ieee80211vap *vap = dev->priv; /* NB: should not be set when in AP mode */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) return -EINVAL; /* * 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. */ if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, zero_bssid)) vap->iv_flags &= ~IEEE80211_F_DESBSSID; else { IEEE80211_ADDR_COPY(vap->iv_des_bssid, &ap_addr->sa_data); if (IEEE80211_ADDR_EQ(vap->iv_des_bssid, broadcast_bssid)) vap->iv_flags &= ~IEEE80211_F_DESBSSID; else vap->iv_flags |= IEEE80211_F_DESBSSID; 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 = dev->priv; if (vap->iv_flags & IEEE80211_F_DESBSSID) IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_des_bssid); else { static const u_int8_t zero_bssid[IEEE80211_ADDR_LEN]; if (vap->iv_state == IEEE80211_S_RUN) if (vap->iv_opmode != IEEE80211_M_WDS) IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->iv_bss->ni_bssid); else IEEE80211_ADDR_COPY(&ap_addr->sa_data, vap->wds_mac); else IEEE80211_ADDR_COPY(&ap_addr->sa_data, zero_bssid); } 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 = dev->priv; if (data->length > IEEE80211_NWID_LEN) return -EINVAL; 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 = dev->priv; 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; 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 = dev->priv; 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) { 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 == ic->ic_bsschan) 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 { /* * Intepret 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. */ 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 = dev->priv; 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 = dev->priv; 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; /* * 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). */ if (data->length > 0 && vap->iv_des_ssid[0].ssid[data->length - 1] == '\0') vap->iv_des_ssid[0].len--; }#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 = dev->priv; 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 = dev->priv; 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? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -