1/*- 2 * Copyright (c) 2001 Atsushi Onoe
| 1/*- 2 * Copyright (c) 2001 Atsushi Onoe
|
3 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
| 3 * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
|
4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * Alternatively, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2 as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h>
| 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * Alternatively, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2 as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h>
|
34__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 127648 2004-03-30 22:57:57Z sam $");
| 34__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 138568 2004-12-08 17:26:47Z sam $");
|
35 36/* 37 * IEEE 802.11 ioctl support (FreeBSD-specific) 38 */ 39 40#include "opt_inet.h" 41#include "opt_ipx.h" 42 43#include <sys/endian.h> 44#include <sys/param.h> 45#include <sys/kernel.h> 46#include <sys/socket.h> 47#include <sys/sockio.h> 48#include <sys/systm.h> 49 50#include <net/if.h> 51#include <net/if_arp.h> 52#include <net/if_media.h> 53#include <net/ethernet.h> 54 55#ifdef INET 56#include <netinet/in.h> 57#include <netinet/if_ether.h> 58#endif 59 60#ifdef IPX 61#include <netipx/ipx.h> 62#include <netipx/ipx_if.h> 63#endif 64 65#include <net80211/ieee80211_var.h> 66#include <net80211/ieee80211_ioctl.h> 67 68#include <dev/wi/if_wavelan_ieee.h> 69
| 35 36/* 37 * IEEE 802.11 ioctl support (FreeBSD-specific) 38 */ 39 40#include "opt_inet.h" 41#include "opt_ipx.h" 42 43#include <sys/endian.h> 44#include <sys/param.h> 45#include <sys/kernel.h> 46#include <sys/socket.h> 47#include <sys/sockio.h> 48#include <sys/systm.h> 49 50#include <net/if.h> 51#include <net/if_arp.h> 52#include <net/if_media.h> 53#include <net/ethernet.h> 54 55#ifdef INET 56#include <netinet/in.h> 57#include <netinet/if_ether.h> 58#endif 59 60#ifdef IPX 61#include <netipx/ipx.h> 62#include <netipx/ipx_if.h> 63#endif 64 65#include <net80211/ieee80211_var.h> 66#include <net80211/ieee80211_ioctl.h> 67 68#include <dev/wi/if_wavelan_ieee.h> 69
|
| 70#define IS_UP(_ic) \ 71 (((_ic)->ic_ifp->if_flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP)) 72#define IS_UP_AUTO(_ic) \ 73 (IS_UP(_ic) && (_ic)->ic_roaming == IEEE80211_ROAMING_AUTO) 74
|
70/* 71 * XXX 72 * Wireless LAN specific configuration interface, which is compatible 73 * with wicontrol(8). 74 */ 75
| 75/* 76 * XXX 77 * Wireless LAN specific configuration interface, which is compatible 78 * with wicontrol(8). 79 */ 80
|
| 81struct wi_read_ap_args { 82 int i; /* result count */ 83 struct wi_apinfo *ap; /* current entry in result buffer */ 84 caddr_t max; /* result buffer bound */ 85}; 86 87static void 88wi_read_ap_result(void *arg, struct ieee80211_node *ni) 89{ 90 struct ieee80211com *ic = ni->ni_ic; 91 struct wi_read_ap_args *sa = arg; 92 struct wi_apinfo *ap = sa->ap; 93 struct ieee80211_rateset *rs; 94 int j; 95 96 if ((caddr_t)(ap + 1) > sa->max) 97 return; 98 memset(ap, 0, sizeof(struct wi_apinfo)); 99 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 100 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr); 101 ap->namelen = ic->ic_des_esslen; 102 if (ic->ic_des_esslen) 103 memcpy(ap->name, ic->ic_des_essid, 104 ic->ic_des_esslen); 105 } else { 106 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid); 107 ap->namelen = ni->ni_esslen; 108 if (ni->ni_esslen) 109 memcpy(ap->name, ni->ni_essid, 110 ni->ni_esslen); 111 } 112 ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan); 113 ap->signal = ic->ic_node_getrssi(ni); 114 ap->capinfo = ni->ni_capinfo; 115 ap->interval = ni->ni_intval; 116 rs = &ni->ni_rates; 117 for (j = 0; j < rs->rs_nrates; j++) { 118 if (rs->rs_rates[j] & IEEE80211_RATE_BASIC) { 119 ap->rate = (rs->rs_rates[j] & 120 IEEE80211_RATE_VAL) * 5; /* XXX */ 121 } 122 } 123 sa->i++; 124 sa->ap++; 125} 126 127struct wi_read_prism2_args { 128 int i; /* result count */ 129 struct wi_scan_res *res;/* current entry in result buffer */ 130 caddr_t max; /* result buffer bound */ 131}; 132 133static void 134wi_read_prism2_result(void *arg, struct ieee80211_node *ni) 135{ 136 struct ieee80211com *ic = ni->ni_ic; 137 struct wi_read_prism2_args *sa = arg; 138 struct wi_scan_res *res = sa->res; 139 140 if ((caddr_t)(res + 1) > sa->max) 141 return; 142 res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan); 143 res->wi_noise = 0; 144 res->wi_signal = ic->ic_node_getrssi(ni); 145 IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid); 146 res->wi_interval = ni->ni_intval; 147 res->wi_capinfo = ni->ni_capinfo; 148 res->wi_ssid_len = ni->ni_esslen; 149 memcpy(res->wi_ssid, ni->ni_essid, IEEE80211_NWID_LEN); 150 /* NB: assumes wi_srates holds <= ni->ni_rates */ 151 memcpy(res->wi_srates, ni->ni_rates.rs_rates, 152 sizeof(res->wi_srates)); 153 if (ni->ni_rates.rs_nrates < 10) 154 res->wi_srates[ni->ni_rates.rs_nrates] = 0; 155 res->wi_rate = ni->ni_rates.rs_rates[ni->ni_txrate]; 156 res->wi_rsvd = 0; 157 158 sa->i++; 159 sa->res++; 160} 161 162struct wi_read_sigcache_args { 163 int i; /* result count */ 164 struct wi_sigcache *wsc;/* current entry in result buffer */ 165 caddr_t max; /* result buffer bound */ 166}; 167 168static void 169wi_read_sigcache(void *arg, struct ieee80211_node *ni) 170{ 171 struct ieee80211com *ic = ni->ni_ic; 172 struct wi_read_sigcache_args *sa = arg; 173 struct wi_sigcache *wsc = sa->wsc; 174 175 if ((caddr_t)(wsc + 1) > sa->max) 176 return; 177 memset(wsc, 0, sizeof(struct wi_sigcache)); 178 IEEE80211_ADDR_COPY(wsc->macsrc, ni->ni_macaddr); 179 wsc->signal = ic->ic_node_getrssi(ni); 180 181 sa->wsc++; 182 sa->i++; 183} 184
|
76int
| 185int
|
77ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data)
| 186ieee80211_cfgget(struct ieee80211com *ic, u_long cmd, caddr_t data)
|
78{
| 187{
|
79 struct ieee80211com *ic = (void *)ifp;
| 188 struct ifnet *ifp = ic->ic_ifp;
|
80 int i, j, error; 81 struct ifreq *ifr = (struct ifreq *)data; 82 struct wi_req wreq; 83 struct wi_ltv_keys *keys;
| 189 int i, j, error; 190 struct ifreq *ifr = (struct ifreq *)data; 191 struct wi_req wreq; 192 struct wi_ltv_keys *keys;
|
84 struct wi_apinfo *ap; 85 struct ieee80211_node *ni; 86 struct ieee80211_rateset *rs; 87 struct wi_sigcache wsc; 88 struct wi_scan_p2_hdr *p2; 89 struct wi_scan_res *res;
| |
90 91 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 92 if (error) 93 return error; 94 wreq.wi_len = 0; 95 switch (wreq.wi_type) { 96 case WI_RID_SERIALNO: 97 /* nothing appropriate */ 98 break; 99 case WI_RID_NODENAME: 100 strcpy((char *)&wreq.wi_val[1], hostname); 101 wreq.wi_val[0] = htole16(strlen(hostname)); 102 wreq.wi_len = (1 + strlen(hostname) + 1) / 2; 103 break; 104 case WI_RID_CURRENT_SSID: 105 if (ic->ic_state != IEEE80211_S_RUN) { 106 wreq.wi_val[0] = 0; 107 wreq.wi_len = 1; 108 break; 109 } 110 wreq.wi_val[0] = htole16(ic->ic_bss->ni_esslen); 111 memcpy(&wreq.wi_val[1], ic->ic_bss->ni_essid, 112 ic->ic_bss->ni_esslen); 113 wreq.wi_len = (1 + ic->ic_bss->ni_esslen + 1) / 2; 114 break; 115 case WI_RID_OWN_SSID: 116 case WI_RID_DESIRED_SSID: 117 wreq.wi_val[0] = htole16(ic->ic_des_esslen); 118 memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen); 119 wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2; 120 break; 121 case WI_RID_CURRENT_BSSID: 122 if (ic->ic_state == IEEE80211_S_RUN) 123 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss->ni_bssid); 124 else 125 memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN); 126 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 127 break; 128 case WI_RID_CHANNEL_LIST: 129 memset(wreq.wi_val, 0, sizeof(wreq.wi_val)); 130 /* 131 * Since channel 0 is not available for DS, channel 1 132 * is assigned to LSB on WaveLAN. 133 */ 134 if (ic->ic_phytype == IEEE80211_T_DS) 135 i = 1; 136 else 137 i = 0; 138 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) 139 if (isset(ic->ic_chan_active, i)) { 140 setbit((u_int8_t *)wreq.wi_val, j); 141 wreq.wi_len = j / 16 + 1; 142 } 143 break; 144 case WI_RID_OWN_CHNL: 145 wreq.wi_val[0] = htole16( 146 ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); 147 wreq.wi_len = 1; 148 break; 149 case WI_RID_CURRENT_CHAN: 150 wreq.wi_val[0] = htole16( 151 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)); 152 wreq.wi_len = 1; 153 break; 154 case WI_RID_COMMS_QUALITY: 155 wreq.wi_val[0] = 0; /* quality */
| 193 194 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 195 if (error) 196 return error; 197 wreq.wi_len = 0; 198 switch (wreq.wi_type) { 199 case WI_RID_SERIALNO: 200 /* nothing appropriate */ 201 break; 202 case WI_RID_NODENAME: 203 strcpy((char *)&wreq.wi_val[1], hostname); 204 wreq.wi_val[0] = htole16(strlen(hostname)); 205 wreq.wi_len = (1 + strlen(hostname) + 1) / 2; 206 break; 207 case WI_RID_CURRENT_SSID: 208 if (ic->ic_state != IEEE80211_S_RUN) { 209 wreq.wi_val[0] = 0; 210 wreq.wi_len = 1; 211 break; 212 } 213 wreq.wi_val[0] = htole16(ic->ic_bss->ni_esslen); 214 memcpy(&wreq.wi_val[1], ic->ic_bss->ni_essid, 215 ic->ic_bss->ni_esslen); 216 wreq.wi_len = (1 + ic->ic_bss->ni_esslen + 1) / 2; 217 break; 218 case WI_RID_OWN_SSID: 219 case WI_RID_DESIRED_SSID: 220 wreq.wi_val[0] = htole16(ic->ic_des_esslen); 221 memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen); 222 wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2; 223 break; 224 case WI_RID_CURRENT_BSSID: 225 if (ic->ic_state == IEEE80211_S_RUN) 226 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss->ni_bssid); 227 else 228 memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN); 229 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 230 break; 231 case WI_RID_CHANNEL_LIST: 232 memset(wreq.wi_val, 0, sizeof(wreq.wi_val)); 233 /* 234 * Since channel 0 is not available for DS, channel 1 235 * is assigned to LSB on WaveLAN. 236 */ 237 if (ic->ic_phytype == IEEE80211_T_DS) 238 i = 1; 239 else 240 i = 0; 241 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) 242 if (isset(ic->ic_chan_active, i)) { 243 setbit((u_int8_t *)wreq.wi_val, j); 244 wreq.wi_len = j / 16 + 1; 245 } 246 break; 247 case WI_RID_OWN_CHNL: 248 wreq.wi_val[0] = htole16( 249 ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); 250 wreq.wi_len = 1; 251 break; 252 case WI_RID_CURRENT_CHAN: 253 wreq.wi_val[0] = htole16( 254 ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)); 255 wreq.wi_len = 1; 256 break; 257 case WI_RID_COMMS_QUALITY: 258 wreq.wi_val[0] = 0; /* quality */
|
156 wreq.wi_val[1] = 157 htole16((*ic->ic_node_getrssi)(ic, ic->ic_bss));
| 259 wreq.wi_val[1] = htole16(ic->ic_node_getrssi(ic->ic_bss));
|
158 wreq.wi_val[2] = 0; /* noise */ 159 wreq.wi_len = 3; 160 break; 161 case WI_RID_PROMISC: 162 wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0); 163 wreq.wi_len = 1; 164 break; 165 case WI_RID_PORTTYPE: 166 wreq.wi_val[0] = htole16(ic->ic_opmode); 167 wreq.wi_len = 1; 168 break; 169 case WI_RID_MAC_NODE: 170 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr); 171 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 172 break; 173 case WI_RID_TX_RATE: 174 if (ic->ic_fixed_rate == -1) 175 wreq.wi_val[0] = 0; /* auto */ 176 else 177 wreq.wi_val[0] = htole16( 178 (ic->ic_sup_rates[ic->ic_curmode].rs_rates[ic->ic_fixed_rate] & 179 IEEE80211_RATE_VAL) / 2); 180 wreq.wi_len = 1; 181 break; 182 case WI_RID_CUR_TX_RATE: 183 wreq.wi_val[0] = htole16( 184 (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] & 185 IEEE80211_RATE_VAL) / 2); 186 wreq.wi_len = 1; 187 break; 188 case WI_RID_RTS_THRESH: 189 wreq.wi_val[0] = htole16(ic->ic_rtsthreshold); 190 wreq.wi_len = 1; 191 break; 192 case WI_RID_CREATE_IBSS: 193 wreq.wi_val[0] = 194 htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0); 195 wreq.wi_len = 1; 196 break; 197 case WI_RID_MICROWAVE_OVEN: 198 wreq.wi_val[0] = 0; /* no ... not supported */ 199 wreq.wi_len = 1; 200 break; 201 case WI_RID_ROAMING_MODE:
| 260 wreq.wi_val[2] = 0; /* noise */ 261 wreq.wi_len = 3; 262 break; 263 case WI_RID_PROMISC: 264 wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0); 265 wreq.wi_len = 1; 266 break; 267 case WI_RID_PORTTYPE: 268 wreq.wi_val[0] = htole16(ic->ic_opmode); 269 wreq.wi_len = 1; 270 break; 271 case WI_RID_MAC_NODE: 272 IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr); 273 wreq.wi_len = IEEE80211_ADDR_LEN / 2; 274 break; 275 case WI_RID_TX_RATE: 276 if (ic->ic_fixed_rate == -1) 277 wreq.wi_val[0] = 0; /* auto */ 278 else 279 wreq.wi_val[0] = htole16( 280 (ic->ic_sup_rates[ic->ic_curmode].rs_rates[ic->ic_fixed_rate] & 281 IEEE80211_RATE_VAL) / 2); 282 wreq.wi_len = 1; 283 break; 284 case WI_RID_CUR_TX_RATE: 285 wreq.wi_val[0] = htole16( 286 (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] & 287 IEEE80211_RATE_VAL) / 2); 288 wreq.wi_len = 1; 289 break; 290 case WI_RID_RTS_THRESH: 291 wreq.wi_val[0] = htole16(ic->ic_rtsthreshold); 292 wreq.wi_len = 1; 293 break; 294 case WI_RID_CREATE_IBSS: 295 wreq.wi_val[0] = 296 htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0); 297 wreq.wi_len = 1; 298 break; 299 case WI_RID_MICROWAVE_OVEN: 300 wreq.wi_val[0] = 0; /* no ... not supported */ 301 wreq.wi_len = 1; 302 break; 303 case WI_RID_ROAMING_MODE:
|
202 wreq.wi_val[0] = htole16(1); /* enabled ... not supported */
| 304 wreq.wi_val[0] = htole16(ic->ic_roaming); /* XXX map */
|
203 wreq.wi_len = 1; 204 break; 205 case WI_RID_SYSTEM_SCALE: 206 wreq.wi_val[0] = htole16(1); /* low density ... not supp */ 207 wreq.wi_len = 1; 208 break; 209 case WI_RID_PM_ENABLED: 210 wreq.wi_val[0] = 211 htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0); 212 wreq.wi_len = 1; 213 break; 214 case WI_RID_MAX_SLEEP: 215 wreq.wi_val[0] = htole16(ic->ic_lintval); 216 wreq.wi_len = 1; 217 break; 218 case WI_RID_CUR_BEACON_INT: 219 wreq.wi_val[0] = htole16(ic->ic_bss->ni_intval); 220 wreq.wi_len = 1; 221 break; 222 case WI_RID_WEP_AVAIL:
| 305 wreq.wi_len = 1; 306 break; 307 case WI_RID_SYSTEM_SCALE: 308 wreq.wi_val[0] = htole16(1); /* low density ... not supp */ 309 wreq.wi_len = 1; 310 break; 311 case WI_RID_PM_ENABLED: 312 wreq.wi_val[0] = 313 htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0); 314 wreq.wi_len = 1; 315 break; 316 case WI_RID_MAX_SLEEP: 317 wreq.wi_val[0] = htole16(ic->ic_lintval); 318 wreq.wi_len = 1; 319 break; 320 case WI_RID_CUR_BEACON_INT: 321 wreq.wi_val[0] = htole16(ic->ic_bss->ni_intval); 322 wreq.wi_len = 1; 323 break; 324 case WI_RID_WEP_AVAIL:
|
223 wreq.wi_val[0] = 224 htole16((ic->ic_caps & IEEE80211_C_WEP) ? 1 : 0);
| 325 wreq.wi_val[0] = htole16(1); /* always available */
|
225 wreq.wi_len = 1; 226 break; 227 case WI_RID_CNFAUTHMODE: 228 wreq.wi_val[0] = htole16(1); /* TODO: open system only */ 229 wreq.wi_len = 1; 230 break; 231 case WI_RID_ENCRYPTION: 232 wreq.wi_val[0] =
| 326 wreq.wi_len = 1; 327 break; 328 case WI_RID_CNFAUTHMODE: 329 wreq.wi_val[0] = htole16(1); /* TODO: open system only */ 330 wreq.wi_len = 1; 331 break; 332 case WI_RID_ENCRYPTION: 333 wreq.wi_val[0] =
|
233 htole16((ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0);
| 334 htole16((ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0);
|
234 wreq.wi_len = 1; 235 break; 236 case WI_RID_TX_CRYPT_KEY:
| 335 wreq.wi_len = 1; 336 break; 337 case WI_RID_TX_CRYPT_KEY:
|
237 wreq.wi_val[0] = htole16(ic->ic_wep_txkey);
| 338 wreq.wi_val[0] = htole16(ic->ic_def_txkey);
|
238 wreq.wi_len = 1; 239 break; 240 case WI_RID_DEFLT_CRYPT_KEYS: 241 keys = (struct wi_ltv_keys *)&wreq; 242 /* do not show keys to non-root user */ 243 error = suser(curthread); 244 if (error) { 245 memset(keys, 0, sizeof(*keys)); 246 error = 0; 247 break; 248 } 249 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 250 keys->wi_keys[i].wi_keylen =
| 339 wreq.wi_len = 1; 340 break; 341 case WI_RID_DEFLT_CRYPT_KEYS: 342 keys = (struct wi_ltv_keys *)&wreq; 343 /* do not show keys to non-root user */ 344 error = suser(curthread); 345 if (error) { 346 memset(keys, 0, sizeof(*keys)); 347 error = 0; 348 break; 349 } 350 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 351 keys->wi_keys[i].wi_keylen =
|
251 htole16(ic->ic_nw_keys[i].wk_len);
| 352 htole16(ic->ic_nw_keys[i].wk_keylen);
|
252 memcpy(keys->wi_keys[i].wi_keydat,
| 353 memcpy(keys->wi_keys[i].wi_keydat,
|
253 ic->ic_nw_keys[i].wk_key, ic->ic_nw_keys[i].wk_len);
| 354 ic->ic_nw_keys[i].wk_key, 355 ic->ic_nw_keys[i].wk_keylen);
|
254 } 255 wreq.wi_len = sizeof(*keys) / 2; 256 break; 257 case WI_RID_MAX_DATALEN:
| 356 } 357 wreq.wi_len = sizeof(*keys) / 2; 358 break; 359 case WI_RID_MAX_DATALEN:
|
258 wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN); /* TODO: frag */
| 360 wreq.wi_val[0] = htole16(ic->ic_fragthreshold);
|
259 wreq.wi_len = 1; 260 break; 261 case WI_RID_IFACE_STATS: 262 /* XXX: should be implemented in lower drivers */ 263 break; 264 case WI_RID_READ_APS:
| 361 wreq.wi_len = 1; 362 break; 363 case WI_RID_IFACE_STATS: 364 /* XXX: should be implemented in lower drivers */ 365 break; 366 case WI_RID_READ_APS:
|
265 if (ic->ic_opmode != IEEE80211_M_HOSTAP) { 266 /* 267 * Don't return results until active scan completes. 268 */ 269 if (ic->ic_state == IEEE80211_S_SCAN && 270 (ic->ic_flags & IEEE80211_F_ASCAN)) { 271 error = EINPROGRESS; 272 break; 273 } 274 } 275 i = 0; 276 ap = (void *)((char *)wreq.wi_val + sizeof(i)); 277 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 278 if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1)) 279 break; 280 memset(ap, 0, sizeof(*ap)); 281 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 282 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr); 283 ap->namelen = ic->ic_des_esslen; 284 if (ic->ic_des_esslen) 285 memcpy(ap->name, ic->ic_des_essid, 286 ic->ic_des_esslen); 287 } else { 288 IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid); 289 ap->namelen = ni->ni_esslen; 290 if (ni->ni_esslen) 291 memcpy(ap->name, ni->ni_essid, 292 ni->ni_esslen); 293 } 294 ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan); 295 ap->signal = (*ic->ic_node_getrssi)(ic, ni); 296 ap->capinfo = ni->ni_capinfo; 297 ap->interval = ni->ni_intval; 298 rs = &ni->ni_rates; 299 for (j = 0; j < rs->rs_nrates; j++) { 300 if (rs->rs_rates[j] & IEEE80211_RATE_BASIC) { 301 ap->rate = (rs->rs_rates[j] & 302 IEEE80211_RATE_VAL) * 5; /* XXX */ 303 } 304 } 305 i++; 306 ap++; 307 } 308 memcpy(wreq.wi_val, &i, sizeof(i)); 309 wreq.wi_len = (sizeof(int) + sizeof(*ap) * i) / 2;
| 367 /* 368 * Don't return results until active scan completes. 369 */ 370 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) { 371 struct wi_read_ap_args args; 372 373 args.i = 0; 374 args.ap = (void *)((char *)wreq.wi_val + sizeof(i)); 375 args.max = (void *)(&wreq + 1); 376 ieee80211_iterate_nodes(&ic->ic_scan, 377 wi_read_ap_result, &args); 378 memcpy(wreq.wi_val, &args.i, sizeof(args.i)); 379 wreq.wi_len = (sizeof(int) + 380 sizeof(struct wi_apinfo) * args.i) / 2; 381 } else 382 error = EINPROGRESS;
|
310 break; 311 case WI_RID_PRISM2:
| 383 break; 384 case WI_RID_PRISM2:
|
312 wreq.wi_val[0] = 1; /* XXX lie so SCAN_RES can give rates */
| 385 /* NB: we lie so WI_RID_SCAN_RES can include rates */ 386 wreq.wi_val[0] = 1;
|
313 wreq.wi_len = sizeof(u_int16_t) / 2; 314 break; 315 case WI_RID_SCAN_RES: /* compatibility interface */
| 387 wreq.wi_len = sizeof(u_int16_t) / 2; 388 break; 389 case WI_RID_SCAN_RES: /* compatibility interface */
|
316 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 317 ic->ic_state == IEEE80211_S_SCAN && 318 (ic->ic_flags & IEEE80211_F_ASCAN)) {
| 390 if ((ic->ic_flags & (IEEE80211_F_SCAN|IEEE80211_F_ASCAN)) == 0) { 391 struct wi_read_prism2_args args; 392 struct wi_scan_p2_hdr *p2; 393 394 /* NB: use Prism2 format so we can include rate info */ 395 p2 = (struct wi_scan_p2_hdr *)wreq.wi_val; 396 args.i = 0; 397 args.res = (void *)&p2[1]; 398 args.max = (void *)(&wreq + 1); 399 ieee80211_iterate_nodes(&ic->ic_scan, 400 wi_read_prism2_result, &args); 401 p2->wi_rsvd = 0; 402 p2->wi_reason = args.i; 403 wreq.wi_len = (sizeof(*p2) + 404 sizeof(struct wi_scan_res) * args.i) / 2; 405 } else
|
319 error = EINPROGRESS;
| 406 error = EINPROGRESS;
|
320 break; 321 } 322 /* NB: we use the Prism2 format so we can return rate info */ 323 p2 = (struct wi_scan_p2_hdr *)wreq.wi_val; 324 res = (void *)&p2[1]; 325 i = 0; 326 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 327 if ((caddr_t)(res + 1) > (caddr_t)(&wreq + 1)) 328 break; 329 res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan); 330 res->wi_noise = 0; 331 res->wi_signal = (*ic->ic_node_getrssi)(ic, ni); 332 IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid); 333 res->wi_interval = ni->ni_intval; 334 res->wi_capinfo = ni->ni_capinfo; 335 res->wi_ssid_len = ni->ni_esslen; 336 memcpy(res->wi_ssid, ni->ni_essid, IEEE80211_NWID_LEN); 337 /* NB: assumes wi_srates holds <= ni->ni_rates */ 338 memcpy(res->wi_srates, ni->ni_rates.rs_rates, 339 sizeof(res->wi_srates)); 340 if (ni->ni_rates.rs_nrates < 10) 341 res->wi_srates[ni->ni_rates.rs_nrates] = 0; 342 res->wi_rate = ni->ni_rates.rs_rates[ni->ni_txrate]; 343 res->wi_rsvd = 0; 344 res++, i++; 345 } 346 p2->wi_rsvd = 0; 347 p2->wi_reason = i; 348 wreq.wi_len = (sizeof(*p2) + sizeof(*res) * i) / 2;
| |
349 break;
| 407 break;
|
350 case WI_RID_READ_CACHE: 351 i = 0; 352 TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { 353 if (i == (WI_MAX_DATALEN/sizeof(struct wi_sigcache))-1) 354 break; 355 IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr); 356 memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc)); 357 wsc.signal = (*ic->ic_node_getrssi)(ic, ni); 358 wsc.noise = 0; 359 wsc.quality = 0; 360 memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i, 361 &wsc, sizeof(wsc)); 362 i++; 363 } 364 wreq.wi_len = sizeof(wsc) * i / 2;
| 408 case WI_RID_READ_CACHE: { 409 struct wi_read_sigcache_args args; 410 args.i = 0; 411 args.wsc = (struct wi_sigcache *) wreq.wi_val; 412 args.max = (void *)(&wreq + 1); 413 ieee80211_iterate_nodes(&ic->ic_scan, wi_read_sigcache, &args); 414 wreq.wi_len = sizeof(struct wi_sigcache) * args.i / 2;
|
365 break;
| 415 break;
|
366 case WI_RID_SCAN_APS: 367 error = EINVAL; 368 break;
| 416 }
|
369 default: 370 error = EINVAL; 371 break; 372 } 373 if (error == 0) { 374 wreq.wi_len++; 375 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 376 } 377 return error; 378} 379 380static int 381findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate) 382{ 383#define IEEERATE(_ic,_m,_i) \ 384 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) 385 int i, nrates = ic->ic_sup_rates[mode].rs_nrates; 386 for (i = 0; i < nrates; i++) 387 if (IEEERATE(ic, mode, i) == rate) 388 return i; 389 return -1; 390#undef IEEERATE 391} 392 393/* 394 * Prepare to do a user-initiated scan for AP's. If no 395 * current/default channel is setup or the current channel 396 * is invalid then pick the first available channel from 397 * the active list as the place to start the scan. 398 */ 399static int
| 417 default: 418 error = EINVAL; 419 break; 420 } 421 if (error == 0) { 422 wreq.wi_len++; 423 error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); 424 } 425 return error; 426} 427 428static int 429findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate) 430{ 431#define IEEERATE(_ic,_m,_i) \ 432 ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) 433 int i, nrates = ic->ic_sup_rates[mode].rs_nrates; 434 for (i = 0; i < nrates; i++) 435 if (IEEERATE(ic, mode, i) == rate) 436 return i; 437 return -1; 438#undef IEEERATE 439} 440 441/* 442 * Prepare to do a user-initiated scan for AP's. If no 443 * current/default channel is setup or the current channel 444 * is invalid then pick the first available channel from 445 * the active list as the place to start the scan. 446 */ 447static int
|
400ieee80211_setupscan(struct ieee80211com *ic)
| 448ieee80211_setupscan(struct ieee80211com *ic, const u_int8_t chanlist[])
|
401{
| 449{
|
402 u_char *chanlist = ic->ic_chan_active;
| |
403 int i; 404
| 450 int i; 451
|
| 452 /* 453 * XXX don't permit a scan to be started unless we 454 * know the device is ready. For the moment this means 455 * the device is marked up as this is the required to 456 * initialize the hardware. It would be better to permit 457 * scanning prior to being up but that'll require some 458 * changes to the infrastructure. 459 */ 460 if (!IS_UP(ic)) 461 return EINVAL;
|
405 if (ic->ic_ibss_chan == NULL || 406 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 407 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) 408 if (isset(chanlist, i)) { 409 ic->ic_ibss_chan = &ic->ic_channels[i]; 410 goto found; 411 } 412 return EINVAL; /* no active channels */ 413found: 414 ; 415 } 416 if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC || 417 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan))) 418 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
| 462 if (ic->ic_ibss_chan == NULL || 463 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 464 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) 465 if (isset(chanlist, i)) { 466 ic->ic_ibss_chan = &ic->ic_channels[i]; 467 goto found; 468 } 469 return EINVAL; /* no active channels */ 470found: 471 ; 472 } 473 if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC || 474 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan))) 475 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
|
| 476 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
|
419 /*
| 477 /*
|
420 * XXX don't permit a scan to be started unless we 421 * know the device is ready. For the moment this means 422 * the device is marked up as this is the required to 423 * initialize the hardware. It would be better to permit 424 * scanning prior to being up but that'll require some 425 * changes to the infrastructure.
| 478 * We force the state to INIT before calling ieee80211_new_state 479 * to get ieee80211_begin_scan called. We really want to scan w/o 480 * altering the current state but that's not possible right now.
|
426 */
| 481 */
|
427 return (ic->ic_if.if_flags & IFF_UP) ? 0 : ENETRESET;
| 482 /* XXX handle proberequest case */ 483 ic->ic_state = IEEE80211_S_INIT; /* XXX bypass state machine */ 484 return 0;
|
428} 429 430int
| 485} 486 487int
|
431ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data)
| 488ieee80211_cfgset(struct ieee80211com *ic, u_long cmd, caddr_t data)
|
432{
| 489{
|
433 struct ieee80211com *ic = (void *)ifp;
| 490 struct ifnet *ifp = ic->ic_ifp;
|
434 int i, j, len, error, rate; 435 struct ifreq *ifr = (struct ifreq *)data; 436 struct wi_ltv_keys *keys; 437 struct wi_req wreq; 438 u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)]; 439 440 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 441 if (error) 442 return error; 443 len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0; 444 switch (wreq.wi_type) { 445 case WI_RID_SERIALNO: 446 case WI_RID_NODENAME: 447 return EPERM; 448 case WI_RID_CURRENT_SSID: 449 return EPERM; 450 case WI_RID_OWN_SSID: 451 case WI_RID_DESIRED_SSID: 452 if (le16toh(wreq.wi_val[0]) * 2 > len || 453 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) { 454 error = ENOSPC; 455 break; 456 } 457 memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid)); 458 ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2; 459 memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen); 460 error = ENETRESET; 461 break; 462 case WI_RID_CURRENT_BSSID: 463 return EPERM; 464 case WI_RID_OWN_CHNL: 465 if (len != 2) 466 return EINVAL; 467 i = le16toh(wreq.wi_val[0]); 468 if (i < 0 || 469 i > IEEE80211_CHAN_MAX || 470 isclr(ic->ic_chan_active, i)) 471 return EINVAL; 472 ic->ic_ibss_chan = &ic->ic_channels[i];
| 491 int i, j, len, error, rate; 492 struct ifreq *ifr = (struct ifreq *)data; 493 struct wi_ltv_keys *keys; 494 struct wi_req wreq; 495 u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)]; 496 497 error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); 498 if (error) 499 return error; 500 len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0; 501 switch (wreq.wi_type) { 502 case WI_RID_SERIALNO: 503 case WI_RID_NODENAME: 504 return EPERM; 505 case WI_RID_CURRENT_SSID: 506 return EPERM; 507 case WI_RID_OWN_SSID: 508 case WI_RID_DESIRED_SSID: 509 if (le16toh(wreq.wi_val[0]) * 2 > len || 510 le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) { 511 error = ENOSPC; 512 break; 513 } 514 memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid)); 515 ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2; 516 memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen); 517 error = ENETRESET; 518 break; 519 case WI_RID_CURRENT_BSSID: 520 return EPERM; 521 case WI_RID_OWN_CHNL: 522 if (len != 2) 523 return EINVAL; 524 i = le16toh(wreq.wi_val[0]); 525 if (i < 0 || 526 i > IEEE80211_CHAN_MAX || 527 isclr(ic->ic_chan_active, i)) 528 return EINVAL; 529 ic->ic_ibss_chan = &ic->ic_channels[i];
|
473 if (ic->ic_flags & IEEE80211_F_SIBSS)
| 530 if (ic->ic_opmode == IEEE80211_M_MONITOR) 531 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 532 else
|
474 error = ENETRESET; 475 break; 476 case WI_RID_CURRENT_CHAN: 477 return EPERM; 478 case WI_RID_COMMS_QUALITY: 479 return EPERM; 480 case WI_RID_PROMISC: 481 if (len != 2) 482 return EINVAL; 483 if (ifp->if_flags & IFF_PROMISC) { 484 if (wreq.wi_val[0] == 0) { 485 ifp->if_flags &= ~IFF_PROMISC; 486 error = ENETRESET; 487 } 488 } else { 489 if (wreq.wi_val[0] != 0) { 490 ifp->if_flags |= IFF_PROMISC; 491 error = ENETRESET; 492 } 493 } 494 break; 495 case WI_RID_PORTTYPE: 496 if (len != 2) 497 return EINVAL; 498 switch (le16toh(wreq.wi_val[0])) { 499 case IEEE80211_M_STA: 500 break; 501 case IEEE80211_M_IBSS: 502 if (!(ic->ic_caps & IEEE80211_C_IBSS)) 503 return EINVAL; 504 break; 505 case IEEE80211_M_AHDEMO: 506 if (ic->ic_phytype != IEEE80211_T_DS || 507 !(ic->ic_caps & IEEE80211_C_AHDEMO)) 508 return EINVAL; 509 break; 510 case IEEE80211_M_HOSTAP: 511 if (!(ic->ic_caps & IEEE80211_C_HOSTAP)) 512 return EINVAL; 513 break; 514 default: 515 return EINVAL; 516 } 517 if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) { 518 ic->ic_opmode = le16toh(wreq.wi_val[0]);
| 533 error = ENETRESET; 534 break; 535 case WI_RID_CURRENT_CHAN: 536 return EPERM; 537 case WI_RID_COMMS_QUALITY: 538 return EPERM; 539 case WI_RID_PROMISC: 540 if (len != 2) 541 return EINVAL; 542 if (ifp->if_flags & IFF_PROMISC) { 543 if (wreq.wi_val[0] == 0) { 544 ifp->if_flags &= ~IFF_PROMISC; 545 error = ENETRESET; 546 } 547 } else { 548 if (wreq.wi_val[0] != 0) { 549 ifp->if_flags |= IFF_PROMISC; 550 error = ENETRESET; 551 } 552 } 553 break; 554 case WI_RID_PORTTYPE: 555 if (len != 2) 556 return EINVAL; 557 switch (le16toh(wreq.wi_val[0])) { 558 case IEEE80211_M_STA: 559 break; 560 case IEEE80211_M_IBSS: 561 if (!(ic->ic_caps & IEEE80211_C_IBSS)) 562 return EINVAL; 563 break; 564 case IEEE80211_M_AHDEMO: 565 if (ic->ic_phytype != IEEE80211_T_DS || 566 !(ic->ic_caps & IEEE80211_C_AHDEMO)) 567 return EINVAL; 568 break; 569 case IEEE80211_M_HOSTAP: 570 if (!(ic->ic_caps & IEEE80211_C_HOSTAP)) 571 return EINVAL; 572 break; 573 default: 574 return EINVAL; 575 } 576 if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) { 577 ic->ic_opmode = le16toh(wreq.wi_val[0]);
|
519 error = ENETRESET;
| 578 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
520 } 521 break; 522#if 0 523 case WI_RID_MAC_NODE: 524 if (len != IEEE80211_ADDR_LEN) 525 return EINVAL; 526 IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val); 527 /* if_init will copy lladdr into ic_myaddr */ 528 error = ENETRESET; 529 break; 530#endif 531 case WI_RID_TX_RATE: 532 if (len != 2) 533 return EINVAL; 534 if (wreq.wi_val[0] == 0) { 535 /* auto */ 536 ic->ic_fixed_rate = -1; 537 break; 538 } 539 rate = 2 * le16toh(wreq.wi_val[0]); 540 if (ic->ic_curmode == IEEE80211_MODE_AUTO) { 541 /* 542 * In autoselect mode search for the rate. We take 543 * the first instance which may not be right, but we 544 * are limited by the interface. Note that we also 545 * lock the mode to insure the rate is meaningful 546 * when it is used. 547 */ 548 for (j = IEEE80211_MODE_11A; 549 j < IEEE80211_MODE_MAX; j++) { 550 if ((ic->ic_modecaps & (1<<j)) == 0) 551 continue; 552 i = findrate(ic, j, rate); 553 if (i != -1) { 554 /* lock mode too */ 555 ic->ic_curmode = j; 556 goto setrate; 557 } 558 } 559 } else { 560 i = findrate(ic, ic->ic_curmode, rate); 561 if (i != -1) 562 goto setrate; 563 } 564 return EINVAL; 565 setrate: 566 ic->ic_fixed_rate = i;
| 579 } 580 break; 581#if 0 582 case WI_RID_MAC_NODE: 583 if (len != IEEE80211_ADDR_LEN) 584 return EINVAL; 585 IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val); 586 /* if_init will copy lladdr into ic_myaddr */ 587 error = ENETRESET; 588 break; 589#endif 590 case WI_RID_TX_RATE: 591 if (len != 2) 592 return EINVAL; 593 if (wreq.wi_val[0] == 0) { 594 /* auto */ 595 ic->ic_fixed_rate = -1; 596 break; 597 } 598 rate = 2 * le16toh(wreq.wi_val[0]); 599 if (ic->ic_curmode == IEEE80211_MODE_AUTO) { 600 /* 601 * In autoselect mode search for the rate. We take 602 * the first instance which may not be right, but we 603 * are limited by the interface. Note that we also 604 * lock the mode to insure the rate is meaningful 605 * when it is used. 606 */ 607 for (j = IEEE80211_MODE_11A; 608 j < IEEE80211_MODE_MAX; j++) { 609 if ((ic->ic_modecaps & (1<<j)) == 0) 610 continue; 611 i = findrate(ic, j, rate); 612 if (i != -1) { 613 /* lock mode too */ 614 ic->ic_curmode = j; 615 goto setrate; 616 } 617 } 618 } else { 619 i = findrate(ic, ic->ic_curmode, rate); 620 if (i != -1) 621 goto setrate; 622 } 623 return EINVAL; 624 setrate: 625 ic->ic_fixed_rate = i;
|
567 error = ENETRESET;
| 626 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
568 break; 569 case WI_RID_CUR_TX_RATE: 570 return EPERM; 571 case WI_RID_RTS_THRESH: 572 if (len != 2) 573 return EINVAL; 574 if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN) 575 return EINVAL; /* TODO: RTS */ 576 break; 577 case WI_RID_CREATE_IBSS: 578 if (len != 2) 579 return EINVAL; 580 if (wreq.wi_val[0] != 0) { 581 if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) 582 return EINVAL; 583 if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { 584 ic->ic_flags |= IEEE80211_F_IBSSON; 585 if (ic->ic_opmode == IEEE80211_M_IBSS && 586 ic->ic_state == IEEE80211_S_SCAN)
| 627 break; 628 case WI_RID_CUR_TX_RATE: 629 return EPERM; 630 case WI_RID_RTS_THRESH: 631 if (len != 2) 632 return EINVAL; 633 if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN) 634 return EINVAL; /* TODO: RTS */ 635 break; 636 case WI_RID_CREATE_IBSS: 637 if (len != 2) 638 return EINVAL; 639 if (wreq.wi_val[0] != 0) { 640 if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) 641 return EINVAL; 642 if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { 643 ic->ic_flags |= IEEE80211_F_IBSSON; 644 if (ic->ic_opmode == IEEE80211_M_IBSS && 645 ic->ic_state == IEEE80211_S_SCAN)
|
587 error = ENETRESET;
| 646 error = IS_UP_AUTO(ic) ? ENETRESET : 0;
|
588 } 589 } else { 590 if (ic->ic_flags & IEEE80211_F_IBSSON) { 591 ic->ic_flags &= ~IEEE80211_F_IBSSON; 592 if (ic->ic_flags & IEEE80211_F_SIBSS) { 593 ic->ic_flags &= ~IEEE80211_F_SIBSS;
| 647 } 648 } else { 649 if (ic->ic_flags & IEEE80211_F_IBSSON) { 650 ic->ic_flags &= ~IEEE80211_F_IBSSON; 651 if (ic->ic_flags & IEEE80211_F_SIBSS) { 652 ic->ic_flags &= ~IEEE80211_F_SIBSS;
|
594 error = ENETRESET;
| 653 error = IS_UP_AUTO(ic) ? ENETRESET : 0;
|
595 } 596 } 597 } 598 break; 599 case WI_RID_MICROWAVE_OVEN: 600 if (len != 2) 601 return EINVAL; 602 if (wreq.wi_val[0] != 0) 603 return EINVAL; /* not supported */ 604 break; 605 case WI_RID_ROAMING_MODE: 606 if (len != 2) 607 return EINVAL;
| 654 } 655 } 656 } 657 break; 658 case WI_RID_MICROWAVE_OVEN: 659 if (len != 2) 660 return EINVAL; 661 if (wreq.wi_val[0] != 0) 662 return EINVAL; /* not supported */ 663 break; 664 case WI_RID_ROAMING_MODE: 665 if (len != 2) 666 return EINVAL;
|
608 if (le16toh(wreq.wi_val[0]) != 1)
| 667 i = le16toh(wreq.wi_val[0]); 668 if (i > IEEE80211_ROAMING_MANUAL)
|
609 return EINVAL; /* not supported */
| 669 return EINVAL; /* not supported */
|
| 670 ic->ic_roaming = i;
|
610 break; 611 case WI_RID_SYSTEM_SCALE: 612 if (len != 2) 613 return EINVAL; 614 if (le16toh(wreq.wi_val[0]) != 1) 615 return EINVAL; /* not supported */ 616 break; 617 case WI_RID_PM_ENABLED: 618 if (len != 2) 619 return EINVAL; 620 if (wreq.wi_val[0] != 0) { 621 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 622 return EINVAL; 623 if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 624 ic->ic_flags |= IEEE80211_F_PMGTON;
| 671 break; 672 case WI_RID_SYSTEM_SCALE: 673 if (len != 2) 674 return EINVAL; 675 if (le16toh(wreq.wi_val[0]) != 1) 676 return EINVAL; /* not supported */ 677 break; 678 case WI_RID_PM_ENABLED: 679 if (len != 2) 680 return EINVAL; 681 if (wreq.wi_val[0] != 0) { 682 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 683 return EINVAL; 684 if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 685 ic->ic_flags |= IEEE80211_F_PMGTON;
|
625 error = ENETRESET;
| 686 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
626 } 627 } else { 628 if (ic->ic_flags & IEEE80211_F_PMGTON) { 629 ic->ic_flags &= ~IEEE80211_F_PMGTON;
| 687 } 688 } else { 689 if (ic->ic_flags & IEEE80211_F_PMGTON) { 690 ic->ic_flags &= ~IEEE80211_F_PMGTON;
|
630 error = ENETRESET;
| 691 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
631 } 632 } 633 break; 634 case WI_RID_MAX_SLEEP: 635 if (len != 2) 636 return EINVAL; 637 ic->ic_lintval = le16toh(wreq.wi_val[0]); 638 if (ic->ic_flags & IEEE80211_F_PMGTON)
| 692 } 693 } 694 break; 695 case WI_RID_MAX_SLEEP: 696 if (len != 2) 697 return EINVAL; 698 ic->ic_lintval = le16toh(wreq.wi_val[0]); 699 if (ic->ic_flags & IEEE80211_F_PMGTON)
|
639 error = ENETRESET;
| 700 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
640 break; 641 case WI_RID_CUR_BEACON_INT: 642 return EPERM; 643 case WI_RID_WEP_AVAIL: 644 return EPERM; 645 case WI_RID_CNFAUTHMODE: 646 if (len != 2) 647 return EINVAL;
| 701 break; 702 case WI_RID_CUR_BEACON_INT: 703 return EPERM; 704 case WI_RID_WEP_AVAIL: 705 return EPERM; 706 case WI_RID_CNFAUTHMODE: 707 if (len != 2) 708 return EINVAL;
|
648 if (le16toh(wreq.wi_val[0]) != 1) 649 return EINVAL; /* TODO: shared key auth */
| 709 i = le16toh(wreq.wi_val[0]); 710 if (i > IEEE80211_AUTH_WPA) 711 return EINVAL; 712 ic->ic_bss->ni_authmode = i; /* XXX ENETRESET? */ 713 error = ENETRESET;
|
650 break; 651 case WI_RID_ENCRYPTION: 652 if (len != 2) 653 return EINVAL; 654 if (wreq.wi_val[0] != 0) { 655 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 656 return EINVAL;
| 714 break; 715 case WI_RID_ENCRYPTION: 716 if (len != 2) 717 return EINVAL; 718 if (wreq.wi_val[0] != 0) { 719 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 720 return EINVAL;
|
657 if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) { 658 ic->ic_flags |= IEEE80211_F_WEPON;
| 721 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) { 722 ic->ic_flags |= IEEE80211_F_PRIVACY;
|
659 error = ENETRESET; 660 } 661 } else {
| 723 error = ENETRESET; 724 } 725 } else {
|
662 if (ic->ic_flags & IEEE80211_F_WEPON) { 663 ic->ic_flags &= ~IEEE80211_F_WEPON;
| 726 if (ic->ic_flags & IEEE80211_F_PRIVACY) { 727 ic->ic_flags &= ~IEEE80211_F_PRIVACY;
|
664 error = ENETRESET; 665 } 666 } 667 break; 668 case WI_RID_TX_CRYPT_KEY: 669 if (len != 2) 670 return EINVAL; 671 i = le16toh(wreq.wi_val[0]); 672 if (i >= IEEE80211_WEP_NKID) 673 return EINVAL;
| 728 error = ENETRESET; 729 } 730 } 731 break; 732 case WI_RID_TX_CRYPT_KEY: 733 if (len != 2) 734 return EINVAL; 735 i = le16toh(wreq.wi_val[0]); 736 if (i >= IEEE80211_WEP_NKID) 737 return EINVAL;
|
674 ic->ic_wep_txkey = i;
| 738 ic->ic_def_txkey = i; 739 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
675 break; 676 case WI_RID_DEFLT_CRYPT_KEYS: 677 if (len != sizeof(struct wi_ltv_keys)) 678 return EINVAL; 679 keys = (struct wi_ltv_keys *)&wreq; 680 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 681 len = le16toh(keys->wi_keys[i].wi_keylen); 682 if (len != 0 && len < IEEE80211_WEP_KEYLEN) 683 return EINVAL;
| 740 break; 741 case WI_RID_DEFLT_CRYPT_KEYS: 742 if (len != sizeof(struct wi_ltv_keys)) 743 return EINVAL; 744 keys = (struct wi_ltv_keys *)&wreq; 745 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 746 len = le16toh(keys->wi_keys[i].wi_keylen); 747 if (len != 0 && len < IEEE80211_WEP_KEYLEN) 748 return EINVAL;
|
684 if (len > sizeof(ic->ic_nw_keys[i].wk_key))
| 749 if (len > IEEE80211_KEYBUF_SIZE)
|
685 return EINVAL; 686 }
| 750 return EINVAL; 751 }
|
687 memset(ic->ic_nw_keys, 0, sizeof(ic->ic_nw_keys));
| |
688 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
| 752 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
|
| 753 struct ieee80211_key *k = &ic->ic_nw_keys[i]; 754
|
689 len = le16toh(keys->wi_keys[i].wi_keylen);
| 755 len = le16toh(keys->wi_keys[i].wi_keylen);
|
690 ic->ic_nw_keys[i].wk_len = len; 691 memcpy(ic->ic_nw_keys[i].wk_key, 692 keys->wi_keys[i].wi_keydat, len);
| 756 k->wk_keylen = len; 757 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 758 memset(k->wk_key, 0, sizeof(k->wk_key)); 759 memcpy(k->wk_key, keys->wi_keys[i].wi_keydat, len); 760#if 0 761 k->wk_type = IEEE80211_CIPHER_WEP; 762#endif
|
693 } 694 error = ENETRESET; 695 break; 696 case WI_RID_MAX_DATALEN: 697 if (len != 2) 698 return EINVAL; 699 len = le16toh(wreq.wi_val[0]); 700 if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN) 701 return EINVAL;
| 763 } 764 error = ENETRESET; 765 break; 766 case WI_RID_MAX_DATALEN: 767 if (len != 2) 768 return EINVAL; 769 len = le16toh(wreq.wi_val[0]); 770 if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN) 771 return EINVAL;
|
702 if (len != IEEE80211_MAX_LEN) 703 return EINVAL; /* TODO: fragment */
| |
704 ic->ic_fragthreshold = len;
| 772 ic->ic_fragthreshold = len;
|
705 error = ENETRESET;
| 773 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0;
|
706 break; 707 case WI_RID_IFACE_STATS: 708 error = EPERM; 709 break; 710 case WI_RID_SCAN_REQ: /* XXX wicontrol */ 711 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 712 break;
| 774 break; 775 case WI_RID_IFACE_STATS: 776 error = EPERM; 777 break; 778 case WI_RID_SCAN_REQ: /* XXX wicontrol */ 779 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 780 break;
|
713 error = ieee80211_setupscan(ic);
| 781 error = ieee80211_setupscan(ic, ic->ic_chan_avail);
|
714 if (error == 0) 715 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 716 break; 717 case WI_RID_SCAN_APS: 718 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 719 break; 720 len--; /* XXX: tx rate? */ 721 /* FALLTHRU */ 722 case WI_RID_CHANNEL_LIST: 723 memset(chanlist, 0, sizeof(chanlist)); 724 /* 725 * Since channel 0 is not available for DS, channel 1 726 * is assigned to LSB on WaveLAN. 727 */ 728 if (ic->ic_phytype == IEEE80211_T_DS) 729 i = 1; 730 else 731 i = 0; 732 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 733 if ((j / 8) >= len) 734 break; 735 if (isclr((u_int8_t *)wreq.wi_val, j)) 736 continue; 737 if (isclr(ic->ic_chan_active, i)) { 738 if (wreq.wi_type != WI_RID_CHANNEL_LIST) 739 continue; 740 if (isclr(ic->ic_chan_avail, i)) 741 return EPERM; 742 } 743 setbit(chanlist, i); 744 }
| 782 if (error == 0) 783 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 784 break; 785 case WI_RID_SCAN_APS: 786 if (ic->ic_opmode == IEEE80211_M_HOSTAP) 787 break; 788 len--; /* XXX: tx rate? */ 789 /* FALLTHRU */ 790 case WI_RID_CHANNEL_LIST: 791 memset(chanlist, 0, sizeof(chanlist)); 792 /* 793 * Since channel 0 is not available for DS, channel 1 794 * is assigned to LSB on WaveLAN. 795 */ 796 if (ic->ic_phytype == IEEE80211_T_DS) 797 i = 1; 798 else 799 i = 0; 800 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 801 if ((j / 8) >= len) 802 break; 803 if (isclr((u_int8_t *)wreq.wi_val, j)) 804 continue; 805 if (isclr(ic->ic_chan_active, i)) { 806 if (wreq.wi_type != WI_RID_CHANNEL_LIST) 807 continue; 808 if (isclr(ic->ic_chan_avail, i)) 809 return EPERM; 810 } 811 setbit(chanlist, i); 812 }
|
745 memcpy(ic->ic_chan_active, chanlist, 746 sizeof(ic->ic_chan_active)); 747 error = ieee80211_setupscan(ic);
| 813 error = ieee80211_setupscan(ic, chanlist);
|
748 if (wreq.wi_type == WI_RID_CHANNEL_LIST) { 749 /* NB: ignore error from ieee80211_setupscan */ 750 error = ENETRESET; 751 } else if (error == 0) 752 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 753 break; 754 default: 755 error = EINVAL; 756 break; 757 }
| 814 if (wreq.wi_type == WI_RID_CHANNEL_LIST) { 815 /* NB: ignore error from ieee80211_setupscan */ 816 error = ENETRESET; 817 } else if (error == 0) 818 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 819 break; 820 default: 821 error = EINVAL; 822 break; 823 }
|
| 824 if (error == ENETRESET && !IS_UP_AUTO(ic)) 825 error = 0;
|
758 return error; 759} 760
| 826 return error; 827} 828
|
761int 762ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
| 829static struct ieee80211_channel * 830getcurchan(struct ieee80211com *ic)
|
763{
| 831{
|
764 struct ieee80211com *ic = (void *)ifp;
| 832 switch (ic->ic_state) { 833 case IEEE80211_S_INIT: 834 case IEEE80211_S_SCAN: 835 return ic->ic_des_chan; 836 default: 837 return ic->ic_ibss_chan; 838 } 839} 840 841static int 842cap2cipher(int flag) 843{ 844 switch (flag) { 845 case IEEE80211_C_WEP: return IEEE80211_CIPHER_WEP; 846 case IEEE80211_C_AES: return IEEE80211_CIPHER_AES_OCB; 847 case IEEE80211_C_AES_CCM: return IEEE80211_CIPHER_AES_CCM; 848 case IEEE80211_C_CKIP: return IEEE80211_CIPHER_CKIP; 849 case IEEE80211_C_TKIP: return IEEE80211_CIPHER_TKIP; 850 } 851 return -1; 852} 853 854static int 855ieee80211_ioctl_getkey(struct ieee80211com *ic, struct ieee80211req *ireq) 856{ 857 struct ieee80211_node *ni; 858 struct ieee80211req_key ik; 859 struct ieee80211_key *wk; 860 const struct ieee80211_cipher *cip; 861 u_int kid; 862 int error; 863 864 if (ireq->i_len != sizeof(ik)) 865 return EINVAL; 866 error = copyin(ireq->i_data, &ik, sizeof(ik)); 867 if (error) 868 return error; 869 kid = ik.ik_keyix; 870 if (kid == IEEE80211_KEYIX_NONE) { 871 if (ic->ic_sta == NULL) 872 return EINVAL; 873 ni = ieee80211_find_node(ic->ic_sta, ik.ik_macaddr); 874 if (ni == NULL) 875 return EINVAL; /* XXX */ 876 wk = &ni->ni_ucastkey; 877 } else { 878 if (kid >= IEEE80211_WEP_NKID) 879 return EINVAL; 880 wk = &ic->ic_nw_keys[kid]; 881 IEEE80211_ADDR_COPY(&ik.ik_macaddr, ic->ic_bss->ni_macaddr); 882 ni = NULL; 883 } 884 cip = wk->wk_cipher; 885 ik.ik_type = cip->ic_cipher; 886 ik.ik_keylen = wk->wk_keylen; 887 ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); 888 if (wk->wk_keyix == ic->ic_def_txkey) 889 ik.ik_flags |= IEEE80211_KEY_DEFAULT; 890 if (suser(curthread) == 0) { 891 /* NB: only root can read key data */ 892 ik.ik_keyrsc = wk->wk_keyrsc; 893 ik.ik_keytsc = wk->wk_keytsc; 894 memcpy(ik.ik_keydata, wk->wk_key, wk->wk_keylen); 895 if (cip->ic_cipher == IEEE80211_CIPHER_TKIP) { 896 memcpy(ik.ik_keydata+wk->wk_keylen, 897 wk->wk_key + IEEE80211_KEYBUF_SIZE, 898 IEEE80211_MICBUF_SIZE); 899 ik.ik_keylen += IEEE80211_MICBUF_SIZE; 900 } 901 } else { 902 ik.ik_keyrsc = 0; 903 ik.ik_keytsc = 0; 904 memset(ik.ik_keydata, 0, sizeof(ik.ik_keydata)); 905 } 906 if (ni != NULL) 907 ieee80211_free_node(ni); 908 return copyout(&ik, ireq->i_data, sizeof(ik)); 909} 910 911static int 912ieee80211_ioctl_getchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 913{ 914 915 if (sizeof(ic->ic_chan_active) > ireq->i_len) 916 ireq->i_len = sizeof(ic->ic_chan_active); 917 return copyout(&ic->ic_chan_active, ireq->i_data, ireq->i_len); 918} 919 920static int 921ieee80211_ioctl_getchaninfo(struct ieee80211com *ic, struct ieee80211req *ireq) 922{ 923 struct ieee80211req_chaninfo chans; /* XXX off stack? */ 924 int i, space; 925 926 /* 927 * Since channel 0 is not available for DS, channel 1 928 * is assigned to LSB on WaveLAN. 929 */ 930 if (ic->ic_phytype == IEEE80211_T_DS) 931 i = 1; 932 else 933 i = 0; 934 memset(&chans, 0, sizeof(chans)); 935 for (; i <= IEEE80211_CHAN_MAX; i++) 936 if (isset(ic->ic_chan_avail, i)) { 937 struct ieee80211_channel *c = &ic->ic_channels[i]; 938 chans.ic_chans[chans.ic_nchans].ic_freq = c->ic_freq; 939 chans.ic_chans[chans.ic_nchans].ic_flags = c->ic_flags; 940 chans.ic_nchans++; 941 } 942 space = __offsetof(struct ieee80211req_chaninfo, 943 ic_chans[chans.ic_nchans]); 944 if (space > ireq->i_len) 945 space = ireq->i_len; 946 return copyout(&chans, ireq->i_data, space); 947} 948 949static int 950ieee80211_ioctl_getwpaie(struct ieee80211com *ic, struct ieee80211req *ireq) 951{ 952 struct ieee80211_node *ni; 953 struct ieee80211req_wpaie wpaie; 954 int error; 955 956 if (ireq->i_len < IEEE80211_ADDR_LEN) 957 return EINVAL; 958 error = copyin(ireq->i_data, wpaie.wpa_macaddr, IEEE80211_ADDR_LEN); 959 if (error != 0) 960 return error; 961 if (ic->ic_sta == NULL) 962 return EINVAL; 963 ni = ieee80211_find_node(ic->ic_sta, wpaie.wpa_macaddr); 964 if (ni == NULL) 965 return EINVAL; /* XXX */ 966 memset(wpaie.wpa_ie, 0, sizeof(wpaie.wpa_ie)); 967 if (ni->ni_wpa_ie != NULL) { 968 int ielen = ni->ni_wpa_ie[1] + 2; 969 if (ielen > sizeof(wpaie.wpa_ie)) 970 ielen = sizeof(wpaie.wpa_ie); 971 memcpy(wpaie.wpa_ie, ni->ni_wpa_ie, ielen); 972 } 973 ieee80211_free_node(ni); 974 if (ireq->i_len > sizeof(wpaie)) 975 ireq->i_len = sizeof(wpaie); 976 return copyout(&wpaie, ireq->i_data, ireq->i_len); 977} 978 979static int 980ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq) 981{ 982 struct ieee80211_node *ni; 983 u_int8_t macaddr[IEEE80211_ADDR_LEN]; 984 const int off = __offsetof(struct ieee80211req_sta_stats, is_stats); 985 int error; 986 987 if (ireq->i_len < off) 988 return EINVAL; 989 error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); 990 if (error != 0) 991 return error; 992 if (ic->ic_sta == NULL) 993 return EINVAL; 994 ni = ieee80211_find_node(ic->ic_sta, macaddr); 995 if (ni == NULL) 996 return EINVAL; /* XXX */ 997 if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) 998 ireq->i_len = sizeof(struct ieee80211req_sta_stats); 999 /* NB: copy out only the statistics */ 1000 error = copyout(&ni->ni_stats, (u_int8_t *) ireq->i_data + off, 1001 ireq->i_len - off); 1002 ieee80211_free_node(ni); 1003 return error; 1004} 1005 1006static void 1007get_scan_result(struct ieee80211req_scan_result *sr, 1008 const struct ieee80211_node *ni) 1009{ 1010 struct ieee80211com *ic = ni->ni_ic; 1011 1012 memset(sr, 0, sizeof(*sr)); 1013 sr->isr_ssid_len = ni->ni_esslen; 1014 if (ni->ni_wpa_ie != NULL) 1015 sr->isr_ie_len += 2+ni->ni_wpa_ie[1]; 1016 if (ni->ni_wme_ie != NULL) 1017 sr->isr_ie_len += 2+ni->ni_wme_ie[1]; 1018 sr->isr_len = sizeof(*sr) + sr->isr_ssid_len + sr->isr_ie_len; 1019 sr->isr_len = roundup(sr->isr_len, sizeof(u_int32_t)); 1020 if (ni->ni_chan != IEEE80211_CHAN_ANYC) { 1021 sr->isr_freq = ni->ni_chan->ic_freq; 1022 sr->isr_flags = ni->ni_chan->ic_flags; 1023 } 1024 sr->isr_rssi = ic->ic_node_getrssi(ni); 1025 sr->isr_intval = ni->ni_intval; 1026 sr->isr_capinfo = ni->ni_capinfo; 1027 sr->isr_erp = ni->ni_erp; 1028 IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid); 1029 sr->isr_nrates = ni->ni_rates.rs_nrates; 1030 if (sr->isr_nrates > 15) 1031 sr->isr_nrates = 15; 1032 memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates); 1033} 1034 1035static int 1036ieee80211_ioctl_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq) 1037{ 1038 union { 1039 struct ieee80211req_scan_result res; 1040 char data[512]; /* XXX shrink? */ 1041 } u; 1042 struct ieee80211req_scan_result *sr = &u.res; 1043 struct ieee80211_node_table *nt; 1044 struct ieee80211_node *ni; 1045 int error, space; 1046 u_int8_t *p, *cp; 1047 1048 p = ireq->i_data; 1049 space = ireq->i_len; 1050 error = 0; 1051 /* XXX locking */ 1052 nt = &ic->ic_scan; 1053 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 1054 /* NB: skip pre-scan node state */ 1055 if (ni->ni_chan == IEEE80211_CHAN_ANYC) 1056 continue; 1057 get_scan_result(sr, ni); 1058 if (sr->isr_len > sizeof(u)) 1059 continue; /* XXX */ 1060 if (space < sr->isr_len) 1061 break; 1062 cp = (u_int8_t *)(sr+1); 1063 memcpy(cp, ni->ni_essid, ni->ni_esslen); 1064 cp += ni->ni_esslen; 1065 if (ni->ni_wpa_ie != NULL) { 1066 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1067 cp += 2+ni->ni_wpa_ie[1]; 1068 } 1069 if (ni->ni_wme_ie != NULL) { 1070 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1071 cp += 2+ni->ni_wme_ie[1]; 1072 } 1073 error = copyout(sr, p, sr->isr_len); 1074 if (error) 1075 break; 1076 p += sr->isr_len; 1077 space -= sr->isr_len; 1078 } 1079 ireq->i_len -= space; 1080 return error; 1081} 1082 1083static void 1084get_sta_info(struct ieee80211req_sta_info *si, const struct ieee80211_node *ni) 1085{ 1086 struct ieee80211com *ic = ni->ni_ic; 1087 1088 si->isi_ie_len = 0; 1089 if (ni->ni_wpa_ie != NULL) 1090 si->isi_ie_len += 2+ni->ni_wpa_ie[1]; 1091 if (ni->ni_wme_ie != NULL) 1092 si->isi_ie_len += 2+ni->ni_wme_ie[1]; 1093 si->isi_len = sizeof(*si) + si->isi_ie_len, sizeof(u_int32_t); 1094 si->isi_len = roundup(si->isi_len, sizeof(u_int32_t)); 1095 si->isi_freq = ni->ni_chan->ic_freq; 1096 si->isi_flags = ni->ni_chan->ic_flags; 1097 si->isi_state = ni->ni_flags; 1098 si->isi_authmode = ni->ni_authmode; 1099 si->isi_rssi = ic->ic_node_getrssi(ni); 1100 si->isi_capinfo = ni->ni_capinfo; 1101 si->isi_erp = ni->ni_erp; 1102 IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); 1103 si->isi_nrates = ni->ni_rates.rs_nrates; 1104 if (si->isi_nrates > 15) 1105 si->isi_nrates = 15; 1106 memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates); 1107 si->isi_txrate = ni->ni_txrate; 1108 si->isi_associd = ni->ni_associd; 1109 si->isi_txpower = ni->ni_txpower; 1110 si->isi_vlan = ni->ni_vlan; 1111 if (ni->ni_flags & IEEE80211_NODE_QOS) { 1112 memcpy(si->isi_txseqs, ni->ni_txseqs, sizeof(ni->ni_txseqs)); 1113 memcpy(si->isi_rxseqs, ni->ni_rxseqs, sizeof(ni->ni_rxseqs)); 1114 } else { 1115 si->isi_txseqs[0] = ni->ni_txseqs[0]; 1116 si->isi_rxseqs[0] = ni->ni_rxseqs[0]; 1117 } 1118 if (ic->ic_opmode == IEEE80211_M_IBSS || ni->ni_associd != 0) 1119 si->isi_inact = ic->ic_inact_run; 1120 else if (ieee80211_node_is_authorized(ni)) 1121 si->isi_inact = ic->ic_inact_auth; 1122 else 1123 si->isi_inact = ic->ic_inact_init; 1124 si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT; 1125} 1126 1127static int 1128ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) 1129{ 1130 union { 1131 struct ieee80211req_sta_info info; 1132 char data[512]; /* XXX shrink? */ 1133 } u; 1134 struct ieee80211req_sta_info *si = &u.info; 1135 struct ieee80211_node_table *nt; 1136 struct ieee80211_node *ni; 1137 int error, space; 1138 u_int8_t *p, *cp; 1139 1140 nt = ic->ic_sta; 1141 if (nt == NULL) 1142 return EINVAL; 1143 p = ireq->i_data; 1144 space = ireq->i_len; 1145 error = 0; 1146 /* XXX locking */ 1147 TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { 1148 get_sta_info(si, ni); 1149 if (si->isi_len > sizeof(u)) 1150 continue; /* XXX */ 1151 if (space < si->isi_len) 1152 break; 1153 cp = (u_int8_t *)(si+1); 1154 if (ni->ni_wpa_ie != NULL) { 1155 memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]); 1156 cp += 2+ni->ni_wpa_ie[1]; 1157 } 1158 if (ni->ni_wme_ie != NULL) { 1159 memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]); 1160 cp += 2+ni->ni_wme_ie[1]; 1161 } 1162 error = copyout(si, p, si->isi_len); 1163 if (error) 1164 break; 1165 p += si->isi_len; 1166 space -= si->isi_len; 1167 } 1168 ireq->i_len -= space; 1169 return error; 1170} 1171 1172static int 1173ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 1174{ 1175 struct ieee80211_node *ni; 1176 struct ieee80211req_sta_txpow txpow; 1177 int error; 1178 1179 if (ireq->i_len != sizeof(txpow)) 1180 return EINVAL; 1181 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1182 if (error != 0) 1183 return error; 1184 if (ic->ic_sta == NULL) 1185 return EINVAL; 1186 ni = ieee80211_find_node(ic->ic_sta, txpow.it_macaddr); 1187 if (ni == NULL) 1188 return EINVAL; /* XXX */ 1189 txpow.it_txpow = ni->ni_txpower; 1190 error = copyout(&txpow, ireq->i_data, sizeof(txpow)); 1191 ieee80211_free_node(ni); 1192 return error; 1193} 1194 1195static int 1196ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 1197{ 1198 struct ieee80211_wme_state *wme = &ic->ic_wme; 1199 struct wmeParams *wmep; 1200 int ac; 1201 1202 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1203 return EINVAL; 1204 1205 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1206 if (ac >= WME_NUM_AC) 1207 ac = WME_AC_BE; 1208 if (ireq->i_len & IEEE80211_WMEPARAM_BSS) 1209 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1210 else 1211 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1212 switch (ireq->i_type) { 1213 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1214 ireq->i_val = wmep->wmep_logcwmin; 1215 break; 1216 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1217 ireq->i_val = wmep->wmep_logcwmax; 1218 break; 1219 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1220 ireq->i_val = wmep->wmep_aifsn; 1221 break; 1222 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1223 ireq->i_val = wmep->wmep_txopLimit; 1224 break; 1225 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1226 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1227 ireq->i_val = wmep->wmep_acm; 1228 break; 1229 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1230 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1231 ireq->i_val = !wmep->wmep_noackPolicy; 1232 break; 1233 } 1234 return 0; 1235} 1236 1237static int 1238ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1239{ 1240 const struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn;
|
765 int error = 0;
| 1241 int error = 0;
|
766 u_int kid, len; 767 struct ieee80211req *ireq; 768 struct ifreq *ifr;
| 1242 u_int kid, len, m;
|
769 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 770 char tmpssid[IEEE80211_NWID_LEN];
| 1243 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 1244 char tmpssid[IEEE80211_NWID_LEN];
|
771 struct ieee80211_channel *chan; 772 struct ifaddr *ifa; /* XXX */
| |
773
| 1245
|
774 switch (cmd) { 775 case SIOCSIFMEDIA: 776 case SIOCGIFMEDIA: 777 error = ifmedia_ioctl(ifp, (struct ifreq *) data, 778 &ic->ic_media, cmd); 779 break; 780 case SIOCG80211: 781 ireq = (struct ieee80211req *) data; 782 switch (ireq->i_type) { 783 case IEEE80211_IOC_SSID: 784 switch (ic->ic_state) { 785 case IEEE80211_S_INIT: 786 case IEEE80211_S_SCAN: 787 ireq->i_len = ic->ic_des_esslen; 788 memcpy(tmpssid, ic->ic_des_essid, ireq->i_len); 789 break; 790 default: 791 ireq->i_len = ic->ic_bss->ni_esslen; 792 memcpy(tmpssid, ic->ic_bss->ni_essid, 793 ireq->i_len); 794 break; 795 } 796 error = copyout(tmpssid, ireq->i_data, ireq->i_len);
| 1246 switch (ireq->i_type) { 1247 case IEEE80211_IOC_SSID: 1248 switch (ic->ic_state) { 1249 case IEEE80211_S_INIT: 1250 case IEEE80211_S_SCAN: 1251 ireq->i_len = ic->ic_des_esslen; 1252 memcpy(tmpssid, ic->ic_des_essid, ireq->i_len);
|
797 break;
| 1253 break;
|
798 case IEEE80211_IOC_NUMSSIDS:
| 1254 default: 1255 ireq->i_len = ic->ic_bss->ni_esslen; 1256 memcpy(tmpssid, ic->ic_bss->ni_essid, 1257 ireq->i_len); 1258 break; 1259 } 1260 error = copyout(tmpssid, ireq->i_data, ireq->i_len); 1261 break; 1262 case IEEE80211_IOC_NUMSSIDS: 1263 ireq->i_val = 1; 1264 break; 1265 case IEEE80211_IOC_WEP: 1266 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 1267 ireq->i_val = IEEE80211_WEP_OFF; 1268 else if (ic->ic_flags & IEEE80211_F_DROPUNENC) 1269 ireq->i_val = IEEE80211_WEP_ON; 1270 else 1271 ireq->i_val = IEEE80211_WEP_MIXED; 1272 break; 1273 case IEEE80211_IOC_WEPKEY: 1274 kid = (u_int) ireq->i_val; 1275 if (kid >= IEEE80211_WEP_NKID) 1276 return EINVAL; 1277 len = (u_int) ic->ic_nw_keys[kid].wk_keylen; 1278 /* NB: only root can read WEP keys */ 1279 if (suser(curthread) == 0) { 1280 bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len); 1281 } else { 1282 bzero(tmpkey, len); 1283 } 1284 ireq->i_len = len; 1285 error = copyout(tmpkey, ireq->i_data, len); 1286 break; 1287 case IEEE80211_IOC_NUMWEPKEYS: 1288 ireq->i_val = IEEE80211_WEP_NKID; 1289 break; 1290 case IEEE80211_IOC_WEPTXKEY: 1291 ireq->i_val = ic->ic_def_txkey; 1292 break; 1293 case IEEE80211_IOC_AUTHMODE: 1294 if (ic->ic_flags & IEEE80211_F_WPA) 1295 ireq->i_val = IEEE80211_AUTH_WPA; 1296 else 1297 ireq->i_val = ic->ic_bss->ni_authmode; 1298 break; 1299 case IEEE80211_IOC_CHANNEL: 1300 ireq->i_val = ieee80211_chan2ieee(ic, getcurchan(ic)); 1301 break; 1302 case IEEE80211_IOC_POWERSAVE: 1303 if (ic->ic_flags & IEEE80211_F_PMGTON) 1304 ireq->i_val = IEEE80211_POWERSAVE_ON; 1305 else 1306 ireq->i_val = IEEE80211_POWERSAVE_OFF; 1307 break; 1308 case IEEE80211_IOC_POWERSAVESLEEP: 1309 ireq->i_val = ic->ic_lintval; 1310 break; 1311 case IEEE80211_IOC_RTSTHRESHOLD: 1312 ireq->i_val = ic->ic_rtsthreshold; 1313 break; 1314 case IEEE80211_IOC_PROTMODE: 1315 ireq->i_val = ic->ic_protmode; 1316 break; 1317 case IEEE80211_IOC_TXPOWER: 1318 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 1319 return EINVAL; 1320 ireq->i_val = ic->ic_txpowlimit; 1321 break; 1322 case IEEE80211_IOC_MCASTCIPHER: 1323 ireq->i_val = rsn->rsn_mcastcipher; 1324 break; 1325 case IEEE80211_IOC_MCASTKEYLEN: 1326 ireq->i_val = rsn->rsn_mcastkeylen; 1327 break; 1328 case IEEE80211_IOC_UCASTCIPHERS: 1329 ireq->i_val = 0; 1330 for (m = 0x1; m != 0; m <<= 1) 1331 if (rsn->rsn_ucastcipherset & m) 1332 ireq->i_val |= 1<<cap2cipher(m); 1333 break; 1334 case IEEE80211_IOC_UCASTCIPHER: 1335 ireq->i_val = rsn->rsn_ucastcipher; 1336 break; 1337 case IEEE80211_IOC_UCASTKEYLEN: 1338 ireq->i_val = rsn->rsn_ucastkeylen; 1339 break; 1340 case IEEE80211_IOC_KEYMGTALGS: 1341 ireq->i_val = rsn->rsn_keymgmtset; 1342 break; 1343 case IEEE80211_IOC_RSNCAPS: 1344 ireq->i_val = rsn->rsn_caps; 1345 break; 1346 case IEEE80211_IOC_WPA: 1347 switch (ic->ic_flags & IEEE80211_F_WPA) { 1348 case IEEE80211_F_WPA1:
|
799 ireq->i_val = 1; 800 break;
| 1349 ireq->i_val = 1; 1350 break;
|
801 case IEEE80211_IOC_WEP: 802 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { 803 ireq->i_val = IEEE80211_WEP_NOSUP; 804 } else { 805 if (ic->ic_flags & IEEE80211_F_WEPON) { 806 ireq->i_val = 807 IEEE80211_WEP_MIXED; 808 } else { 809 ireq->i_val = 810 IEEE80211_WEP_OFF; 811 } 812 }
| 1351 case IEEE80211_F_WPA2: 1352 ireq->i_val = 2;
|
813 break;
| 1353 break;
|
814 case IEEE80211_IOC_WEPKEY: 815 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { 816 error = EINVAL; 817 break; 818 } 819 kid = (u_int) ireq->i_val; 820 if (kid >= IEEE80211_WEP_NKID) { 821 error = EINVAL; 822 break; 823 } 824 len = (u_int) ic->ic_nw_keys[kid].wk_len; 825 /* NB: only root can read WEP keys */ 826 if (suser(curthread) == 0) { 827 bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len); 828 } else { 829 bzero(tmpkey, len); 830 } 831 ireq->i_len = len; 832 error = copyout(tmpkey, ireq->i_data, len);
| 1354 case IEEE80211_F_WPA1 | IEEE80211_F_WPA2: 1355 ireq->i_val = 3;
|
833 break;
| 1356 break;
|
834 case IEEE80211_IOC_NUMWEPKEYS: 835 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 836 error = EINVAL; 837 else 838 ireq->i_val = IEEE80211_WEP_NKID;
| 1357 default: 1358 ireq->i_val = 0;
|
839 break;
| 1359 break;
|
840 case IEEE80211_IOC_WEPTXKEY: 841 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) 842 error = EINVAL; 843 else 844 ireq->i_val = ic->ic_wep_txkey;
| 1360 } 1361 break; 1362 case IEEE80211_IOC_CHANLIST: 1363 error = ieee80211_ioctl_getchanlist(ic, ireq); 1364 break; 1365 case IEEE80211_IOC_ROAMING: 1366 ireq->i_val = ic->ic_roaming; 1367 break; 1368 case IEEE80211_IOC_PRIVACY: 1369 ireq->i_val = (ic->ic_flags & IEEE80211_F_PRIVACY) != 0; 1370 break; 1371 case IEEE80211_IOC_DROPUNENCRYPTED: 1372 ireq->i_val = (ic->ic_flags & IEEE80211_F_DROPUNENC) != 0; 1373 break; 1374 case IEEE80211_IOC_COUNTERMEASURES: 1375 ireq->i_val = (ic->ic_flags & IEEE80211_F_COUNTERM) != 0; 1376 break; 1377 case IEEE80211_IOC_DRIVER_CAPS: 1378 ireq->i_val = ic->ic_caps>>16; 1379 ireq->i_len = ic->ic_caps&0xffff; 1380 break; 1381 case IEEE80211_IOC_WME: 1382 ireq->i_val = (ic->ic_flags & IEEE80211_F_WME) != 0; 1383 break; 1384 case IEEE80211_IOC_HIDESSID: 1385 ireq->i_val = (ic->ic_flags & IEEE80211_F_HIDESSID) != 0; 1386 break; 1387 case IEEE80211_IOC_APBRIDGE: 1388 ireq->i_val = (ic->ic_flags & IEEE80211_F_NOBRIDGE) == 0; 1389 break; 1390 case IEEE80211_IOC_OPTIE: 1391 if (ic->ic_opt_ie == NULL) 1392 return EINVAL; 1393 /* NB: truncate, caller can check length */ 1394 if (ireq->i_len > ic->ic_opt_ie_len) 1395 ireq->i_len = ic->ic_opt_ie_len; 1396 error = copyout(ic->ic_opt_ie, ireq->i_data, ireq->i_len); 1397 break; 1398 case IEEE80211_IOC_WPAKEY: 1399 error = ieee80211_ioctl_getkey(ic, ireq); 1400 break; 1401 case IEEE80211_IOC_CHANINFO: 1402 error = ieee80211_ioctl_getchaninfo(ic, ireq); 1403 break; 1404 case IEEE80211_IOC_BSSID: 1405 if (ireq->i_len != IEEE80211_ADDR_LEN) 1406 return EINVAL; 1407 error = copyout(ic->ic_state == IEEE80211_S_RUN ? 1408 ic->ic_bss->ni_bssid : 1409 ic->ic_des_bssid, 1410 ireq->i_data, ireq->i_len); 1411 break; 1412 case IEEE80211_IOC_WPAIE: 1413 error = ieee80211_ioctl_getwpaie(ic, ireq); 1414 break; 1415 case IEEE80211_IOC_SCAN_RESULTS: 1416 error = ieee80211_ioctl_getscanresults(ic, ireq); 1417 break; 1418 case IEEE80211_IOC_STA_STATS: 1419 error = ieee80211_ioctl_getstastats(ic, ireq); 1420 break; 1421 case IEEE80211_IOC_TXPOWMAX: 1422 ireq->i_val = ic->ic_bss->ni_txpower; 1423 break; 1424 case IEEE80211_IOC_STA_TXPOW: 1425 error = ieee80211_ioctl_getstatxpow(ic, ireq); 1426 break; 1427 case IEEE80211_IOC_STA_INFO: 1428 error = ieee80211_ioctl_getstainfo(ic, ireq); 1429 break; 1430 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1431 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1432 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1433 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1434 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1435 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 1436 error = ieee80211_ioctl_getwmeparam(ic, ireq); 1437 break; 1438 case IEEE80211_IOC_DTIM_PERIOD: 1439 ireq->i_val = ic->ic_dtim_period; 1440 break; 1441 case IEEE80211_IOC_BEACON_INTERVAL: 1442 /* NB: get from ic_bss for station mode */ 1443 ireq->i_val = ic->ic_bss->ni_intval; 1444 break; 1445 default: 1446 error = EINVAL; 1447 break; 1448 } 1449 return error; 1450} 1451 1452static int 1453ieee80211_ioctl_setoptie(struct ieee80211com *ic, struct ieee80211req *ireq) 1454{ 1455 int error; 1456 void *ie; 1457 1458 /* 1459 * NB: Doing this for ap operation could be useful (e.g. for 1460 * WPA and/or WME) except that it typically is worthless 1461 * without being able to intervene when processing 1462 * association response frames--so disallow it for now. 1463 */ 1464 if (ic->ic_opmode != IEEE80211_M_STA) 1465 return EINVAL; 1466 if (ireq->i_len > IEEE80211_MAX_OPT_IE) 1467 return EINVAL; 1468 /* NB: data.length is validated by the wireless extensions code */ 1469 MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_WAITOK); 1470 if (ie == NULL) 1471 return ENOMEM; 1472 error = copyin(ireq->i_data, ie, ireq->i_len); 1473 /* XXX sanity check data? */ 1474 if (ic->ic_opt_ie != NULL) 1475 FREE(ic->ic_opt_ie, M_DEVBUF); 1476 ic->ic_opt_ie = ie; 1477 ic->ic_opt_ie_len = ireq->i_len; 1478 return 0; 1479} 1480 1481static int 1482ieee80211_ioctl_setkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1483{ 1484 struct ieee80211req_key ik; 1485 struct ieee80211_node *ni; 1486 struct ieee80211_key *wk; 1487 u_int16_t kid; 1488 int error; 1489 1490 if (ireq->i_len != sizeof(ik)) 1491 return EINVAL; 1492 error = copyin(ireq->i_data, &ik, sizeof(ik)); 1493 if (error) 1494 return error; 1495 /* NB: cipher support is verified by ieee80211_crypt_newkey */ 1496 /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */ 1497 if (ik.ik_keylen > sizeof(ik.ik_keydata)) 1498 return E2BIG; 1499 kid = ik.ik_keyix; 1500 if (kid == IEEE80211_KEYIX_NONE) { 1501 /* XXX unicast keys currently must be tx/rx */ 1502 if (ik.ik_flags != (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)) 1503 return EINVAL; 1504 if (ic->ic_opmode == IEEE80211_M_STA) { 1505 ni = ic->ic_bss; 1506 if (!IEEE80211_ADDR_EQ(ik.ik_macaddr, ni->ni_bssid)) 1507 return EADDRNOTAVAIL; 1508 } else { 1509 if (ic->ic_sta == NULL) 1510 return EINVAL; 1511 ni = ieee80211_find_node(ic->ic_sta, ik.ik_macaddr); 1512 if (ni == NULL) 1513 return ENOENT; 1514 } 1515 wk = &ni->ni_ucastkey; 1516 } else { 1517 if (kid >= IEEE80211_WEP_NKID) 1518 return EINVAL; 1519 wk = &ic->ic_nw_keys[kid]; 1520 ni = NULL; 1521 } 1522 error = 0; 1523 ieee80211_key_update_begin(ic); 1524 if (ieee80211_crypto_newkey(ic, ik.ik_type, wk)) { 1525 wk->wk_keylen = ik.ik_keylen; 1526 /* NB: MIC presence is implied by cipher type */ 1527 if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) 1528 wk->wk_keylen = IEEE80211_KEYBUF_SIZE; 1529 wk->wk_keyrsc = ik.ik_keyrsc; 1530 wk->wk_keytsc = 0; /* new key, reset */ 1531 wk->wk_flags |= 1532 ik.ik_flags & (IEEE80211_KEY_XMIT|IEEE80211_KEY_RECV); 1533 memset(wk->wk_key, 0, sizeof(wk->wk_key)); 1534 memcpy(wk->wk_key, ik.ik_keydata, ik.ik_keylen); 1535 if (!ieee80211_crypto_setkey(ic, wk, 1536 ni != NULL ? ni->ni_macaddr : ik.ik_macaddr)) 1537 error = EIO; 1538 else if ((ik.ik_flags & IEEE80211_KEY_DEFAULT)) 1539 ic->ic_def_txkey = kid; 1540 } else 1541 error = ENXIO; 1542 ieee80211_key_update_end(ic); 1543 if (ni != NULL) 1544 ieee80211_free_node(ni); 1545 return error; 1546} 1547 1548static int 1549ieee80211_ioctl_delkey(struct ieee80211com *ic, struct ieee80211req *ireq) 1550{ 1551 struct ieee80211req_del_key dk; 1552 int kid, error; 1553 1554 if (ireq->i_len != sizeof(dk)) 1555 return EINVAL; 1556 error = copyin(ireq->i_data, &dk, sizeof(dk)); 1557 if (error) 1558 return error; 1559 kid = dk.idk_keyix; 1560 /* XXX u_int8_t -> u_int16_t */ 1561 if (dk.idk_keyix == (u_int8_t) IEEE80211_KEYIX_NONE) { 1562 struct ieee80211_node *ni; 1563 1564 if (ic->ic_sta == NULL) 1565 return EINVAL; 1566 ni = ieee80211_find_node(ic->ic_sta, dk.idk_macaddr); 1567 if (ni == NULL) 1568 return EINVAL; /* XXX */ 1569 /* XXX error return */ 1570 ieee80211_crypto_delkey(ic, &ni->ni_ucastkey); 1571 ieee80211_free_node(ni); 1572 } else { 1573 if (kid >= IEEE80211_WEP_NKID) 1574 return EINVAL; 1575 /* XXX error return */ 1576 ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[kid]); 1577 } 1578 return 0; 1579} 1580 1581static void 1582domlme(void *arg, struct ieee80211_node *ni) 1583{ 1584 struct ieee80211com *ic = ni->ni_ic; 1585 struct ieee80211req_mlme *mlme = arg; 1586 1587 if (ni->ni_associd != 0) { 1588 IEEE80211_SEND_MGMT(ic, ni, 1589 mlme->im_op == IEEE80211_MLME_DEAUTH ? 1590 IEEE80211_FC0_SUBTYPE_DEAUTH : 1591 IEEE80211_FC0_SUBTYPE_DISASSOC, 1592 mlme->im_reason); 1593 } 1594 ieee80211_node_leave(ic, ni); 1595} 1596 1597static int 1598ieee80211_ioctl_setmlme(struct ieee80211com *ic, struct ieee80211req *ireq) 1599{ 1600 struct ieee80211req_mlme mlme; 1601 struct ieee80211_node *ni; 1602 int error; 1603 1604 if (ireq->i_len != sizeof(mlme)) 1605 return EINVAL; 1606 error = copyin(ireq->i_data, &mlme, sizeof(mlme)); 1607 if (error) 1608 return error; 1609 switch (mlme.im_op) { 1610 case IEEE80211_MLME_ASSOC: 1611 if (ic->ic_opmode != IEEE80211_M_STA) 1612 return EINVAL; 1613 /* XXX must be in S_SCAN state? */ 1614 1615 if (ic->ic_des_esslen != 0) { 1616 /* 1617 * Desired ssid specified; must match both bssid and 1618 * ssid to distinguish ap advertising multiple ssid's. 1619 */ 1620 ni = ieee80211_find_node_with_ssid(&ic->ic_scan, 1621 mlme.im_macaddr, 1622 ic->ic_des_esslen, ic->ic_des_essid); 1623 } else { 1624 /* 1625 * Normal case; just match bssid. 1626 */ 1627 ni = ieee80211_find_node(&ic->ic_scan, mlme.im_macaddr); 1628 } 1629 if (ni == NULL) 1630 return EINVAL; 1631 if (!ieee80211_sta_join(ic, ni)) { 1632 ieee80211_free_node(ni); 1633 return EINVAL; 1634 } 1635 break; 1636 case IEEE80211_MLME_DISASSOC: 1637 case IEEE80211_MLME_DEAUTH: 1638 switch (ic->ic_opmode) { 1639 case IEEE80211_M_STA: 1640 /* XXX not quite right */ 1641 ieee80211_new_state(ic, IEEE80211_S_INIT, 1642 mlme.im_reason);
|
845 break;
| 1643 break;
|
846 case IEEE80211_IOC_AUTHMODE: 847 ireq->i_val = IEEE80211_AUTH_OPEN;
| 1644 case IEEE80211_M_HOSTAP: 1645 /* NB: the broadcast address means do 'em all */ 1646 if (!IEEE80211_ADDR_EQ(mlme.im_macaddr, ic->ic_ifp->if_broadcastaddr)) { 1647 if (ic->ic_sta == NULL || 1648 (ni = ieee80211_find_node(ic->ic_sta, 1649 mlme.im_macaddr)) == NULL) 1650 return EINVAL; 1651 domlme(&mlme, ni); 1652 ieee80211_free_node(ni); 1653 } else { 1654 if (ic->ic_sta != NULL) 1655 ieee80211_iterate_nodes(ic->ic_sta, 1656 domlme, &mlme); 1657 }
|
848 break;
| 1658 break;
|
849 case IEEE80211_IOC_CHANNEL: 850 switch (ic->ic_state) { 851 case IEEE80211_S_INIT: 852 case IEEE80211_S_SCAN: 853 if (ic->ic_opmode == IEEE80211_M_STA) 854 chan = ic->ic_des_chan; 855 else 856 chan = ic->ic_ibss_chan; 857 break; 858 default: 859 chan = ic->ic_bss->ni_chan; 860 break;
| 1659 default: 1660 return EINVAL; 1661 } 1662 break; 1663 case IEEE80211_MLME_AUTHORIZE: 1664 case IEEE80211_MLME_UNAUTHORIZE: 1665 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 1666 return EINVAL; 1667 if (ic->ic_sta == NULL) 1668 return EINVAL; 1669 ni = ieee80211_find_node(ic->ic_sta, mlme.im_macaddr); 1670 if (ni == NULL) 1671 return EINVAL; 1672 if (mlme.im_op == IEEE80211_MLME_AUTHORIZE) 1673 ieee80211_node_authorize(ic, ni); 1674 else 1675 ieee80211_node_unauthorize(ic, ni); 1676 ieee80211_free_node(ni); 1677 break; 1678 default: 1679 return EINVAL; 1680 } 1681 return 0; 1682} 1683 1684static int 1685ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq) 1686{ 1687 u_int8_t mac[IEEE80211_ADDR_LEN]; 1688 const struct ieee80211_aclator *acl = ic->ic_acl; 1689 int error; 1690 1691 if (ireq->i_len != sizeof(mac)) 1692 return EINVAL; 1693 error = copyin(ireq->i_data, mac, ireq->i_len); 1694 if (error) 1695 return error; 1696 if (acl == NULL) { 1697 acl = ieee80211_aclator_get("mac"); 1698 if (acl == NULL || !acl->iac_attach(ic)) 1699 return EINVAL; 1700 ic->ic_acl = acl; 1701 } 1702 if (ireq->i_type == IEEE80211_IOC_ADDMAC) 1703 acl->iac_add(ic, mac); 1704 else 1705 acl->iac_remove(ic, mac); 1706 return 0; 1707} 1708 1709static int 1710ieee80211_ioctl_maccmd(struct ieee80211com *ic, struct ieee80211req *ireq) 1711{ 1712 const struct ieee80211_aclator *acl = ic->ic_acl; 1713 1714 switch (ireq->i_val) { 1715 case IEEE80211_MACCMD_POLICY_OPEN: 1716 case IEEE80211_MACCMD_POLICY_ALLOW: 1717 case IEEE80211_MACCMD_POLICY_DENY: 1718 if (acl == NULL) { 1719 acl = ieee80211_aclator_get("mac"); 1720 if (acl == NULL || !acl->iac_attach(ic)) 1721 return EINVAL; 1722 ic->ic_acl = acl; 1723 } 1724 acl->iac_setpolicy(ic, ireq->i_val); 1725 break; 1726 case IEEE80211_MACCMD_FLUSH: 1727 if (acl != NULL) 1728 acl->iac_flush(ic); 1729 /* NB: silently ignore when not in use */ 1730 break; 1731 case IEEE80211_MACCMD_DETACH: 1732 if (acl != NULL) { 1733 ic->ic_acl = NULL; 1734 acl->iac_detach(ic); 1735 } 1736 break; 1737 default: 1738 return EINVAL; 1739 } 1740 return 0; 1741} 1742 1743static int 1744ieee80211_ioctl_setchanlist(struct ieee80211com *ic, struct ieee80211req *ireq) 1745{ 1746 struct ieee80211req_chanlist list; 1747 u_char chanlist[IEEE80211_CHAN_BYTES]; 1748 int i, j, error; 1749 1750 if (ireq->i_len != sizeof(list)) 1751 return EINVAL; 1752 error = copyin(ireq->i_data, &list, sizeof(list)); 1753 if (error) 1754 return error; 1755 memset(chanlist, 0, sizeof(chanlist)); 1756 /* 1757 * Since channel 0 is not available for DS, channel 1 1758 * is assigned to LSB on WaveLAN. 1759 */ 1760 if (ic->ic_phytype == IEEE80211_T_DS) 1761 i = 1; 1762 else 1763 i = 0; 1764 for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { 1765 /* 1766 * NB: silently discard unavailable channels so users 1767 * can specify 1-255 to get all available channels. 1768 */ 1769 if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) 1770 setbit(chanlist, i); 1771 } 1772 if (ic->ic_ibss_chan == NULL || 1773 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { 1774 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) 1775 if (isset(chanlist, i)) { 1776 ic->ic_ibss_chan = &ic->ic_channels[i]; 1777 goto found;
|
861 }
| 1778 }
|
862 ireq->i_val = ieee80211_chan2ieee(ic, chan);
| 1779 return EINVAL; /* no active channels */ 1780found: 1781 ; 1782 } 1783 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); 1784 if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC || 1785 isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan))) 1786 ic->ic_bss->ni_chan = ic->ic_ibss_chan; 1787 return IS_UP_AUTO(ic) ? ENETRESET : 0; 1788} 1789 1790static int 1791ieee80211_ioctl_setstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) 1792{ 1793 struct ieee80211_node *ni; 1794 struct ieee80211req_sta_txpow txpow; 1795 int error; 1796 1797 if (ireq->i_len != sizeof(txpow)) 1798 return EINVAL; 1799 error = copyin(ireq->i_data, &txpow, sizeof(txpow)); 1800 if (error != 0) 1801 return error; 1802 if (ic->ic_sta == NULL) 1803 return EINVAL; 1804 ni = ieee80211_find_node(ic->ic_sta, txpow.it_macaddr); 1805 if (ni == NULL) 1806 return EINVAL; /* XXX */ 1807 ni->ni_txpower = txpow.it_txpow; 1808 ieee80211_free_node(ni); 1809 return error; 1810} 1811 1812static int 1813ieee80211_ioctl_setwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) 1814{ 1815 struct ieee80211_wme_state *wme = &ic->ic_wme; 1816 struct wmeParams *wmep, *chanp; 1817 int isbss, ac; 1818 1819 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 1820 return EINVAL; 1821 1822 isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS); 1823 ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL); 1824 if (ac >= WME_NUM_AC) 1825 ac = WME_AC_BE; 1826 if (isbss) { 1827 chanp = &wme->wme_bssChanParams.cap_wmeParams[ac]; 1828 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[ac]; 1829 } else { 1830 chanp = &wme->wme_chanParams.cap_wmeParams[ac]; 1831 wmep = &wme->wme_wmeChanParams.cap_wmeParams[ac]; 1832 } 1833 switch (ireq->i_type) { 1834 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 1835 if (isbss) { 1836 wmep->wmep_logcwmin = ireq->i_val; 1837 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1838 chanp->wmep_logcwmin = ireq->i_val; 1839 } else { 1840 wmep->wmep_logcwmin = chanp->wmep_logcwmin = 1841 ireq->i_val; 1842 } 1843 break; 1844 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 1845 if (isbss) { 1846 wmep->wmep_logcwmax = ireq->i_val; 1847 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1848 chanp->wmep_logcwmax = ireq->i_val; 1849 } else { 1850 wmep->wmep_logcwmax = chanp->wmep_logcwmax = 1851 ireq->i_val; 1852 } 1853 break; 1854 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 1855 if (isbss) { 1856 wmep->wmep_aifsn = ireq->i_val; 1857 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1858 chanp->wmep_aifsn = ireq->i_val; 1859 } else { 1860 wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val; 1861 } 1862 break; 1863 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 1864 if (isbss) { 1865 wmep->wmep_txopLimit = ireq->i_val; 1866 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1867 chanp->wmep_txopLimit = ireq->i_val; 1868 } else { 1869 wmep->wmep_txopLimit = chanp->wmep_txopLimit = 1870 ireq->i_val; 1871 } 1872 break; 1873 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 1874 wmep->wmep_acm = ireq->i_val; 1875 if ((wme->wme_flags & WME_F_AGGRMODE) == 0) 1876 chanp->wmep_acm = ireq->i_val; 1877 break; 1878 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/ 1879 wmep->wmep_noackPolicy = chanp->wmep_noackPolicy = 1880 (ireq->i_val) == 0; 1881 break; 1882 } 1883 ieee80211_wme_updateparams(ic); 1884 return 0; 1885} 1886 1887static int 1888cipher2cap(int cipher) 1889{ 1890 switch (cipher) { 1891 case IEEE80211_CIPHER_WEP: return IEEE80211_C_WEP; 1892 case IEEE80211_CIPHER_AES_OCB: return IEEE80211_C_AES; 1893 case IEEE80211_CIPHER_AES_CCM: return IEEE80211_C_AES_CCM; 1894 case IEEE80211_CIPHER_CKIP: return IEEE80211_C_CKIP; 1895 case IEEE80211_CIPHER_TKIP: return IEEE80211_C_TKIP; 1896 } 1897 return 0; 1898} 1899 1900static int 1901ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq) 1902{ 1903 static const u_int8_t zerobssid[IEEE80211_ADDR_LEN]; 1904 struct ieee80211_rsnparms *rsn = &ic->ic_bss->ni_rsn; 1905 int error; 1906 const struct ieee80211_authenticator *auth; 1907 u_int8_t tmpkey[IEEE80211_KEYBUF_SIZE]; 1908 char tmpssid[IEEE80211_NWID_LEN]; 1909 u_int8_t tmpbssid[IEEE80211_ADDR_LEN]; 1910 struct ieee80211_key *k; 1911 int j, caps; 1912 u_int kid; 1913 1914 error = 0; 1915 switch (ireq->i_type) { 1916 case IEEE80211_IOC_SSID: 1917 if (ireq->i_val != 0 || 1918 ireq->i_len > IEEE80211_NWID_LEN) 1919 return EINVAL; 1920 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 1921 if (error)
|
863 break;
| 1922 break;
|
864 case IEEE80211_IOC_POWERSAVE: 865 if (ic->ic_flags & IEEE80211_F_PMGTON) 866 ireq->i_val = IEEE80211_POWERSAVE_ON; 867 else 868 ireq->i_val = IEEE80211_POWERSAVE_OFF;
| 1923 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 1924 ic->ic_des_esslen = ireq->i_len; 1925 memcpy(ic->ic_des_essid, tmpssid, ireq->i_len); 1926 error = ENETRESET; 1927 break; 1928 case IEEE80211_IOC_WEP: 1929 switch (ireq->i_val) { 1930 case IEEE80211_WEP_OFF: 1931 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 1932 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
|
869 break;
| 1933 break;
|
870 case IEEE80211_IOC_POWERSAVESLEEP: 871 ireq->i_val = ic->ic_lintval;
| 1934 case IEEE80211_WEP_ON: 1935 ic->ic_flags |= IEEE80211_F_PRIVACY; 1936 ic->ic_flags |= IEEE80211_F_DROPUNENC;
|
872 break;
| 1937 break;
|
873 case IEEE80211_IOC_RTSTHRESHOLD: 874 ireq->i_val = ic->ic_rtsthreshold;
| 1938 case IEEE80211_WEP_MIXED: 1939 ic->ic_flags |= IEEE80211_F_PRIVACY; 1940 ic->ic_flags &= ~IEEE80211_F_DROPUNENC;
|
875 break;
| 1941 break;
|
876 case IEEE80211_IOC_PROTMODE: 877 ireq->i_val = ic->ic_protmode;
| 1942 } 1943 error = ENETRESET; 1944 break; 1945 case IEEE80211_IOC_WEPKEY: 1946 kid = (u_int) ireq->i_val; 1947 if (kid >= IEEE80211_WEP_NKID) 1948 return EINVAL; 1949 k = &ic->ic_nw_keys[kid]; 1950 if (ireq->i_len == 0) { 1951 /* zero-len =>'s delete any existing key */ 1952 (void) ieee80211_crypto_delkey(ic, k);
|
878 break;
| 1953 break;
|
879 case IEEE80211_IOC_TXPOWER: 880 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
| 1954 } 1955 if (ireq->i_len > sizeof(tmpkey)) 1956 return EINVAL; 1957 memset(tmpkey, 0, sizeof(tmpkey)); 1958 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 1959 if (error) 1960 break; 1961 ieee80211_key_update_begin(ic); 1962 if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, k)) { 1963 k->wk_keylen = ireq->i_len; 1964 k->wk_flags |= 1965 IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 1966 memcpy(k->wk_key, tmpkey, sizeof(tmpkey)); 1967 if (!ieee80211_crypto_setkey(ic, k, ic->ic_myaddr))
|
881 error = EINVAL;
| 1968 error = EINVAL;
|
882 else 883 ireq->i_val = ic->ic_txpower;
| 1969 } else 1970 error = EINVAL; 1971 ieee80211_key_update_end(ic); 1972 break; 1973 case IEEE80211_IOC_WEPTXKEY: 1974 kid = (u_int) ireq->i_val; 1975 if (kid >= IEEE80211_WEP_NKID) 1976 return EINVAL; 1977 ic->ic_def_txkey = kid; 1978 error = ERESTART; /* push to hardware */ 1979 break; 1980 case IEEE80211_IOC_AUTHMODE: 1981 switch (ireq->i_val) { 1982 case IEEE80211_AUTH_WPA: 1983 case IEEE80211_AUTH_8021X: /* 802.1x */ 1984 case IEEE80211_AUTH_OPEN: /* open */ 1985 case IEEE80211_AUTH_SHARED: /* shared-key */ 1986 case IEEE80211_AUTH_AUTO: /* auto */ 1987 auth = ieee80211_authenticator_get(ireq->i_val); 1988 if (auth == NULL) 1989 return EINVAL;
|
884 break; 885 default:
| 1990 break; 1991 default:
|
886 error = EINVAL;
| 1992 return EINVAL; 1993 } 1994 switch (ireq->i_val) { 1995 case IEEE80211_AUTH_WPA: /* WPA w/ 802.1x */ 1996 ic->ic_flags |= IEEE80211_F_PRIVACY; 1997 ireq->i_val = IEEE80211_AUTH_8021X;
|
887 break;
| 1998 break;
|
| 1999 case IEEE80211_AUTH_OPEN: /* open */ 2000 ic->ic_flags &= ~(IEEE80211_F_WPA|IEEE80211_F_PRIVACY); 2001 break; 2002 case IEEE80211_AUTH_SHARED: /* shared-key */ 2003 case IEEE80211_AUTH_8021X: /* 802.1x */ 2004 ic->ic_flags &= ~IEEE80211_F_WPA; 2005 /* both require a key so mark the PRIVACY capability */ 2006 ic->ic_flags |= IEEE80211_F_PRIVACY; 2007 break; 2008 case IEEE80211_AUTH_AUTO: /* auto */ 2009 ic->ic_flags &= ~IEEE80211_F_WPA; 2010 /* XXX PRIVACY handling? */ 2011 /* XXX what's the right way to do this? */ 2012 break;
|
888 }
| 2013 }
|
| 2014 /* NB: authenticator attach/detach happens on state change */ 2015 ic->ic_bss->ni_authmode = ireq->i_val; 2016 /* XXX mixed/mode/usage? */ 2017 ic->ic_auth = auth; 2018 error = ENETRESET;
|
889 break;
| 2019 break;
|
890 case SIOCS80211: 891 error = suser(curthread); 892 if (error) 893 break; 894 ireq = (struct ieee80211req *) data; 895 switch (ireq->i_type) { 896 case IEEE80211_IOC_SSID: 897 if (ireq->i_val != 0 || 898 ireq->i_len > IEEE80211_NWID_LEN) { 899 error = EINVAL; 900 break; 901 } 902 error = copyin(ireq->i_data, tmpssid, ireq->i_len); 903 if (error) 904 break; 905 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); 906 ic->ic_des_esslen = ireq->i_len; 907 memcpy(ic->ic_des_essid, tmpssid, ireq->i_len);
| 2020 case IEEE80211_IOC_CHANNEL: 2021 /* XXX 0xffff overflows 16-bit signed */ 2022 if (ireq->i_val == 0 || 2023 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) 2024 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 2025 else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX || 2026 isclr(ic->ic_chan_active, ireq->i_val)) { 2027 return EINVAL; 2028 } else 2029 ic->ic_ibss_chan = ic->ic_des_chan = 2030 &ic->ic_channels[ireq->i_val]; 2031 switch (ic->ic_state) { 2032 case IEEE80211_S_INIT: 2033 case IEEE80211_S_SCAN:
|
908 error = ENETRESET; 909 break;
| 2034 error = ENETRESET; 2035 break;
|
910 case IEEE80211_IOC_WEP:
| 2036 default:
|
911 /*
| 2037 /*
|
912 * These cards only support one mode so 913 * we just turn wep on if what ever is 914 * passed in is not OFF.
| 2038 * If the desired channel has changed (to something 2039 * other than any) and we're not already scanning, 2040 * then kick the state machine.
|
915 */
| 2041 */
|
916 if (ireq->i_val == IEEE80211_WEP_OFF) { 917 ic->ic_flags &= ~IEEE80211_F_WEPON; 918 } else { 919 ic->ic_flags |= IEEE80211_F_WEPON; 920 } 921 error = ENETRESET;
| 2042 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 2043 ic->ic_bss->ni_chan != ic->ic_des_chan && 2044 (ic->ic_flags & IEEE80211_F_SCAN) == 0) 2045 error = ENETRESET;
|
922 break;
| 2046 break;
|
923 case IEEE80211_IOC_WEPKEY: 924 if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { 925 error = EINVAL; 926 break;
| 2047 } 2048 if (error == ENETRESET && ic->ic_opmode == IEEE80211_M_MONITOR) 2049 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2050 break; 2051 case IEEE80211_IOC_POWERSAVE: 2052 switch (ireq->i_val) { 2053 case IEEE80211_POWERSAVE_OFF: 2054 if (ic->ic_flags & IEEE80211_F_PMGTON) { 2055 ic->ic_flags &= ~IEEE80211_F_PMGTON; 2056 error = ENETRESET;
|
927 }
| 2057 }
|
928 kid = (u_int) ireq->i_val; 929 if (kid >= IEEE80211_WEP_NKID) { 930 error = EINVAL; 931 break; 932 } 933 if (ireq->i_len > sizeof(tmpkey)) { 934 error = EINVAL; 935 break; 936 } 937 memset(tmpkey, 0, sizeof(tmpkey)); 938 error = copyin(ireq->i_data, tmpkey, ireq->i_len); 939 if (error) 940 break; 941 memcpy(ic->ic_nw_keys[kid].wk_key, tmpkey, 942 sizeof(tmpkey)); 943 ic->ic_nw_keys[kid].wk_len = ireq->i_len; 944 error = ENETRESET;
| |
945 break;
| 2058 break;
|
946 case IEEE80211_IOC_WEPTXKEY: 947 kid = (u_int) ireq->i_val; 948 if (kid >= IEEE80211_WEP_NKID) {
| 2059 case IEEE80211_POWERSAVE_ON: 2060 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
|
949 error = EINVAL;
| 2061 error = EINVAL;
|
950 break; 951 } 952 ic->ic_wep_txkey = kid; 953 error = ENETRESET; 954 break; 955#if 0 956 case IEEE80211_IOC_AUTHMODE: 957 sc->wi_authmode = ireq->i_val; 958 break; 959#endif 960 case IEEE80211_IOC_CHANNEL: 961 /* XXX 0xffff overflows 16-bit signed */ 962 if (ireq->i_val == 0 || 963 ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) 964 ic->ic_des_chan = IEEE80211_CHAN_ANYC; 965 else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX || 966 isclr(ic->ic_chan_active, ireq->i_val)) { 967 error = EINVAL; 968 break; 969 } else 970 ic->ic_ibss_chan = ic->ic_des_chan = 971 &ic->ic_channels[ireq->i_val]; 972 switch (ic->ic_state) { 973 case IEEE80211_S_INIT: 974 case IEEE80211_S_SCAN:
| 2062 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 2063 ic->ic_flags |= IEEE80211_F_PMGTON;
|
975 error = ENETRESET;
| 2064 error = ENETRESET;
|
976 break; 977 default: 978 if (ic->ic_opmode == IEEE80211_M_STA) { 979 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && 980 ic->ic_bss->ni_chan != ic->ic_des_chan) 981 error = ENETRESET; 982 } else { 983 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) 984 error = ENETRESET; 985 } 986 break;
| |
987 } 988 break;
| 2065 } 2066 break;
|
989 case IEEE80211_IOC_POWERSAVE: 990 switch (ireq->i_val) { 991 case IEEE80211_POWERSAVE_OFF: 992 if (ic->ic_flags & IEEE80211_F_PMGTON) { 993 ic->ic_flags &= ~IEEE80211_F_PMGTON; 994 error = ENETRESET; 995 } 996 break; 997 case IEEE80211_POWERSAVE_ON: 998 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) 999 error = EINVAL; 1000 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { 1001 ic->ic_flags |= IEEE80211_F_PMGTON; 1002 error = ENETRESET; 1003 } 1004 break; 1005 default: 1006 error = EINVAL; 1007 break; 1008 }
| 2067 default: 2068 error = EINVAL;
|
1009 break;
| 2069 break;
|
1010 case IEEE80211_IOC_POWERSAVESLEEP: 1011 if (ireq->i_val < 0) { 1012 error = EINVAL; 1013 break; 1014 } 1015 ic->ic_lintval = ireq->i_val; 1016 error = ENETRESET;
| 2070 } 2071 break; 2072 case IEEE80211_IOC_POWERSAVESLEEP: 2073 if (ireq->i_val < 0) 2074 return EINVAL; 2075 ic->ic_lintval = ireq->i_val; 2076 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2077 break; 2078 case IEEE80211_IOC_RTSTHRESHOLD: 2079 if (!(IEEE80211_RTS_MIN < ireq->i_val && 2080 ireq->i_val < IEEE80211_RTS_MAX)) 2081 return EINVAL; 2082 ic->ic_rtsthreshold = ireq->i_val; 2083 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2084 break; 2085 case IEEE80211_IOC_PROTMODE: 2086 if (ireq->i_val > IEEE80211_PROT_RTSCTS) 2087 return EINVAL; 2088 ic->ic_protmode = ireq->i_val; 2089 /* NB: if not operating in 11g this can wait */ 2090 if (ic->ic_curmode == IEEE80211_MODE_11G) 2091 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2092 break; 2093 case IEEE80211_IOC_TXPOWER: 2094 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) 2095 return EINVAL; 2096 if (!(IEEE80211_TXPOWER_MIN < ireq->i_val && 2097 ireq->i_val < IEEE80211_TXPOWER_MAX)) 2098 return EINVAL; 2099 ic->ic_txpowlimit = ireq->i_val; 2100 error = IS_UP(ic) ? ic->ic_reset(ic->ic_ifp) : 0; 2101 break; 2102 case IEEE80211_IOC_ROAMING: 2103 if (!(IEEE80211_ROAMING_DEVICE <= ireq->i_val && 2104 ireq->i_val <= IEEE80211_ROAMING_MANUAL)) 2105 return EINVAL; 2106 ic->ic_roaming = ireq->i_val; 2107 /* XXXX reset? */ 2108 break; 2109 case IEEE80211_IOC_PRIVACY: 2110 if (ireq->i_val) { 2111 /* XXX check for key state? */ 2112 ic->ic_flags |= IEEE80211_F_PRIVACY; 2113 } else 2114 ic->ic_flags &= ~IEEE80211_F_PRIVACY; 2115 break; 2116 case IEEE80211_IOC_DROPUNENCRYPTED: 2117 if (ireq->i_val) 2118 ic->ic_flags |= IEEE80211_F_DROPUNENC; 2119 else 2120 ic->ic_flags &= ~IEEE80211_F_DROPUNENC; 2121 break; 2122 case IEEE80211_IOC_WPAKEY: 2123 error = ieee80211_ioctl_setkey(ic, ireq); 2124 break; 2125 case IEEE80211_IOC_DELKEY: 2126 error = ieee80211_ioctl_delkey(ic, ireq); 2127 break; 2128 case IEEE80211_IOC_MLME: 2129 error = ieee80211_ioctl_setmlme(ic, ireq); 2130 break; 2131 case IEEE80211_IOC_OPTIE: 2132 error = ieee80211_ioctl_setoptie(ic, ireq); 2133 break; 2134 case IEEE80211_IOC_COUNTERMEASURES: 2135 if (ireq->i_val) { 2136 if ((ic->ic_flags & IEEE80211_F_WPA) == 0) 2137 return EINVAL; 2138 ic->ic_flags |= IEEE80211_F_COUNTERM; 2139 } else 2140 ic->ic_flags &= ~IEEE80211_F_COUNTERM; 2141 break; 2142 case IEEE80211_IOC_WPA: 2143 if (ireq->i_val > 3) 2144 return EINVAL; 2145 /* XXX verify ciphers available */ 2146 ic->ic_flags &= ~IEEE80211_F_WPA; 2147 switch (ireq->i_val) { 2148 case 1: 2149 ic->ic_flags |= IEEE80211_F_WPA1;
|
1017 break;
| 2150 break;
|
1018 case IEEE80211_IOC_RTSTHRESHOLD: 1019 if (!(IEEE80211_RTS_MIN < ireq->i_val && 1020 ireq->i_val < IEEE80211_RTS_MAX)) { 1021 error = EINVAL; 1022 break; 1023 } 1024 ic->ic_rtsthreshold = ireq->i_val; 1025 error = ENETRESET;
| 2151 case 2: 2152 ic->ic_flags |= IEEE80211_F_WPA2;
|
1026 break;
| 2153 break;
|
1027 case IEEE80211_IOC_PROTMODE: 1028 if (ireq->i_val > IEEE80211_PROT_RTSCTS) { 1029 error = EINVAL; 1030 break; 1031 } 1032 ic->ic_protmode = ireq->i_val; 1033 /* NB: if not operating in 11g this can wait */ 1034 if (ic->ic_curmode == IEEE80211_MODE_11G) 1035 error = ENETRESET;
| 2154 case 3: 2155 ic->ic_flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2;
|
1036 break;
| 2156 break;
|
1037 case IEEE80211_IOC_TXPOWER: 1038 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { 1039 error = EINVAL; 1040 break; 1041 } 1042 if (!(IEEE80211_TXPOWER_MIN < ireq->i_val && 1043 ireq->i_val < IEEE80211_TXPOWER_MAX)) { 1044 error = EINVAL; 1045 break; 1046 } 1047 ic->ic_txpower = ireq->i_val; 1048 error = ENETRESET;
| 2157 } 2158 error = ENETRESET; /* XXX? */ 2159 break; 2160 case IEEE80211_IOC_WME: 2161 if (ireq->i_val) { 2162 if ((ic->ic_caps & IEEE80211_C_WME) == 0) 2163 return EINVAL; 2164 ic->ic_flags |= IEEE80211_F_WME; 2165 } else 2166 ic->ic_flags &= ~IEEE80211_F_WME; 2167 error = ENETRESET; /* XXX maybe not for station? */ 2168 break; 2169 case IEEE80211_IOC_HIDESSID: 2170 if (ireq->i_val) 2171 ic->ic_flags |= IEEE80211_F_HIDESSID; 2172 else 2173 ic->ic_flags &= ~IEEE80211_F_HIDESSID; 2174 error = ENETRESET; 2175 break; 2176 case IEEE80211_IOC_APBRIDGE: 2177 if (ireq->i_val == 0) 2178 ic->ic_flags |= IEEE80211_F_NOBRIDGE; 2179 else 2180 ic->ic_flags &= ~IEEE80211_F_NOBRIDGE; 2181 break; 2182 case IEEE80211_IOC_MCASTCIPHER: 2183 if ((ic->ic_caps & cipher2cap(ireq->i_val)) == 0 && 2184 !ieee80211_crypto_available(ireq->i_val)) 2185 return EINVAL; 2186 rsn->rsn_mcastcipher = ireq->i_val; 2187 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2188 break; 2189 case IEEE80211_IOC_MCASTKEYLEN: 2190 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2191 return EINVAL; 2192 /* XXX no way to verify driver capability */ 2193 rsn->rsn_mcastkeylen = ireq->i_val; 2194 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2195 break; 2196 case IEEE80211_IOC_UCASTCIPHERS: 2197 /* 2198 * Convert user-specified cipher set to the set 2199 * we can support (via hardware or software). 2200 * NB: this logic intentionally ignores unknown and 2201 * unsupported ciphers so folks can specify 0xff or 2202 * similar and get all available ciphers. 2203 */ 2204 caps = 0; 2205 for (j = 1; j < 32; j++) /* NB: skip WEP */ 2206 if ((ireq->i_val & (1<<j)) && 2207 ((ic->ic_caps & cipher2cap(j)) || 2208 ieee80211_crypto_available(j))) 2209 caps |= 1<<j; 2210 if (caps == 0) /* nothing available */ 2211 return EINVAL; 2212 /* XXX verify ciphers ok for unicast use? */ 2213 /* XXX disallow if running as it'll have no effect */ 2214 rsn->rsn_ucastcipherset = caps; 2215 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2216 break; 2217 case IEEE80211_IOC_UCASTCIPHER: 2218 if ((rsn->rsn_ucastcipherset & cipher2cap(ireq->i_val)) == 0) 2219 return EINVAL; 2220 rsn->rsn_ucastcipher = ireq->i_val; 2221 break; 2222 case IEEE80211_IOC_UCASTKEYLEN: 2223 if (!(0 < ireq->i_val && ireq->i_val < IEEE80211_KEYBUF_SIZE)) 2224 return EINVAL; 2225 /* XXX no way to verify driver capability */ 2226 rsn->rsn_ucastkeylen = ireq->i_val; 2227 break; 2228 case IEEE80211_IOC_DRIVER_CAPS: 2229 /* NB: for testing */ 2230 ic->ic_caps = (((u_int16_t) ireq->i_val) << 16) | 2231 ((u_int16_t) ireq->i_len); 2232 break; 2233 case IEEE80211_IOC_KEYMGTALGS: 2234 /* XXX check */ 2235 rsn->rsn_keymgmtset = ireq->i_val; 2236 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2237 break; 2238 case IEEE80211_IOC_RSNCAPS: 2239 /* XXX check */ 2240 rsn->rsn_caps = ireq->i_val; 2241 error = (ic->ic_flags & IEEE80211_F_WPA) ? ENETRESET : 0; 2242 break; 2243 case IEEE80211_IOC_BSSID: 2244 /* NB: should only be set when in STA mode */ 2245 if (ic->ic_opmode != IEEE80211_M_STA) 2246 return EINVAL; 2247 if (ireq->i_len != sizeof(tmpbssid)) 2248 return EINVAL; 2249 error = copyin(ireq->i_data, tmpbssid, ireq->i_len); 2250 if (error)
|
1049 break;
| 2251 break;
|
1050 default: 1051 error = EINVAL;
| 2252 IEEE80211_ADDR_COPY(ic->ic_des_bssid, tmpbssid); 2253 if (IEEE80211_ADDR_EQ(ic->ic_des_bssid, zerobssid)) 2254 ic->ic_flags &= ~IEEE80211_F_DESBSSID; 2255 else 2256 ic->ic_flags |= IEEE80211_F_DESBSSID; 2257 error = ENETRESET; 2258 break; 2259 case IEEE80211_IOC_CHANLIST: 2260 error = ieee80211_ioctl_setchanlist(ic, ireq); 2261 break; 2262 case IEEE80211_IOC_SCAN_REQ: 2263 if (ic->ic_opmode == IEEE80211_M_HOSTAP) /* XXX ignore */
|
1052 break;
| 2264 break;
|
1053 }
| 2265 error = ieee80211_setupscan(ic, ic->ic_chan_avail); 2266 if (error == 0) /* XXX background scan */ 2267 error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
|
1054 break;
| 2268 break;
|
| 2269 case IEEE80211_IOC_ADDMAC: 2270 case IEEE80211_IOC_DELMAC: 2271 error = ieee80211_ioctl_macmac(ic, ireq); 2272 break; 2273 case IEEE80211_IOC_MACCMD: 2274 error = ieee80211_ioctl_maccmd(ic, ireq); 2275 break; 2276 case IEEE80211_IOC_STA_TXPOW: 2277 error = ieee80211_ioctl_setstatxpow(ic, ireq); 2278 break; 2279 case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */ 2280 case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */ 2281 case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */ 2282 case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */ 2283 case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */ 2284 case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */ 2285 error = ieee80211_ioctl_setwmeparam(ic, ireq); 2286 break; 2287 case IEEE80211_IOC_DTIM_PERIOD: 2288 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2289 ic->ic_opmode != IEEE80211_M_IBSS) 2290 return EINVAL; 2291 if (IEEE80211_DTIM_MIN <= ireq->i_val && 2292 ireq->i_val <= IEEE80211_DTIM_MAX) { 2293 ic->ic_dtim_period = ireq->i_val; 2294 error = ENETRESET; /* requires restart */ 2295 } else 2296 error = EINVAL; 2297 break; 2298 case IEEE80211_IOC_BEACON_INTERVAL: 2299 if (ic->ic_opmode != IEEE80211_M_HOSTAP && 2300 ic->ic_opmode != IEEE80211_M_IBSS) 2301 return EINVAL; 2302 if (IEEE80211_BINTVAL_MIN <= ireq->i_val && 2303 ireq->i_val <= IEEE80211_BINTVAL_MAX) { 2304 ic->ic_lintval = ireq->i_val; 2305 error = ENETRESET; /* requires restart */ 2306 } else 2307 error = EINVAL; 2308 break; 2309 default: 2310 error = EINVAL; 2311 break; 2312 } 2313 if (error == ENETRESET && !IS_UP_AUTO(ic)) 2314 error = 0; 2315 return error; 2316} 2317 2318int 2319ieee80211_ioctl(struct ieee80211com *ic, u_long cmd, caddr_t data) 2320{ 2321 struct ifnet *ifp = ic->ic_ifp; 2322 int error = 0; 2323 struct ifreq *ifr; 2324 struct ifaddr *ifa; /* XXX */ 2325 2326 switch (cmd) { 2327 case SIOCSIFMEDIA: 2328 case SIOCGIFMEDIA: 2329 error = ifmedia_ioctl(ifp, (struct ifreq *) data, 2330 &ic->ic_media, cmd); 2331 break; 2332 case SIOCG80211: 2333 error = ieee80211_ioctl_get80211(ic, cmd, 2334 (struct ieee80211req *) data); 2335 break; 2336 case SIOCS80211: 2337 error = suser(curthread); 2338 if (error == 0) 2339 error = ieee80211_ioctl_set80211(ic, cmd, 2340 (struct ieee80211req *) data); 2341 break;
|
1055 case SIOCGIFGENERIC:
| 2342 case SIOCGIFGENERIC:
|
1056 error = ieee80211_cfgget(ifp, cmd, data);
| 2343 error = ieee80211_cfgget(ic, cmd, data);
|
1057 break; 1058 case SIOCSIFGENERIC: 1059 error = suser(curthread); 1060 if (error) 1061 break;
| 2344 break; 2345 case SIOCSIFGENERIC: 2346 error = suser(curthread); 2347 if (error) 2348 break;
|
1062 error = ieee80211_cfgset(ifp, cmd, data);
| 2349 error = ieee80211_cfgset(ic, cmd, data);
|
1063 break; 1064 case SIOCG80211STATS: 1065 ifr = (struct ifreq *)data; 1066 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 1067 break; 1068 case SIOCSIFMTU: 1069 ifr = (struct ifreq *)data; 1070 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 1071 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 1072 error = EINVAL; 1073 else 1074 ifp->if_mtu = ifr->ifr_mtu; 1075 break; 1076 case SIOCSIFADDR: 1077 /* 1078 * XXX Handle this directly so we can supress if_init calls. 1079 * XXX This should be done in ether_ioctl but for the moment 1080 * XXX there are too many other parts of the system that 1081 * XXX set IFF_UP and so supress if_init being called when 1082 * XXX it should be. 1083 */ 1084 ifa = (struct ifaddr *) data; 1085 switch (ifa->ifa_addr->sa_family) { 1086#ifdef INET 1087 case AF_INET: 1088 if ((ifp->if_flags & IFF_UP) == 0) { 1089 ifp->if_flags |= IFF_UP; 1090 ifp->if_init(ifp->if_softc); 1091 } 1092 arp_ifinit(ifp, ifa); 1093 break; 1094#endif 1095#ifdef IPX 1096 /* 1097 * XXX - This code is probably wrong, 1098 * but has been copied many times. 1099 */ 1100 case AF_IPX: { 1101 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 1102 struct arpcom *ac = (struct arpcom *)ifp; 1103 1104 if (ipx_nullhost(*ina)) 1105 ina->x_host = *(union ipx_host *) ac->ac_enaddr; 1106 else 1107 bcopy((caddr_t) ina->x_host.c_host, 1108 (caddr_t) ac->ac_enaddr, 1109 sizeof(ac->ac_enaddr)); 1110 /* fall thru... */ 1111 } 1112#endif 1113 default: 1114 if ((ifp->if_flags & IFF_UP) == 0) { 1115 ifp->if_flags |= IFF_UP; 1116 ifp->if_init(ifp->if_softc); 1117 } 1118 break; 1119 } 1120 break; 1121 default: 1122 error = ether_ioctl(ifp, cmd, data); 1123 break; 1124 } 1125 return error; 1126}
| 2350 break; 2351 case SIOCG80211STATS: 2352 ifr = (struct ifreq *)data; 2353 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); 2354 break; 2355 case SIOCSIFMTU: 2356 ifr = (struct ifreq *)data; 2357 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && 2358 ifr->ifr_mtu <= IEEE80211_MTU_MAX)) 2359 error = EINVAL; 2360 else 2361 ifp->if_mtu = ifr->ifr_mtu; 2362 break; 2363 case SIOCSIFADDR: 2364 /* 2365 * XXX Handle this directly so we can supress if_init calls. 2366 * XXX This should be done in ether_ioctl but for the moment 2367 * XXX there are too many other parts of the system that 2368 * XXX set IFF_UP and so supress if_init being called when 2369 * XXX it should be. 2370 */ 2371 ifa = (struct ifaddr *) data; 2372 switch (ifa->ifa_addr->sa_family) { 2373#ifdef INET 2374 case AF_INET: 2375 if ((ifp->if_flags & IFF_UP) == 0) { 2376 ifp->if_flags |= IFF_UP; 2377 ifp->if_init(ifp->if_softc); 2378 } 2379 arp_ifinit(ifp, ifa); 2380 break; 2381#endif 2382#ifdef IPX 2383 /* 2384 * XXX - This code is probably wrong, 2385 * but has been copied many times. 2386 */ 2387 case AF_IPX: { 2388 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 2389 struct arpcom *ac = (struct arpcom *)ifp; 2390 2391 if (ipx_nullhost(*ina)) 2392 ina->x_host = *(union ipx_host *) ac->ac_enaddr; 2393 else 2394 bcopy((caddr_t) ina->x_host.c_host, 2395 (caddr_t) ac->ac_enaddr, 2396 sizeof(ac->ac_enaddr)); 2397 /* fall thru... */ 2398 } 2399#endif 2400 default: 2401 if ((ifp->if_flags & IFF_UP) == 0) { 2402 ifp->if_flags |= IFF_UP; 2403 ifp->if_init(ifp->if_softc); 2404 } 2405 break; 2406 } 2407 break; 2408 default: 2409 error = ether_ioctl(ifp, cmd, data); 2410 break; 2411 } 2412 return error; 2413}
|