1 /* $OpenBSD: ieee80211_ioctl.c,v 1.81 2022/03/07 08:13:13 stsp Exp $ */
2 /* $NetBSD: ieee80211_ioctl.c,v 1.15 2004/05/06 02:58:16 dyoung Exp $ */
3
4 /*-
5 * Copyright (c) 2001 Atsushi Onoe
6 * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * IEEE 802.11 ioctl support
34 */
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/systm.h>
41 #include <sys/endian.h>
42 #include <sys/tree.h>
43 #ifdef __HAIKU__
44 #include <sys/ucred.h>
45 #endif
46
47 #include <net/if.h>
48 #include <net/if_media.h>
49
50 #include <netinet/in.h>
51 #include <netinet/if_ether.h>
52
53 #include <net80211/ieee80211_var.h>
54 #include <net80211/ieee80211_crypto.h>
55 #include <net80211/ieee80211_ioctl.h>
56
57 void ieee80211_node2req(struct ieee80211com *,
58 const struct ieee80211_node *, struct ieee80211_nodereq *);
59 void ieee80211_req2node(struct ieee80211com *,
60 const struct ieee80211_nodereq *, struct ieee80211_node *);
61
62 void
ieee80211_node2req(struct ieee80211com * ic,const struct ieee80211_node * ni,struct ieee80211_nodereq * nr)63 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni,
64 struct ieee80211_nodereq *nr)
65 {
66 uint8_t rssi;
67
68 memset(nr, 0, sizeof(*nr));
69
70 strlcpy(nr->nr_ifname, ic->ic_if.if_xname, sizeof(nr->nr_ifname));
71
72 /* Node address and name information */
73 IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr);
74 IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid);
75 nr->nr_nwid_len = ni->ni_esslen;
76 bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN);
77
78 /* Channel and rates */
79 nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan);
80 if (ni->ni_chan != IEEE80211_CHAN_ANYC)
81 nr->nr_chan_flags = ni->ni_chan->ic_flags;
82 if (ic->ic_curmode != IEEE80211_MODE_11N)
83 nr->nr_chan_flags &= ~IEEE80211_CHAN_HT;
84 nr->nr_nrates = ni->ni_rates.rs_nrates;
85 bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE);
86
87 /* Node status information */
88 rssi = (*ic->ic_node_getrssi)(ic, ni);
89 if (ic->ic_max_rssi) {
90 /* Driver reports RSSI relative to ic_max_rssi. */
91 nr->nr_rssi = rssi;
92 } else {
93 /*
94 * Driver reports RSSI value in dBm.
95 * Convert from unsigned to signed.
96 * Some drivers report a negative value, some don't.
97 * Reasonable range is -20dBm to -80dBm.
98 */
99 nr->nr_rssi = (rssi < 128) ? -rssi : rssi;
100 }
101 nr->nr_max_rssi = ic->ic_max_rssi;
102 bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp));
103 nr->nr_intval = ni->ni_intval;
104 nr->nr_capinfo = ni->ni_capinfo;
105 nr->nr_erp = ni->ni_erp;
106 nr->nr_pwrsave = ni->ni_pwrsave;
107 nr->nr_associd = ni->ni_associd;
108 nr->nr_txseq = ni->ni_txseq;
109 nr->nr_rxseq = ni->ni_rxseq;
110 nr->nr_fails = ni->ni_fails;
111 nr->nr_assoc_fail = ni->ni_assoc_fail; /* flag values are the same */
112 nr->nr_inact = ni->ni_inact;
113 nr->nr_txrate = ni->ni_txrate;
114 nr->nr_state = ni->ni_state;
115
116 /* RSN */
117 nr->nr_rsnciphers = ni->ni_rsnciphers;
118 nr->nr_rsnakms = 0;
119 nr->nr_rsnprotos = 0;
120 if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_RSN)
121 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA2;
122 if (ni->ni_supported_rsnprotos & IEEE80211_PROTO_WPA)
123 nr->nr_rsnprotos |= IEEE80211_WPA_PROTO_WPA1;
124 if (ni->ni_supported_rsnakms & IEEE80211_AKM_8021X)
125 nr->nr_rsnakms |= IEEE80211_WPA_AKM_8021X;
126 if (ni->ni_supported_rsnakms & IEEE80211_AKM_PSK)
127 nr->nr_rsnakms |= IEEE80211_WPA_AKM_PSK;
128 if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_8021X)
129 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_8021X;
130 if (ni->ni_supported_rsnakms & IEEE80211_AKM_SHA256_PSK)
131 nr->nr_rsnakms |= IEEE80211_WPA_AKM_SHA256_PSK;
132 #ifdef __FreeBSD_version
133 if (ni->ni_rsnie != NULL)
134 memcpy(nr->nr_rsnie, ni->ni_rsnie, 2 + ni->ni_rsnie[1]);
135 else
136 nr->nr_rsnie[1] = 0;
137 #endif
138
139 /* Node flags */
140 nr->nr_flags = 0;
141 if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0)
142 nr->nr_flags |= IEEE80211_NODEREQ_AP;
143 if (ni == ic->ic_bss)
144 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS;
145
146 /* HT */
147 nr->nr_htcaps = ni->ni_htcaps;
148 memcpy(nr->nr_rxmcs, ni->ni_rxmcs, sizeof(nr->nr_rxmcs));
149 nr->nr_max_rxrate = ni->ni_max_rxrate;
150 nr->nr_tx_mcs_set = ni->ni_tx_mcs_set;
151 if (ni->ni_flags & IEEE80211_NODE_HT)
152 nr->nr_flags |= IEEE80211_NODEREQ_HT;
153
154 /* HT / VHT */
155 nr->nr_txmcs = ni->ni_txmcs;
156
157 /* VHT */
158 nr->nr_vht_ss = ni->ni_vht_ss;
159 if (ni->ni_flags & IEEE80211_NODE_VHT)
160 nr->nr_flags |= IEEE80211_NODEREQ_VHT;
161 }
162
163 void
ieee80211_req2node(struct ieee80211com * ic,const struct ieee80211_nodereq * nr,struct ieee80211_node * ni)164 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr,
165 struct ieee80211_node *ni)
166 {
167 /* Node address and name information */
168 IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr);
169 IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid);
170 ni->ni_esslen = nr->nr_nwid_len;
171 bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN);
172
173 /* Rates */
174 ni->ni_rates.rs_nrates = nr->nr_nrates;
175 bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE);
176
177 /* Node information */
178 ni->ni_intval = nr->nr_intval;
179 ni->ni_capinfo = nr->nr_capinfo;
180 ni->ni_erp = nr->nr_erp;
181 ni->ni_pwrsave = nr->nr_pwrsave;
182 ni->ni_associd = nr->nr_associd;
183 ni->ni_txseq = nr->nr_txseq;
184 ni->ni_rxseq = nr->nr_rxseq;
185 ni->ni_fails = nr->nr_fails;
186 ni->ni_inact = nr->nr_inact;
187 ni->ni_txrate = nr->nr_txrate;
188 ni->ni_state = nr->nr_state;
189 }
190
191 void
ieee80211_disable_wep(struct ieee80211com * ic)192 ieee80211_disable_wep(struct ieee80211com *ic)
193 {
194 struct ieee80211_key *k;
195 int i;
196
197 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
198 k = &ic->ic_nw_keys[i];
199 if (k->k_cipher != IEEE80211_CIPHER_NONE)
200 (*ic->ic_delete_key)(ic, NULL, k);
201 explicit_bzero(k, sizeof(*k));
202 }
203 ic->ic_flags &= ~IEEE80211_F_WEPON;
204 }
205
206 void
ieee80211_disable_rsn(struct ieee80211com * ic)207 ieee80211_disable_rsn(struct ieee80211com *ic)
208 {
209 ic->ic_flags &= ~(IEEE80211_F_PSK | IEEE80211_F_RSNON);
210 explicit_bzero(ic->ic_psk, sizeof(ic->ic_psk));
211 ic->ic_rsnprotos = 0;
212 ic->ic_rsnakms = 0;
213 ic->ic_rsngroupcipher = 0;
214 ic->ic_rsnciphers = 0;
215 }
216
217 /* Keep in sync with ieee80211_node.c:ieee80211_ess_setnwkeys() */
218 static int
ieee80211_ioctl_setnwkeys(struct ieee80211com * ic,const struct ieee80211_nwkey * nwkey)219 ieee80211_ioctl_setnwkeys(struct ieee80211com *ic,
220 const struct ieee80211_nwkey *nwkey)
221 {
222 struct ieee80211_key *k;
223 int error, i;
224
225 if (!(ic->ic_caps & IEEE80211_C_WEP))
226 return ENODEV;
227
228 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN) {
229 if (!(ic->ic_flags & IEEE80211_F_WEPON))
230 return 0;
231 ic->ic_flags &= ~IEEE80211_F_WEPON;
232 return ENETRESET;
233 }
234 if (nwkey->i_defkid < 1 || nwkey->i_defkid > IEEE80211_WEP_NKID)
235 return EINVAL;
236
237 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
238 if (nwkey->i_key[i].i_keylen == 0 ||
239 nwkey->i_key[i].i_keydat == NULL)
240 continue; /* entry not set */
241 if (nwkey->i_key[i].i_keylen > IEEE80211_KEYBUF_SIZE)
242 return EINVAL;
243
244 /* map wep key to ieee80211_key */
245 k = &ic->ic_nw_keys[i];
246 if (k->k_cipher != IEEE80211_CIPHER_NONE)
247 (*ic->ic_delete_key)(ic, NULL, k);
248 memset(k, 0, sizeof(*k));
249 if (nwkey->i_key[i].i_keylen <= 5)
250 k->k_cipher = IEEE80211_CIPHER_WEP40;
251 else
252 k->k_cipher = IEEE80211_CIPHER_WEP104;
253 k->k_len = ieee80211_cipher_keylen(k->k_cipher);
254 k->k_flags = IEEE80211_KEY_GROUP | IEEE80211_KEY_TX;
255 error = copyin(nwkey->i_key[i].i_keydat, k->k_key, k->k_len);
256 if (error != 0)
257 return error;
258 error = (*ic->ic_set_key)(ic, NULL, k);
259 switch (error) {
260 case 0:
261 case EBUSY:
262 break;
263 default:
264 return error;
265 }
266 }
267
268 ic->ic_def_txkey = nwkey->i_defkid - 1;
269 ic->ic_flags |= IEEE80211_F_WEPON;
270 if (ic->ic_flags & IEEE80211_F_RSNON)
271 ieee80211_disable_rsn(ic);
272
273 return ENETRESET;
274 }
275
276 static int
ieee80211_ioctl_getnwkeys(struct ieee80211com * ic,struct ieee80211_nwkey * nwkey)277 ieee80211_ioctl_getnwkeys(struct ieee80211com *ic,
278 struct ieee80211_nwkey *nwkey)
279 {
280 int i;
281
282 if (ic->ic_flags & IEEE80211_F_WEPON)
283 nwkey->i_wepon = IEEE80211_NWKEY_WEP;
284 else
285 nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
286
287 nwkey->i_defkid = ic->ic_wep_txkey + 1;
288
289 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
290 if (nwkey->i_key[i].i_keydat == NULL)
291 continue;
292 /* do not show any keys to userland */
293 return EPERM;
294 }
295 return 0;
296 }
297
298 /* Keep in sync with ieee80211_node.c:ieee80211_ess_setwpaparms() */
299 static int
ieee80211_ioctl_setwpaparms(struct ieee80211com * ic,const struct ieee80211_wpaparams * wpa)300 ieee80211_ioctl_setwpaparms(struct ieee80211com *ic,
301 const struct ieee80211_wpaparams *wpa)
302 {
303 if (!(ic->ic_caps & IEEE80211_C_RSN))
304 return ENODEV;
305
306 if (!wpa->i_enabled) {
307 if (!(ic->ic_flags & IEEE80211_F_RSNON))
308 return 0;
309 ic->ic_flags &= ~IEEE80211_F_RSNON;
310 ic->ic_rsnprotos = 0;
311 ic->ic_rsnakms = 0;
312 ic->ic_rsngroupcipher = 0;
313 ic->ic_rsnciphers = 0;
314 return ENETRESET;
315 }
316
317 ic->ic_rsnprotos = 0;
318 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA1)
319 ic->ic_rsnprotos |= IEEE80211_PROTO_WPA;
320 if (wpa->i_protos & IEEE80211_WPA_PROTO_WPA2)
321 ic->ic_rsnprotos |= IEEE80211_PROTO_RSN;
322 if (ic->ic_rsnprotos == 0) /* set to default (RSN) */
323 ic->ic_rsnprotos = IEEE80211_PROTO_RSN;
324
325 ic->ic_rsnakms = 0;
326 if (wpa->i_akms & IEEE80211_WPA_AKM_PSK)
327 ic->ic_rsnakms |= IEEE80211_AKM_PSK;
328 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_PSK)
329 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_PSK;
330 if (wpa->i_akms & IEEE80211_WPA_AKM_8021X)
331 ic->ic_rsnakms |= IEEE80211_AKM_8021X;
332 if (wpa->i_akms & IEEE80211_WPA_AKM_SHA256_8021X)
333 ic->ic_rsnakms |= IEEE80211_AKM_SHA256_8021X;
334 if (ic->ic_rsnakms == 0) /* set to default (PSK) */
335 ic->ic_rsnakms = IEEE80211_AKM_PSK;
336
337 if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP40)
338 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP40;
339 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_TKIP)
340 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;
341 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_CCMP)
342 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;
343 else if (wpa->i_groupcipher == IEEE80211_WPA_CIPHER_WEP104)
344 ic->ic_rsngroupcipher = IEEE80211_CIPHER_WEP104;
345 else { /* set to default */
346 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
347 ic->ic_rsngroupcipher = IEEE80211_CIPHER_TKIP;
348 else
349 ic->ic_rsngroupcipher = IEEE80211_CIPHER_CCMP;
350 }
351
352 ic->ic_rsnciphers = 0;
353 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_TKIP)
354 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;
355 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_CCMP)
356 ic->ic_rsnciphers |= IEEE80211_CIPHER_CCMP;
357 if (wpa->i_ciphers & IEEE80211_WPA_CIPHER_USEGROUP)
358 ic->ic_rsnciphers = IEEE80211_CIPHER_USEGROUP;
359 if (ic->ic_rsnciphers == 0) { /* set to default (CCMP, TKIP if WPA1) */
360 ic->ic_rsnciphers = IEEE80211_CIPHER_CCMP;
361 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
362 ic->ic_rsnciphers |= IEEE80211_CIPHER_TKIP;
363 }
364
365 ic->ic_flags |= IEEE80211_F_RSNON;
366
367 return ENETRESET;
368 }
369
370 static int
ieee80211_ioctl_getwpaparms(struct ieee80211com * ic,struct ieee80211_wpaparams * wpa)371 ieee80211_ioctl_getwpaparms(struct ieee80211com *ic,
372 struct ieee80211_wpaparams *wpa)
373 {
374 wpa->i_enabled = (ic->ic_flags & IEEE80211_F_RSNON) ? 1 : 0;
375
376 wpa->i_protos = 0;
377 if (ic->ic_rsnprotos & IEEE80211_PROTO_WPA)
378 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1;
379 if (ic->ic_rsnprotos & IEEE80211_PROTO_RSN)
380 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2;
381
382 wpa->i_akms = 0;
383 if (ic->ic_rsnakms & IEEE80211_AKM_PSK)
384 wpa->i_akms |= IEEE80211_WPA_AKM_PSK;
385 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_PSK)
386 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK;
387 if (ic->ic_rsnakms & IEEE80211_AKM_8021X)
388 wpa->i_akms |= IEEE80211_WPA_AKM_8021X;
389 if (ic->ic_rsnakms & IEEE80211_AKM_SHA256_8021X)
390 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X;
391
392 if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP40)
393 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40;
394 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_TKIP)
395 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP;
396 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_CCMP)
397 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP;
398 else if (ic->ic_rsngroupcipher == IEEE80211_CIPHER_WEP104)
399 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104;
400 else
401 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE;
402
403 wpa->i_ciphers = 0;
404 if (ic->ic_rsnciphers & IEEE80211_CIPHER_TKIP)
405 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP;
406 if (ic->ic_rsnciphers & IEEE80211_CIPHER_CCMP)
407 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP;
408 if (ic->ic_rsnciphers & IEEE80211_CIPHER_USEGROUP)
409 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP;
410
411 return 0;
412 }
413
414 static void
ieee80211_ess_getwpaparms(struct ieee80211_ess * ess,struct ieee80211_wpaparams * wpa)415 ieee80211_ess_getwpaparms(struct ieee80211_ess *ess,
416 struct ieee80211_wpaparams *wpa)
417 {
418 wpa->i_enabled = (ess->flags & IEEE80211_F_RSNON) ? 1 : 0;
419
420 wpa->i_protos = 0;
421 if (ess->rsnprotos & IEEE80211_PROTO_WPA)
422 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA1;
423 if (ess->rsnprotos & IEEE80211_PROTO_RSN)
424 wpa->i_protos |= IEEE80211_WPA_PROTO_WPA2;
425
426 wpa->i_akms = 0;
427 if (ess->rsnakms & IEEE80211_AKM_PSK)
428 wpa->i_akms |= IEEE80211_WPA_AKM_PSK;
429 if (ess->rsnakms & IEEE80211_AKM_SHA256_PSK)
430 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_PSK;
431 if (ess->rsnakms & IEEE80211_AKM_8021X)
432 wpa->i_akms |= IEEE80211_WPA_AKM_8021X;
433 if (ess->rsnakms & IEEE80211_AKM_SHA256_8021X)
434 wpa->i_akms |= IEEE80211_WPA_AKM_SHA256_8021X;
435
436 if (ess->rsngroupcipher == IEEE80211_CIPHER_WEP40)
437 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP40;
438 else if (ess->rsngroupcipher == IEEE80211_CIPHER_TKIP)
439 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_TKIP;
440 else if (ess->rsngroupcipher == IEEE80211_CIPHER_CCMP)
441 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_CCMP;
442 else if (ess->rsngroupcipher == IEEE80211_CIPHER_WEP104)
443 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_WEP104;
444 else
445 wpa->i_groupcipher = IEEE80211_WPA_CIPHER_NONE;
446
447 wpa->i_ciphers = 0;
448 if (ess->rsnciphers & IEEE80211_CIPHER_TKIP)
449 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_TKIP;
450 if (ess->rsnciphers & IEEE80211_CIPHER_CCMP)
451 wpa->i_ciphers |= IEEE80211_WPA_CIPHER_CCMP;
452 if (ess->rsnciphers & IEEE80211_CIPHER_USEGROUP)
453 wpa->i_ciphers = IEEE80211_WPA_CIPHER_USEGROUP;
454 }
455
456 int
ieee80211_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)457 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
458 {
459 struct ieee80211com *ic = (void *)ifp;
460 struct ifreq *ifr = (struct ifreq *)data;
461 int i, error = 0;
462 size_t len;
463 struct ieee80211_nwid nwid;
464 struct ieee80211_join join;
465 struct ieee80211_joinreq_all *ja;
466 struct ieee80211_ess *ess;
467 struct ieee80211_wpapsk *psk;
468 struct ieee80211_keyavail *ka;
469 struct ieee80211_keyrun *kr;
470 struct ieee80211_power *power;
471 struct ieee80211_bssid *bssid;
472 struct ieee80211chanreq *chanreq;
473 struct ieee80211_channel *chan;
474 struct ieee80211_txpower *txpower;
475 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
477 };
478 struct ieee80211_nodereq *nr, nrbuf;
479 struct ieee80211_nodereq_all *na;
480 struct ieee80211_node *ni;
481 struct ieee80211_chaninfo chaninfo;
482 struct ieee80211_chanreq_all *allchans;
483 u_int32_t flags;
484
485 switch (cmd) {
486 case SIOCSIFMEDIA:
487 case SIOCGIFMEDIA:
488 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
489 break;
490 case SIOCS80211NWID:
491 if ((error = suser(curproc)) != 0)
492 break;
493 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
494 break;
495 if (nwid.i_len > IEEE80211_NWID_LEN) {
496 error = EINVAL;
497 break;
498 }
499 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
500 ic->ic_des_esslen = nwid.i_len;
501 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
502 if (ic->ic_des_esslen > 0) {
503 /* 'nwid' disables auto-join magic */
504 ic->ic_flags &= ~IEEE80211_F_AUTO_JOIN;
505 } else if (!TAILQ_EMPTY(&ic->ic_ess)) {
506 /* '-nwid' re-enables auto-join */
507 ic->ic_flags |= IEEE80211_F_AUTO_JOIN;
508 }
509 /* disable WPA/WEP */
510 ieee80211_disable_rsn(ic);
511 ieee80211_disable_wep(ic);
512 error = ENETRESET;
513 break;
514 case SIOCG80211NWID:
515 memset(&nwid, 0, sizeof(nwid));
516 switch (ic->ic_state) {
517 case IEEE80211_S_INIT:
518 case IEEE80211_S_SCAN:
519 nwid.i_len = ic->ic_des_esslen;
520 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);
521 break;
522 default:
523 nwid.i_len = ic->ic_bss->ni_esslen;
524 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len);
525 break;
526 }
527 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
528 break;
529 case SIOCS80211JOIN:
530 if ((error = suser(curproc)) != 0)
531 break;
532 if (ic->ic_opmode != IEEE80211_M_STA)
533 break;
534 if ((error = copyin(ifr->ifr_data, &join, sizeof(join))) != 0)
535 break;
536 if (join.i_len > IEEE80211_NWID_LEN) {
537 error = EINVAL;
538 break;
539 }
540 if (join.i_flags & IEEE80211_JOIN_DEL) {
541 int update_ic = 0;
542 if (ic->ic_des_esslen == join.i_len &&
543 memcmp(join.i_nwid, ic->ic_des_essid,
544 join.i_len) == 0)
545 update_ic = 1;
546 if (join.i_flags & IEEE80211_JOIN_DEL_ALL &&
547 ieee80211_get_ess(ic, ic->ic_des_essid,
548 ic->ic_des_esslen) != NULL)
549 update_ic = 1;
550 ieee80211_del_ess(ic, join.i_nwid, join.i_len,
551 join.i_flags & IEEE80211_JOIN_DEL_ALL ? 1 : 0);
552 if (update_ic == 1) {
553 /* Unconfigure this essid */
554 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
555 ic->ic_des_esslen = 0;
556 /* disable WPA/WEP */
557 ieee80211_disable_rsn(ic);
558 ieee80211_disable_wep(ic);
559 error = ENETRESET;
560 }
561 } else {
562 if (ic->ic_des_esslen == join.i_len &&
563 memcmp(join.i_nwid, ic->ic_des_essid,
564 join.i_len) == 0) {
565 struct ieee80211_node *ni;
566
567 ieee80211_deselect_ess(ic);
568 ni = ieee80211_find_node(ic,
569 ic->ic_bss->ni_bssid);
570 if (ni != NULL)
571 ieee80211_free_node(ic, ni);
572 error = ENETRESET;
573 }
574 /* save nwid for auto-join */
575 if (ieee80211_add_ess(ic, &join) == 0)
576 ic->ic_flags |= IEEE80211_F_AUTO_JOIN;
577 }
578 break;
579 case SIOCG80211JOIN:
580 memset(&join, 0, sizeof(join));
581 error = ENOENT;
582 if (ic->ic_bss == NULL)
583 break;
584 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
585 if (memcmp(ess->essid, ic->ic_bss->ni_essid,
586 IEEE80211_NWID_LEN) == 0) {
587 join.i_len = ic->ic_bss->ni_esslen;
588 memcpy(join.i_nwid, ic->ic_bss->ni_essid,
589 join.i_len);
590 if (ic->ic_flags & IEEE80211_F_AUTO_JOIN)
591 join.i_flags = IEEE80211_JOIN_FOUND;
592 error = copyout(&join, ifr->ifr_data,
593 sizeof(join));
594 break;
595 }
596 }
597 break;
598 case SIOCG80211JOINALL:
599 ja = (struct ieee80211_joinreq_all *)data;
600 ja->ja_nodes = len = 0;
601 TAILQ_FOREACH(ess, &ic->ic_ess, ess_next) {
602 if (len + sizeof(ja->ja_node[0]) >= ja->ja_size) {
603 error = E2BIG;
604 break;
605 }
606 memset(&join, 0, sizeof(join));
607 join.i_len = ess->esslen;
608 memcpy(&join.i_nwid, ess->essid, join.i_len);
609 if (ess->flags & IEEE80211_F_RSNON)
610 join.i_flags |= IEEE80211_JOIN_WPA;
611 if (ess->flags & IEEE80211_F_PSK)
612 join.i_flags |= IEEE80211_JOIN_WPAPSK;
613 if (ess->flags & IEEE80211_JOIN_8021X)
614 join.i_flags |= IEEE80211_JOIN_8021X;
615 if (ess->flags & IEEE80211_F_WEPON)
616 join.i_flags |= IEEE80211_JOIN_NWKEY;
617 if (ess->flags & IEEE80211_JOIN_ANY)
618 join.i_flags |= IEEE80211_JOIN_ANY;
619 ieee80211_ess_getwpaparms(ess, &join.i_wpaparams);
620 error = copyout(&join, &ja->ja_node[ja->ja_nodes],
621 sizeof(ja->ja_node[0]));
622 if (error)
623 break;
624 len += sizeof(join);
625 ja->ja_nodes++;
626 }
627 break;
628 case SIOCS80211NWKEY:
629 if ((error = suser(curproc)) != 0)
630 break;
631 error = ieee80211_ioctl_setnwkeys(ic, (void *)data);
632 break;
633 case SIOCG80211NWKEY:
634 error = ieee80211_ioctl_getnwkeys(ic, (void *)data);
635 break;
636 case SIOCS80211WPAPARMS:
637 if ((error = suser(curproc)) != 0)
638 break;
639 error = ieee80211_ioctl_setwpaparms(ic, (void *)data);
640 break;
641 case SIOCG80211WPAPARMS:
642 error = ieee80211_ioctl_getwpaparms(ic, (void *)data);
643 break;
644 case SIOCS80211WPAPSK:
645 if ((error = suser(curproc)) != 0)
646 break;
647 psk = (struct ieee80211_wpapsk *)data;
648 if (psk->i_enabled) {
649 ic->ic_flags |= IEEE80211_F_PSK;
650 memcpy(ic->ic_psk, psk->i_psk, sizeof(ic->ic_psk));
651 if (ic->ic_flags & IEEE80211_F_WEPON)
652 ieee80211_disable_wep(ic);
653 } else {
654 ic->ic_flags &= ~IEEE80211_F_PSK;
655 memset(ic->ic_psk, 0, sizeof(ic->ic_psk));
656 }
657 error = ENETRESET;
658 break;
659 case SIOCG80211WPAPSK:
660 psk = (struct ieee80211_wpapsk *)data;
661 if (ic->ic_flags & IEEE80211_F_PSK) {
662 /* do not show any keys to userland */
663 psk->i_enabled = 2;
664 memset(psk->i_psk, 0, sizeof(psk->i_psk));
665 break; /* return ok but w/o key */
666 } else
667 psk->i_enabled = 0;
668 break;
669 case SIOCS80211KEYAVAIL:
670 if ((error = suser(curproc)) != 0)
671 break;
672 ka = (struct ieee80211_keyavail *)data;
673 (void)ieee80211_pmksa_add(ic, IEEE80211_AKM_8021X,
674 ka->i_macaddr, ka->i_key, ka->i_lifetime);
675 break;
676 case SIOCS80211KEYRUN:
677 if ((error = suser(curproc)) != 0)
678 break;
679 kr = (struct ieee80211_keyrun *)data;
680 error = ieee80211_keyrun(ic, kr->i_macaddr);
681 if (error == 0 && (ic->ic_flags & IEEE80211_F_WEPON))
682 ieee80211_disable_wep(ic);
683 break;
684 case SIOCS80211POWER:
685 if ((error = suser(curproc)) != 0)
686 break;
687 power = (struct ieee80211_power *)data;
688 ic->ic_lintval = power->i_maxsleep;
689 if (power->i_enabled != 0) {
690 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
691 error = EINVAL;
692 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
693 ic->ic_flags |= IEEE80211_F_PMGTON;
694 error = ENETRESET;
695 }
696 } else {
697 if (ic->ic_flags & IEEE80211_F_PMGTON) {
698 ic->ic_flags &= ~IEEE80211_F_PMGTON;
699 error = ENETRESET;
700 }
701 }
702 break;
703 case SIOCG80211POWER:
704 power = (struct ieee80211_power *)data;
705 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
706 power->i_maxsleep = ic->ic_lintval;
707 break;
708 case SIOCS80211BSSID:
709 if ((error = suser(curproc)) != 0)
710 break;
711 bssid = (struct ieee80211_bssid *)data;
712 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))
713 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
714 else {
715 ic->ic_flags |= IEEE80211_F_DESBSSID;
716 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);
717 }
718 #ifndef IEEE80211_STA_ONLY
719 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
720 break;
721 #endif
722 switch (ic->ic_state) {
723 case IEEE80211_S_INIT:
724 case IEEE80211_S_SCAN:
725 error = ENETRESET;
726 break;
727 default:
728 if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
729 !IEEE80211_ADDR_EQ(ic->ic_des_bssid,
730 ic->ic_bss->ni_bssid))
731 error = ENETRESET;
732 break;
733 }
734 break;
735 case SIOCG80211BSSID:
736 bssid = (struct ieee80211_bssid *)data;
737 switch (ic->ic_state) {
738 case IEEE80211_S_INIT:
739 case IEEE80211_S_SCAN:
740 #ifndef IEEE80211_STA_ONLY
741 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
742 IEEE80211_ADDR_COPY(bssid->i_bssid,
743 ic->ic_myaddr);
744 else
745 #endif
746 if (ic->ic_flags & IEEE80211_F_DESBSSID)
747 IEEE80211_ADDR_COPY(bssid->i_bssid,
748 ic->ic_des_bssid);
749 else
750 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
751 break;
752 default:
753 IEEE80211_ADDR_COPY(bssid->i_bssid,
754 ic->ic_bss->ni_bssid);
755 break;
756 }
757 break;
758 case SIOCS80211CHANNEL:
759 if ((error = suser(curproc)) != 0)
760 break;
761 chanreq = (struct ieee80211chanreq *)data;
762 if (chanreq->i_channel == IEEE80211_CHAN_ANY)
763 ic->ic_des_chan = IEEE80211_CHAN_ANYC;
764 else if (chanreq->i_channel > IEEE80211_CHAN_MAX ||
765 isclr(ic->ic_chan_active, chanreq->i_channel)) {
766 error = EINVAL;
767 break;
768 } else
769 ic->ic_ibss_chan = ic->ic_des_chan =
770 &ic->ic_channels[chanreq->i_channel];
771 switch (ic->ic_state) {
772 case IEEE80211_S_INIT:
773 case IEEE80211_S_SCAN:
774 error = ENETRESET;
775 break;
776 default:
777 if (ic->ic_opmode == IEEE80211_M_STA) {
778 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
779 ic->ic_bss->ni_chan != ic->ic_des_chan)
780 error = ENETRESET;
781 } else {
782 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan)
783 error = ENETRESET;
784 }
785 break;
786 }
787 break;
788 case SIOCG80211CHANNEL:
789 chanreq = (struct ieee80211chanreq *)data;
790 switch (ic->ic_state) {
791 case IEEE80211_S_INIT:
792 case IEEE80211_S_SCAN:
793 if (ic->ic_opmode == IEEE80211_M_STA)
794 chan = ic->ic_des_chan;
795 else
796 chan = ic->ic_ibss_chan;
797 break;
798 default:
799 chan = ic->ic_bss->ni_chan;
800 break;
801 }
802 chanreq->i_channel = ieee80211_chan2ieee(ic, chan);
803 break;
804 case SIOCG80211ALLCHANS:
805 allchans = (struct ieee80211_chanreq_all *)data;
806 for (i = 0; i <= IEEE80211_CHAN_MAX; i++) {
807 chan = &ic->ic_channels[i];
808 chaninfo.ic_freq = chan->ic_freq;
809 chaninfo.ic_flags = 0;
810 if (chan->ic_flags & IEEE80211_CHAN_2GHZ)
811 chaninfo.ic_flags |= IEEE80211_CHANINFO_2GHZ;
812 if (chan->ic_flags & IEEE80211_CHAN_5GHZ)
813 chaninfo.ic_flags |= IEEE80211_CHANINFO_5GHZ;
814 if (chan->ic_flags & IEEE80211_CHAN_PASSIVE)
815 chaninfo.ic_flags |= IEEE80211_CHANINFO_PASSIVE;
816 error = copyout(&chaninfo, &allchans->i_chans[i],
817 sizeof(chaninfo));
818 if (error)
819 break;
820 }
821 break;
822 #if 0
823 case SIOCG80211ZSTATS:
824 #endif
825 case SIOCG80211STATS:
826 ifr = (struct ifreq *)data;
827 error = copyout(&ic->ic_stats, ifr->ifr_data,
828 sizeof(ic->ic_stats));
829 #if 0
830 if (cmd == SIOCG80211ZSTATS)
831 memset(&ic->ic_stats, 0, sizeof(ic->ic_stats));
832 #endif
833 break;
834 case SIOCS80211TXPOWER:
835 if ((error = suser(curproc)) != 0)
836 break;
837 txpower = (struct ieee80211_txpower *)data;
838 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) {
839 error = EINVAL;
840 break;
841 }
842 if (!(IEEE80211_TXPOWER_MIN <= txpower->i_val &&
843 txpower->i_val <= IEEE80211_TXPOWER_MAX)) {
844 error = EINVAL;
845 break;
846 }
847 ic->ic_txpower = txpower->i_val;
848 error = ENETRESET;
849 break;
850 case SIOCG80211TXPOWER:
851 txpower = (struct ieee80211_txpower *)data;
852 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
853 error = EINVAL;
854 else
855 txpower->i_val = ic->ic_txpower;
856 break;
857 case SIOCSIFMTU:
858 ifr = (struct ifreq *)data;
859 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
860 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
861 error = EINVAL;
862 else
863 ifp->if_mtu = ifr->ifr_mtu;
864 break;
865 case SIOCS80211SCAN:
866 /* Disabled. SIOCG80211ALLNODES is enough. */
867 break;
868 case SIOCG80211NODE:
869 nr = (struct ieee80211_nodereq *)data;
870 if (ic->ic_bss &&
871 IEEE80211_ADDR_EQ(nr->nr_macaddr, ic->ic_bss->ni_macaddr))
872 ni = ic->ic_bss;
873 else
874 ni = ieee80211_find_node(ic, nr->nr_macaddr);
875 if (ni == NULL) {
876 error = ENOENT;
877 break;
878 }
879 ieee80211_node2req(ic, ni, nr);
880 break;
881 case SIOCS80211NODE:
882 if ((error = suser(curproc)) != 0)
883 break;
884 #ifndef IEEE80211_STA_ONLY
885 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
886 error = EINVAL;
887 break;
888 }
889 #endif
890 nr = (struct ieee80211_nodereq *)data;
891
892 ni = ieee80211_find_node(ic, nr->nr_macaddr);
893 if (ni == NULL)
894 ni = ieee80211_alloc_node(ic, nr->nr_macaddr);
895 if (ni == NULL) {
896 error = ENOENT;
897 break;
898 }
899
900 if (nr->nr_flags & IEEE80211_NODEREQ_COPY)
901 ieee80211_req2node(ic, nr, ni);
902 break;
903 #ifndef IEEE80211_STA_ONLY
904 case SIOCS80211DELNODE:
905 if ((error = suser(curproc)) != 0)
906 break;
907 nr = (struct ieee80211_nodereq *)data;
908 ni = ieee80211_find_node(ic, nr->nr_macaddr);
909 if (ni == NULL)
910 error = ENOENT;
911 else if (ni == ic->ic_bss)
912 error = EPERM;
913 else {
914 if (ni->ni_state == IEEE80211_STA_COLLECT)
915 break;
916
917 /* Disassociate station. */
918 if (ni->ni_state == IEEE80211_STA_ASSOC)
919 IEEE80211_SEND_MGMT(ic, ni,
920 IEEE80211_FC0_SUBTYPE_DISASSOC,
921 IEEE80211_REASON_ASSOC_LEAVE);
922
923 /* Deauth station. */
924 if (ni->ni_state >= IEEE80211_STA_AUTH)
925 IEEE80211_SEND_MGMT(ic, ni,
926 IEEE80211_FC0_SUBTYPE_DEAUTH,
927 IEEE80211_REASON_AUTH_LEAVE);
928
929 ieee80211_node_leave(ic, ni);
930 }
931 break;
932 #endif
933 case SIOCG80211ALLNODES:
934 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
935 (IFF_UP | IFF_RUNNING)) {
936 error = ENETDOWN;
937 break;
938 }
939
940 na = (struct ieee80211_nodereq_all *)data;
941 na->na_nodes = i = 0;
942 ni = RBT_MIN(ieee80211_tree, &ic->ic_tree);
943 #ifdef __FreeBSD_version
944 while (ni && na->na_startnode) {
945 ni = RBT_NEXT(ieee80211_tree, ni);
946 na->na_startnode--;
947 }
948 #endif
949 while (ni && na->na_size >=
950 i + sizeof(struct ieee80211_nodereq)) {
951 ieee80211_node2req(ic, ni, &nrbuf);
952 error = copyout(&nrbuf, (caddr_t)na->na_node + i,
953 sizeof(struct ieee80211_nodereq));
954 if (error)
955 break;
956 i += sizeof(struct ieee80211_nodereq);
957 na->na_nodes++;
958 ni = RBT_NEXT(ieee80211_tree, ni);
959 }
960 if (suser(curproc) == 0)
961 ieee80211_begin_bgscan(ifp);
962 break;
963 case SIOCG80211FLAGS:
964 flags = ic->ic_userflags;
965 #ifndef IEEE80211_STA_ONLY
966 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
967 #endif
968 flags &= ~IEEE80211_F_HOSTAPMASK;
969 ifr->ifr_flags = flags;
970 break;
971 case SIOCS80211FLAGS:
972 if ((error = suser(curproc)) != 0)
973 break;
974 flags = ifr->ifr_flags;
975 if (
976 #ifndef IEEE80211_STA_ONLY
977 ic->ic_opmode != IEEE80211_M_HOSTAP &&
978 #endif
979 (flags & IEEE80211_F_HOSTAPMASK)) {
980 error = EINVAL;
981 break;
982 }
983 ic->ic_userflags = flags;
984 error = ENETRESET;
985 break;
986 #ifndef __HAIKU__
987 case SIOCADDMULTI:
988 case SIOCDELMULTI:
989 error = (cmd == SIOCADDMULTI) ?
990 ether_addmulti(ifr, &ic->ic_ac) :
991 ether_delmulti(ifr, &ic->ic_ac);
992 if (error == ENETRESET)
993 error = 0;
994 break;
995 #endif
996 default:
997 #ifdef __FreeBSD_version
998 error = ether_ioctl(ifp, cmd, data);
999 #else
1000 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
1001 #endif
1002 }
1003
1004 return error;
1005 }
1006