📄 ieee80211_wireless.c.svn-base
字号:
iwe.u.data.length = 0; current_ev = iwe_stream_add_point(req->info, current_ev, end_buf, &iwe, ""); /* We ran out of space in the buffer. */ if (last_ev == current_ev) return E2BIG; memset(&iwe, 0, sizeof(iwe)); last_ev = current_ev; iwe.cmd = SIOCGIWRATE; current_val = current_ev + iwe_stream_lcp_len(req->info); /* NB: not sorted, does it matter? */ for (j = 0; j < se->se_rates[1]; j++) { int r = se->se_rates[2 + j] & IEEE80211_RATE_VAL; if (r != 0) { iwe.u.bitrate.value = r * (1000000 / 2); current_val = iwe_stream_add_value(req->info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } } for (j = 0; j < se->se_xrates[1]; j++) { int r = se->se_xrates[2+j] & IEEE80211_RATE_VAL; if (r != 0) { iwe.u.bitrate.value = r * (1000000 / 2); current_val = iwe_stream_add_value(req->info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN); } } /* remove fixed header if no rates were added */ if ((current_val - current_ev) > iwe_stream_lcp_len(req->info)) { current_ev = current_val; } else { /* We ran out of space in the buffer. */ if (last_ev == current_ev) return E2BIG; } memset(&iwe, 0, sizeof(iwe)); last_ev = current_ev; iwe.cmd = IWEVCUSTOM; snprintf(buf, sizeof(buf), "bcn_int=%d", se->se_intval); iwe.u.data.length = strlen(buf); current_ev = iwe_stream_add_point(req->info, current_ev, end_buf, &iwe, buf); /* We ran out of space in the buffer. */ if (last_ev == current_ev) return E2BIG; if (se->se_rsn_ie != NULL) { last_ev = current_ev;#ifdef IWEVGENIE memset(&iwe, 0, sizeof(iwe)); if ((se->se_rsn_ie[1] + 2) > MAX_IE_LENGTH) return E2BIG; memcpy(buf, se->se_rsn_ie, se->se_rsn_ie[1] + 2); iwe.cmd = IWEVGENIE; iwe.u.data.length = se->se_rsn_ie[1] + 2;#else memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; if (se->se_rsn_ie[0] == IEEE80211_ELEMID_RSN) iwe.u.data.length = encode_ie(buf, sizeof(buf), se->se_rsn_ie, se->se_rsn_ie[1] + 2, rsn_leader, sizeof(rsn_leader) - 1);#endif if (iwe.u.data.length != 0) { current_ev = iwe_stream_add_point(req->info, current_ev, end_buf, &iwe, buf); /* We ran out of space in the buffer */ if (last_ev == current_ev) return E2BIG; } } if (se->se_wpa_ie != NULL) { last_ev = current_ev;#ifdef IWEVGENIE memset(&iwe, 0, sizeof(iwe)); if ((se->se_wpa_ie[1] + 2) > MAX_IE_LENGTH) return E2BIG; memcpy(buf, se->se_wpa_ie, se->se_wpa_ie[1] + 2); iwe.cmd = IWEVGENIE; iwe.u.data.length = se->se_wpa_ie[1] + 2;#else memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; iwe.u.data.length = encode_ie(buf, sizeof(buf), se->se_wpa_ie, se->se_wpa_ie[1] + 2, wpa_leader, sizeof(wpa_leader) - 1);#endif if (iwe.u.data.length != 0) { current_ev = iwe_stream_add_point(req->info, current_ev, end_buf, &iwe, buf); /* We ran out of space in the buffer. */ if (last_ev == current_ev) return E2BIG; } } if (se->se_wme_ie != NULL) { static const char wme_leader[] = "wme_ie="; memset(&iwe, 0, sizeof(iwe)); last_ev = current_ev; iwe.cmd = IWEVCUSTOM; iwe.u.data.length = encode_ie(buf, sizeof(buf), se->se_wme_ie, se->se_wme_ie[1] + 2, wme_leader, sizeof(wme_leader) - 1); if (iwe.u.data.length != 0) { current_ev = iwe_stream_add_point(req->info, current_ev, end_buf, &iwe, buf); /* We ran out of space in the buffer. */ if (last_ev == current_ev) return E2BIG; } } if (se->se_ath_ie != NULL) { static const char ath_leader[] = "ath_ie="; memset(&iwe, 0, sizeof(iwe)); last_ev = current_ev; iwe.cmd = IWEVCUSTOM; iwe.u.data.length = encode_ie(buf, sizeof(buf), se->se_ath_ie, se->se_ath_ie[1] + 2, ath_leader, sizeof(ath_leader) - 1); if (iwe.u.data.length != 0) { current_ev = iwe_stream_add_point(req->info, current_ev, end_buf, &iwe, buf); /* We ran out of space in the buffer. */ if (last_ev == current_ev) return E2BIG; } } req->current_ev = current_ev; return 0;}static intieee80211_ioctl_giwscan(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 iwscanreq req; int res = 0; req.vap = vap; req.info = info; req.current_ev = extra; if (data->length == 0) { req.end_buf = extra + IW_SCAN_MAX_DATA; } else { req.end_buf = extra + data->length; } /* * NB: This is no longer needed, as long as the caller supports * large scan results. * * Do two passes to ensure WPA/non-WPA scan candidates * are sorted to the front. This is a hack to deal with * the wireless extensions capping scan results at * IW_SCAN_MAX_DATA bytes. In densely populated environments * it's easy to overflow this buffer (especially with WPA/RSN * information elements). Note this sorting hack does not * guarantee we won't overflow anyway. */ req.mode = vap->iv_flags & IEEE80211_F_WPA; res = ieee80211_scan_iterate(ic, giwscan_cb, &req); if (res == 0) { req.mode = req.mode ? 0 : IEEE80211_F_WPA; res = ieee80211_scan_iterate(ic, giwscan_cb, &req); } data->length = req.current_ev - extra; if (res != 0) { return -res; } return res;}#endif /* SIOCGIWSCAN */static intcipher2cap(int cipher){ switch (cipher) { case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP; case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES; case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM; case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP; case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP; } return 0;}#define IEEE80211_MODE_TURBO_STATIC_A IEEE80211_MODE_MAXstatic intieee80211_convert_mode(const char *mode){#define TOUPPER(c) ((((c) > 0x60) && ((c) < 0x7b)) ? ((c) - 0x20) : (c)) static const struct { char *name; int mode; } mappings[] = { /* NB: need to order longest strings first for overlaps */ { "11AST" , IEEE80211_MODE_TURBO_STATIC_A }, { "AUTO" , IEEE80211_MODE_AUTO }, { "11A" , IEEE80211_MODE_11A }, { "11B" , IEEE80211_MODE_11B }, { "11G" , IEEE80211_MODE_11G }, { "FH" , IEEE80211_MODE_FH }, { "0" , IEEE80211_MODE_AUTO }, { "1" , IEEE80211_MODE_11A }, { "2" , IEEE80211_MODE_11B }, { "3" , IEEE80211_MODE_11G }, { "4" , IEEE80211_MODE_FH }, { "5" , IEEE80211_MODE_TURBO_STATIC_A }, { NULL } }; int i, j; const char *cp; for (i = 0; mappings[i].name != NULL; i++) { cp = mappings[i].name; for (j = 0; j < strlen(mode) + 1; j++) { /* convert user-specified string to upper case */ if (TOUPPER(mode[j]) != cp[j]) break; if (cp[j] == '\0') return mappings[i].mode; } } return -1;#undef TOUPPER}static intieee80211_ioctl_setmode(struct net_device *dev, struct iw_request_info *info, struct iw_point *wri, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; struct ifreq ifr; char s[6]; /* big enough for ``11adt'' */ int retv, mode, ifr_mode; if (ic->ic_media.ifm_cur == NULL) return -EINVAL; /* XXX: Wrong error */ if (wri->length > sizeof(s)) /* silently truncate */ wri->length = sizeof(s); if (copy_from_user(s, wri->pointer, wri->length)) return -EFAULT; s[sizeof(s) - 1] = '\0'; /* ensure null termination */ mode = ieee80211_convert_mode(s); if (mode < 0) return -EINVAL; if (ieee80211_check_mode_consistency(ic, mode, vap->iv_des_chan)) { /* * error in AP mode. * overwrite channel selection in other modes. */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) return -EINVAL; else vap->iv_des_chan = IEEE80211_CHAN_ANYC; } ifr_mode = mode; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media & ~IFM_MMASK; if (mode == IEEE80211_MODE_TURBO_STATIC_A) ifr_mode = IEEE80211_MODE_11A; ifr.ifr_media |= IFM_MAKEMODE(ifr_mode); retv = ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA); if ((!retv || retv == -ENETRESET) && (mode != vap->iv_des_mode)) { if (preempt_scan(dev, 100, 100)) ieee80211_scan_flush(ic); /* NB: could optimize */ else return -ETIMEDOUT; vap->iv_des_mode = mode; if (IS_UP_AUTO(vap)) ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); retv = 0; }#ifdef ATH_SUPERG_XR /* set the same params on the xr vap device if exists */ if (vap->iv_xrvap && !(vap->iv_flags & IEEE80211_F_XR)) vap->iv_xrvap->iv_des_mode = mode;#endif return -retv;}#undef IEEE80211_MODE_TURBO_STATIC_A#ifdef ATH_SUPERG_XRstatic voidieee80211_setupxr(struct ieee80211vap *vap){ struct net_device *dev = vap->iv_dev; struct ieee80211com *ic = vap->iv_ic; if (!(vap->iv_flags & IEEE80211_F_XR)) { if ((vap->iv_ath_cap & IEEE80211_ATHC_XR) && !vap->iv_xrvap) { struct ieee80211vap *xrvap = NULL; char name[IFNAMSIZ]; strcpy(name, dev->name); strcat(name, "-xr"); /* * Create a new XR vap. If the normal VAP is already up, * bring up the XR vap aswell. */ vap->iv_ath_cap &= ~IEEE80211_ATHC_TURBOP; /* turn off turbo */ ieee80211_scan_flush(ic); /* NB: could optimize */ if (!(xrvap = ic->ic_vap_create(ic, name, IEEE80211_M_HOSTAP, IEEE80211_VAP_XR | IEEE80211_CLONE_BSSID, dev))) return; /* We use iv_xrvap to link to the parent VAP as well */ xrvap->iv_xrvap = vap; xrvap->iv_ath_cap = vap->iv_ath_cap; xrvap->iv_fragthreshold = IEEE80211_XR_FRAG_THRESHOLD; xrvap->iv_des_mode = vap->iv_des_mode; copy_des_ssid(xrvap, vap); vap->iv_xrvap = xrvap; } else if (!(vap->iv_ath_cap & IEEE80211_ATHC_XR) && vap->iv_xrvap) { /* * Destroy the XR vap. If the XR VAP is up, bring * it down before destroying. */ if (vap->iv_xrvap) { ieee80211_stop(vap->iv_xrvap->iv_dev); ic->ic_vap_delete(vap->iv_xrvap); } vap->iv_xrvap = NULL; } }}#endifstatic intieee80211_setathcap(struct ieee80211vap *vap, int cap, int setting){ struct ieee80211com *ic = vap->iv_ic; int ocap; if ((ic->ic_ath_cap & cap) == 0) return EINVAL; ocap = vap->iv_ath_cap; if (setting) vap->iv_ath_cap |= cap; else vap->iv_ath_cap &= ~cap; return (vap->iv_ath_cap != ocap ? ENETRESET : 0);}static intieee80211_set_turbo(struct net_device *dev, int flag){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; struct ifreq ifr; struct ieee80211vap *tmpvap = netdev_priv(dev); int nvap = 0; TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) nvap++; if ((nvap > 1) && flag) return -EINVAL; ifr.ifr_media = ic->ic_media.ifm_cur->ifm_media &~ IFM_MMASK; if (flag) ifr.ifr_media |= IFM_IEEE80211_TURBO; else ifr.ifr_media &= ~IFM_IEEE80211_TURBO; (void) ifmedia_ioctl(ic->ic_dev, &ifr, &ic->ic_media, SIOCSIFMEDIA); return 0;}static intieee80211_ioctl_setparam(struct net_device *dev, struct iw_request_info *info, void *w, char *extra){ struct ieee80211vap *vap = netdev_priv(dev); struct ieee80211com *ic = vap->iv_ic; struct ieee80211_rsnparms *rsn = &vap->iv_bss->ni_rsn; unsigned int *i = (unsigned int *)extra; unsigned int param = i[0]; /* parameter id is 1st */ unsigned int value = i[1]; /* NB: most values are TYPE_INT */ int retv = 0; int j, caps, bmiss; const struct ieee80211_authenticator *auth; const struct ieee80211_aclator *acl; switch (param) { case IEEE80211_PARAM_AUTHMODE: switch (value) { case IEEE80211_AUTH_WPA: /* WPA */ case IEEE80211_AUTH_8021X: /* 802.1x */ case IEEE80211_AUTH_OPEN: /* open */ case IEEE80211_AUTH_SHARED: /* shared-key */ case IEEE80211_AUTH_AUTO: /* auto */ auth = ieee80211_authenticator_get(value); if (auth == NULL) return -EINVAL; /* XXX: Wrong error */ break; default: return -EINVAL; } switch (value) { case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ value = IEEE80211_AUTH_8021X; break; case IEEE80211_AUTH_OPEN: /* open */ vap->iv_flags &= ~(IEEE80211_F_WPA); break; case IEEE80211_AUTH_SHARED: /* shared-key */ case IEEE80211_AUTH_AUTO: /* auto */ case IEEE80211_AUTH_8021X: /* 802.1x */ vap->iv_flags &= ~IEEE80211_F_WPA; break; } /* NB: authenticator attach/detach happens on state change */ vap->iv_bss->ni_authmode = value; /* XXX mixed/mode/usage? */ vap->iv_auth = auth; retv = ENETRESET; break; case IEEE80211_PARAM_PROTMODE: if (value > IEEE80211_PROT_RTSCTS) return -EINVAL; ic->ic_protmode = value; /* NB: if not operating in 11g this can wait */ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan)) retv = ENETRESET; break; case IEEE80211_PARAM_RSSI_EWMA: ic->ic_rssi_ewma = value; break; case IEEE80211_PARAM_MCASTCIPHER: if ((vap->iv_caps & cipher2cap(value)) == 0 && !ieee80211_crypto_available(vap, value)) return -EINVAL; rsn->rsn_mcastcipher = value; if (vap->iv_flags & IEEE80211_F_WPA) retv = ENETRESET; break; case IEEE80211_PARAM_MCASTKEYLEN: if (value
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -