This source file includes following definitions.
- ieee80211_node2req
- ieee80211_req2node
- ieee80211_ioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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/proc.h>
43 #include <sys/tree.h>
44
45 #include <net/if.h>
46 #include <net/if_arp.h>
47 #include <net/if_media.h>
48
49 #ifdef INET
50 #include <netinet/in.h>
51 #include <netinet/if_ether.h>
52 #endif
53
54 #include <net80211/ieee80211_var.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
63 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni,
64 struct ieee80211_nodereq *nr)
65 {
66
67 IEEE80211_ADDR_COPY(nr->nr_macaddr, ni->ni_macaddr);
68 IEEE80211_ADDR_COPY(nr->nr_bssid, ni->ni_bssid);
69 nr->nr_nwid_len = ni->ni_esslen;
70 bcopy(ni->ni_essid, nr->nr_nwid, IEEE80211_NWID_LEN);
71
72
73 nr->nr_channel = ieee80211_chan2ieee(ic, ni->ni_chan);
74 nr->nr_chan_flags = ni->ni_chan->ic_flags;
75 nr->nr_nrates = ni->ni_rates.rs_nrates;
76 bcopy(ni->ni_rates.rs_rates, nr->nr_rates, IEEE80211_RATE_MAXSIZE);
77
78
79 nr->nr_rssi = (*ic->ic_node_getrssi)(ic, ni);
80 nr->nr_max_rssi = ic->ic_max_rssi;
81 bcopy(ni->ni_tstamp, nr->nr_tstamp, sizeof(nr->nr_tstamp));
82 nr->nr_intval = ni->ni_intval;
83 nr->nr_capinfo = ni->ni_capinfo;
84 nr->nr_fhdwell = ni->ni_fhdwell;
85 nr->nr_fhindex = ni->ni_fhindex;
86 nr->nr_erp = ni->ni_erp;
87 nr->nr_pwrsave = ni->ni_pwrsave;
88 nr->nr_associd = ni->ni_associd;
89 nr->nr_txseq = ni->ni_txseq;
90 nr->nr_rxseq = ni->ni_rxseq;
91 nr->nr_fails = ni->ni_fails;
92 nr->nr_inact = ni->ni_inact;
93 nr->nr_txrate = ni->ni_txrate;
94 nr->nr_state = ni->ni_state;
95
96
97 nr->nr_flags = 0;
98 if (bcmp(nr->nr_macaddr, nr->nr_bssid, IEEE80211_ADDR_LEN) == 0)
99 nr->nr_flags |= IEEE80211_NODEREQ_AP;
100 if (ni == ic->ic_bss)
101 nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS;
102 }
103
104 void
105 ieee80211_req2node(struct ieee80211com *ic, const struct ieee80211_nodereq *nr,
106 struct ieee80211_node *ni)
107 {
108
109 IEEE80211_ADDR_COPY(ni->ni_macaddr, nr->nr_macaddr);
110 IEEE80211_ADDR_COPY(ni->ni_bssid, nr->nr_bssid);
111 ni->ni_esslen = nr->nr_nwid_len;
112 bcopy(nr->nr_nwid, ni->ni_essid, IEEE80211_NWID_LEN);
113
114
115 ni->ni_rates.rs_nrates = nr->nr_nrates;
116 bcopy(nr->nr_rates, ni->ni_rates.rs_rates, IEEE80211_RATE_MAXSIZE);
117
118
119 ni->ni_intval = nr->nr_intval;
120 ni->ni_capinfo = nr->nr_capinfo;
121 ni->ni_fhdwell = nr->nr_fhdwell;
122 ni->ni_fhindex = nr->nr_fhindex;
123 ni->ni_erp = nr->nr_erp;
124 ni->ni_pwrsave = nr->nr_pwrsave;
125 ni->ni_associd = nr->nr_associd;
126 ni->ni_txseq = nr->nr_txseq;
127 ni->ni_rxseq = nr->nr_rxseq;
128 ni->ni_fails = nr->nr_fails;
129 ni->ni_inact = nr->nr_inact;
130 ni->ni_txrate = nr->nr_txrate;
131 ni->ni_state = nr->nr_state;
132 }
133
134 int
135 ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
136 {
137 struct ieee80211com *ic = (void *)ifp;
138 struct ifreq *ifr = (struct ifreq *)data;
139 int i, error = 0;
140 struct ieee80211_nwid nwid;
141 struct ieee80211_nwkey *nwkey;
142 struct ieee80211_power *power;
143 struct ieee80211_bssid *bssid;
144 struct ieee80211chanreq *chanreq;
145 struct ieee80211_channel *chan;
146 struct ieee80211_txpower *txpower;
147 struct ieee80211_key keys[IEEE80211_WEP_NKID];
148 static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
150 };
151 struct ieee80211_nodereq *nr, nrbuf;
152 struct ieee80211_nodereq_all *na;
153 struct ieee80211_node *ni;
154 u_int32_t flags;
155
156 switch (cmd) {
157 case SIOCSIFADDR:
158 case SIOCGIFADDR:
159 error = ether_ioctl(ifp, &ic->ic_ac, cmd, data);
160 break;
161 case SIOCSIFMEDIA:
162 case SIOCGIFMEDIA:
163 error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
164 break;
165 case SIOCS80211NWID:
166 if ((error = suser(curproc, 0)) != 0)
167 break;
168 if ((error = copyin(ifr->ifr_data, &nwid, sizeof(nwid))) != 0)
169 break;
170 if (nwid.i_len > IEEE80211_NWID_LEN) {
171 error = EINVAL;
172 break;
173 }
174 memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN);
175 ic->ic_des_esslen = nwid.i_len;
176 memcpy(ic->ic_des_essid, nwid.i_nwid, nwid.i_len);
177 error = ENETRESET;
178 break;
179 case SIOCG80211NWID:
180 memset(&nwid, 0, sizeof(nwid));
181 switch (ic->ic_state) {
182 case IEEE80211_S_INIT:
183 case IEEE80211_S_SCAN:
184 nwid.i_len = ic->ic_des_esslen;
185 memcpy(nwid.i_nwid, ic->ic_des_essid, nwid.i_len);
186 break;
187 default:
188 nwid.i_len = ic->ic_bss->ni_esslen;
189 memcpy(nwid.i_nwid, ic->ic_bss->ni_essid, nwid.i_len);
190 break;
191 }
192 error = copyout(&nwid, ifr->ifr_data, sizeof(nwid));
193 break;
194 case SIOCS80211NWKEY:
195 if ((error = suser(curproc, 0)) != 0)
196 break;
197 nwkey = (struct ieee80211_nwkey *)data;
198 if ((ic->ic_caps & IEEE80211_C_WEP) == 0 &&
199 nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
200 error = EINVAL;
201 break;
202 }
203
204 memset(keys, 0, sizeof(keys));
205 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
206 keys[i].k_len = nwkey->i_key[i].i_keylen;
207
208
209
210
211 if (keys[i].k_len > sizeof(keys[i].k_key)) {
212 error = EINVAL;
213 break;
214 }
215 if (keys[i].k_len <= 0)
216 continue;
217 if ((error = copyin(nwkey->i_key[i].i_keydat,
218 keys[i].k_key, keys[i].k_len)) != 0)
219 break;
220 }
221 if (error)
222 break;
223 i = nwkey->i_defkid - 1;
224 if (i < 0 || i >= IEEE80211_WEP_NKID ||
225 keys[i].k_len == 0 ||
226 (keys[i].k_len == -1 && ic->ic_nw_keys[i].k_len == 0)) {
227 if (nwkey->i_wepon != IEEE80211_NWKEY_OPEN) {
228 error = EINVAL;
229 break;
230 }
231 } else
232 ic->ic_wep_txkey = i;
233
234 if (nwkey->i_wepon == IEEE80211_NWKEY_OPEN)
235 ic->ic_flags &= ~IEEE80211_F_WEPON;
236 else
237 ic->ic_flags |= IEEE80211_F_WEPON;
238 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
239 struct ieee80211_key *k = &ic->ic_nw_keys[i];
240 if (keys[i].k_len < 0)
241 continue;
242 if (keys[i].k_len == 0)
243 k->k_cipher = IEEE80211_CIPHER_NONE;
244 else if (keys[i].k_len <= 5)
245 k->k_cipher = IEEE80211_CIPHER_WEP40;
246 else
247 k->k_cipher = IEEE80211_CIPHER_WEP104;
248 k->k_len = keys[i].k_len;
249 memcpy(k->k_key, keys[i].k_key, sizeof(keys[i].k_key));
250 }
251 error = ENETRESET;
252 break;
253 case SIOCG80211NWKEY:
254 nwkey = (struct ieee80211_nwkey *)data;
255 if (ic->ic_flags & IEEE80211_F_WEPON)
256 nwkey->i_wepon = IEEE80211_NWKEY_WEP;
257 else
258 nwkey->i_wepon = IEEE80211_NWKEY_OPEN;
259 nwkey->i_defkid = ic->ic_wep_txkey + 1;
260 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
261 if (nwkey->i_key[i].i_keydat == NULL)
262 continue;
263
264 if ((error = suser(curproc, 0)) != 0)
265 break;
266 nwkey->i_key[i].i_keylen = ic->ic_nw_keys[i].k_len;
267 if ((error = copyout(ic->ic_nw_keys[i].k_key,
268 nwkey->i_key[i].i_keydat,
269 ic->ic_nw_keys[i].k_len)) != 0)
270 break;
271 }
272 break;
273 case SIOCS80211POWER:
274 if ((error = suser(curproc, 0)) != 0)
275 break;
276 power = (struct ieee80211_power *)data;
277 ic->ic_lintval = power->i_maxsleep;
278 if (power->i_enabled != 0) {
279 if ((ic->ic_caps & IEEE80211_C_PMGT) == 0)
280 error = EINVAL;
281 else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) {
282 ic->ic_flags |= IEEE80211_F_PMGTON;
283 error = ENETRESET;
284 }
285 } else {
286 if (ic->ic_flags & IEEE80211_F_PMGTON) {
287 ic->ic_flags &= ~IEEE80211_F_PMGTON;
288 error = ENETRESET;
289 }
290 }
291 break;
292 case SIOCG80211POWER:
293 power = (struct ieee80211_power *)data;
294 power->i_enabled = (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0;
295 power->i_maxsleep = ic->ic_lintval;
296 break;
297 case SIOCS80211BSSID:
298 if ((error = suser(curproc, 0)) != 0)
299 break;
300 bssid = (struct ieee80211_bssid *)data;
301 if (IEEE80211_ADDR_EQ(bssid->i_bssid, empty_macaddr))
302 ic->ic_flags &= ~IEEE80211_F_DESBSSID;
303 else {
304 ic->ic_flags |= IEEE80211_F_DESBSSID;
305 IEEE80211_ADDR_COPY(ic->ic_des_bssid, bssid->i_bssid);
306 }
307 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
308 break;
309 switch (ic->ic_state) {
310 case IEEE80211_S_INIT:
311 case IEEE80211_S_SCAN:
312 error = ENETRESET;
313 break;
314 default:
315 if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
316 !IEEE80211_ADDR_EQ(ic->ic_des_bssid,
317 ic->ic_bss->ni_bssid))
318 error = ENETRESET;
319 break;
320 }
321 break;
322 case SIOCG80211BSSID:
323 bssid = (struct ieee80211_bssid *)data;
324 switch (ic->ic_state) {
325 case IEEE80211_S_INIT:
326 case IEEE80211_S_SCAN:
327 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
328 IEEE80211_ADDR_COPY(bssid->i_bssid,
329 ic->ic_myaddr);
330 else if (ic->ic_flags & IEEE80211_F_DESBSSID)
331 IEEE80211_ADDR_COPY(bssid->i_bssid,
332 ic->ic_des_bssid);
333 else
334 memset(bssid->i_bssid, 0, IEEE80211_ADDR_LEN);
335 break;
336 default:
337 IEEE80211_ADDR_COPY(bssid->i_bssid,
338 ic->ic_bss->ni_bssid);
339 break;
340 }
341 break;
342 case SIOCS80211CHANNEL:
343 if ((error = suser(curproc, 0)) != 0)
344 break;
345 chanreq = (struct ieee80211chanreq *)data;
346 if (chanreq->i_channel == IEEE80211_CHAN_ANY)
347 ic->ic_des_chan = IEEE80211_CHAN_ANYC;
348 else if (chanreq->i_channel > IEEE80211_CHAN_MAX ||
349 isclr(ic->ic_chan_active, chanreq->i_channel)) {
350 error = EINVAL;
351 break;
352 } else
353 ic->ic_ibss_chan = ic->ic_des_chan =
354 &ic->ic_channels[chanreq->i_channel];
355 switch (ic->ic_state) {
356 case IEEE80211_S_INIT:
357 case IEEE80211_S_SCAN:
358 error = ENETRESET;
359 break;
360 default:
361 if (ic->ic_opmode == IEEE80211_M_STA) {
362 if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
363 ic->ic_bss->ni_chan != ic->ic_des_chan)
364 error = ENETRESET;
365 } else {
366 if (ic->ic_bss->ni_chan != ic->ic_ibss_chan)
367 error = ENETRESET;
368 }
369 break;
370 }
371 break;
372 case SIOCG80211CHANNEL:
373 chanreq = (struct ieee80211chanreq *)data;
374 switch (ic->ic_state) {
375 case IEEE80211_S_INIT:
376 case IEEE80211_S_SCAN:
377 if (ic->ic_opmode == IEEE80211_M_STA)
378 chan = ic->ic_des_chan;
379 else
380 chan = ic->ic_ibss_chan;
381 break;
382 default:
383 chan = ic->ic_bss->ni_chan;
384 break;
385 }
386 chanreq->i_channel = ieee80211_chan2ieee(ic, chan);
387 break;
388 #if 0
389 case SIOCG80211ZSTATS:
390 #endif
391 case SIOCG80211STATS:
392 ifr = (struct ifreq *)data;
393 copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats));
394 #if 0
395 if (cmd == SIOCG80211ZSTATS)
396 memset(&ic->ic_stats, 0, sizeof(ic->ic_stats));
397 #endif
398 break;
399 case SIOCS80211TXPOWER:
400 if ((error = suser(curproc, 0)) != 0)
401 break;
402 txpower = (struct ieee80211_txpower *)data;
403 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) {
404 error = EINVAL;
405 break;
406 }
407 if (!(IEEE80211_TXPOWER_MIN < txpower->i_val &&
408 txpower->i_val < IEEE80211_TXPOWER_MAX)) {
409 error = EINVAL;
410 break;
411 }
412 ic->ic_txpower = txpower->i_val;
413 error = ENETRESET;
414 break;
415 case SIOCG80211TXPOWER:
416 txpower = (struct ieee80211_txpower *)data;
417 if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0)
418 error = EINVAL;
419 else
420 txpower->i_val = ic->ic_txpower;
421 break;
422 case SIOCSIFMTU:
423 ifr = (struct ifreq *)data;
424 if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu &&
425 ifr->ifr_mtu <= IEEE80211_MTU_MAX))
426 error = EINVAL;
427 else
428 ifp->if_mtu = ifr->ifr_mtu;
429 break;
430 case SIOCS80211SCAN:
431 if ((error = suser(curproc, 0)) != 0)
432 break;
433 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
434 break;
435 if ((ifp->if_flags & IFF_UP) == 0) {
436 error = ENETDOWN;
437 break;
438 }
439 if ((ic->ic_scan_lock & IEEE80211_SCAN_REQUEST) == 0) {
440 if (ic->ic_scan_lock & IEEE80211_SCAN_LOCKED)
441 ic->ic_scan_lock |= IEEE80211_SCAN_RESUME;
442 ic->ic_scan_lock |= IEEE80211_SCAN_REQUEST;
443 if (ic->ic_state != IEEE80211_S_SCAN)
444 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
445 }
446
447 error = tsleep(&ic->ic_scan_lock, PCATCH, "80211scan",
448 hz * IEEE80211_SCAN_TIMEOUT);
449 break;
450 case SIOCG80211NODE:
451 nr = (struct ieee80211_nodereq *)data;
452 ni = ieee80211_find_node(ic, nr->nr_macaddr);
453 if (ni == NULL) {
454 error = ENOENT;
455 break;
456 }
457 ieee80211_node2req(ic, ni, nr);
458 break;
459 case SIOCS80211NODE:
460 if ((error = suser(curproc, 0)) != 0)
461 break;
462 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
463 error = EINVAL;
464 break;
465 }
466 nr = (struct ieee80211_nodereq *)data;
467
468 ni = ieee80211_find_node(ic, nr->nr_macaddr);
469 if (ni == NULL)
470 ni = ieee80211_alloc_node(ic, nr->nr_macaddr);
471 if (ni == NULL) {
472 error = ENOENT;
473 break;
474 }
475
476 if (nr->nr_flags & IEEE80211_NODEREQ_COPY)
477 ieee80211_req2node(ic, nr, ni);
478 break;
479 case SIOCS80211DELNODE:
480 if ((error = suser(curproc, 0)) != 0)
481 break;
482 nr = (struct ieee80211_nodereq *)data;
483 ni = ieee80211_find_node(ic, nr->nr_macaddr);
484 if (ni == NULL)
485 error = ENOENT;
486 else if (ni == ic->ic_bss)
487 error = EPERM;
488 else {
489 if (ni->ni_state == IEEE80211_STA_COLLECT)
490 break;
491
492
493 if (ni->ni_state == IEEE80211_STA_ASSOC)
494 IEEE80211_SEND_MGMT(ic, ni,
495 IEEE80211_FC0_SUBTYPE_DISASSOC,
496 IEEE80211_REASON_ASSOC_LEAVE);
497
498
499 if (ni->ni_state >= IEEE80211_STA_AUTH)
500 IEEE80211_SEND_MGMT(ic, ni,
501 IEEE80211_FC0_SUBTYPE_DEAUTH,
502 IEEE80211_REASON_AUTH_LEAVE);
503
504 ieee80211_release_node(ic, ni);
505 }
506 break;
507 case SIOCG80211ALLNODES:
508 na = (struct ieee80211_nodereq_all *)data;
509 na->na_nodes = i = 0;
510 ni = RB_MIN(ieee80211_tree, &ic->ic_tree);
511 while (ni && na->na_size >=
512 i + sizeof(struct ieee80211_nodereq)) {
513 ieee80211_node2req(ic, ni, &nrbuf);
514 error = copyout(&nrbuf, (caddr_t)na->na_node + i,
515 sizeof(struct ieee80211_nodereq));
516 if (error)
517 break;
518 i += sizeof(struct ieee80211_nodereq);
519 na->na_nodes++;
520 ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
521 }
522 break;
523 case SIOCG80211FLAGS:
524 flags = ic->ic_flags;
525 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
526 flags &= ~IEEE80211_F_HOSTAPMASK;
527 ifr->ifr_flags = flags >> IEEE80211_F_USERSHIFT;
528 break;
529 case SIOCS80211FLAGS:
530 if ((error = suser(curproc, 0)) != 0)
531 break;
532 flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
533 if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
534 (flags & IEEE80211_F_HOSTAPMASK)) {
535 error = EINVAL;
536 break;
537 }
538 ic->ic_flags = (ic->ic_flags & ~IEEE80211_F_USERMASK) | flags;
539 error = ENETRESET;
540 break;
541 default:
542 error = EINVAL;
543 break;
544 }
545 return error;
546 }