2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/errno.h>
38 #include <sys/strsun.h>
39 #include <sys/policy.h>
40 #include <inet/common.h>
44 #include <sys/mac_provider.h>
45 #include <inet/wifi_ioctl.h>
46 #include "net80211_impl.h"
48 static int wl_set_essid(struct ieee80211com
*, const void *);
49 static void wl_get_essid(struct ieee80211com
*, void *);
50 static int wl_set_bssid(struct ieee80211com
*, const void *);
51 static void wl_get_bssid(struct ieee80211com
*, void *);
52 static int wl_set_bsstype(struct ieee80211com
*, const void *);
53 static void wl_get_bsstype(struct ieee80211com
*, void *);
54 static void wl_get_linkstatus(struct ieee80211com
*, void *);
55 static int wl_set_desrates(struct ieee80211com
*, const void *);
56 static void wl_get_desrates(struct ieee80211com
*, void *);
57 static int wl_set_authmode(struct ieee80211com
*, const void *);
58 static void wl_get_authmode(struct ieee80211com
*, void *);
59 static int wl_set_encrypt(struct ieee80211com
*, const void *);
60 static void wl_get_encrypt(struct ieee80211com
*, void *);
61 static void wl_get_rssi(struct ieee80211com
*, void *);
62 static int wl_set_phy(struct ieee80211com
*, const void *);
63 static int wl_get_phy(struct ieee80211com
*, void *);
64 static void wl_get_capability(struct ieee80211com
*, void *);
65 static int wl_set_wpa(struct ieee80211com
*, const void *);
66 static void wl_get_wpa(struct ieee80211com
*, void *);
67 static void wl_get_scanresults(struct ieee80211com
*, void *);
68 static void wl_get_esslist(struct ieee80211com
*, void *);
69 static int wl_set_wepkey(struct ieee80211com
*, const void *);
70 static int wl_set_optie(struct ieee80211com
*, const void *);
71 static int wl_set_delkey(struct ieee80211com
*, const void *);
72 static int wl_set_mlme(struct ieee80211com
*, const void *);
73 static int wl_set_wpakey(struct ieee80211com
*, const void *);
74 static void wl_get_suprates(struct ieee80211com
*, void *);
75 static int wl_set_createibss(struct ieee80211com
*, const void *);
76 static void wl_get_createibss(struct ieee80211com
*, void *);
79 wifi_strnlen(const char *s
, size_t n
)
83 for (i
= 0; i
< n
&& s
[i
] != '\0'; i
++)
89 * Initialize an output message block by copying from an
90 * input message block. The message is of type wldp_t.
91 * mp input message block
92 * buflen length of wldp_buf
95 wifi_setupoutmsg(mblk_t
*mp
, int buflen
)
99 wp
= (wldp_t
*)mp
->b_rptr
;
100 wp
->wldp_length
= WIFI_BUF_OFFSET
+ buflen
;
101 wp
->wldp_result
= WL_SUCCESS
;
102 mp
->b_wptr
= mp
->b_rptr
+ wp
->wldp_length
;
106 * Allocate and initialize an output message.
109 wifi_getoutmsg(mblk_t
*mp
, uint32_t cmd
, int buflen
)
114 size
= WIFI_BUF_OFFSET
;
115 if (cmd
== WLAN_GET_PARAM
)
116 size
+= buflen
; /* to hold output parameters */
117 mp1
= allocb(size
, BPRI_HI
);
119 ieee80211_err("wifi_getoutbuf: allocb %d bytes failed!\n",
124 bzero(mp1
->b_rptr
, size
);
125 bcopy(mp
->b_rptr
, mp1
->b_rptr
, WIFI_BUF_OFFSET
);
126 wifi_setupoutmsg(mp1
, size
- WIFI_BUF_OFFSET
);
132 wifi_cfg_essid(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
135 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
137 wl_essid_t
*iw_essid
= (wl_essid_t
*)inp
->wldp_buf
;
138 wl_essid_t
*ow_essid
;
141 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_essid_t
))) == NULL
)
143 outp
= (wldp_t
*)omp
->b_rptr
;
144 ow_essid
= (wl_essid_t
*)outp
->wldp_buf
;
148 wl_get_essid(ic
, ow_essid
);
151 err
= wl_set_essid(ic
, iw_essid
);
154 ieee80211_err("wifi_cfg_essid: unknown command %x\n", cmd
);
155 outp
->wldp_result
= WL_NOTSUPPORTED
;
166 wifi_cfg_bssid(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
169 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
173 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_bssid_t
))) == NULL
)
175 outp
= (wldp_t
*)omp
->b_rptr
;
179 wl_get_bssid(ic
, outp
->wldp_buf
);
182 err
= wl_set_bssid(ic
, inp
->wldp_buf
);
183 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wifi_cfg_bssid: "
185 ieee80211_macaddr_sprintf(inp
->wldp_buf
));
188 ieee80211_err("wifi_cfg_bssid: unknown command %x\n", cmd
);
189 outp
->wldp_result
= WL_NOTSUPPORTED
;
200 wifi_cfg_nodename(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
203 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
205 wl_nodename_t
*iw_name
= (wl_nodename_t
*)inp
->wldp_buf
;
206 wl_nodename_t
*ow_name
;
211 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_nodename_t
))) == NULL
)
213 outp
= (wldp_t
*)omp
->b_rptr
;
214 ow_name
= (wl_nodename_t
*)outp
->wldp_buf
;
218 len
= wifi_strnlen((const char *)ic
->ic_nickname
,
220 ow_name
->wl_nodename_length
= len
;
221 bcopy(ic
->ic_nickname
, ow_name
->wl_nodename_name
, len
);
224 if (iw_name
->wl_nodename_length
> IEEE80211_NWID_LEN
) {
225 ieee80211_err("wifi_cfg_nodename: "
226 "node name too long, %u\n",
227 iw_name
->wl_nodename_length
);
228 outp
->wldp_result
= WL_NOTSUPPORTED
;
232 nodename
= iw_name
->wl_nodename_name
;
233 nodename
[IEEE80211_NWID_LEN
] = 0;
234 ieee80211_dbg(IEEE80211_MSG_CONFIG
,
235 "wifi_cfg_nodename: set nodename %s, len=%d\n",
236 nodename
, iw_name
->wl_nodename_length
);
238 len
= iw_name
->wl_nodename_length
;
240 bcopy(nodename
, ic
->ic_nickname
, len
);
241 if (len
< IEEE80211_NWID_LEN
)
242 ic
->ic_nickname
[len
] = 0;
245 ieee80211_err("wifi_cfg_nodename: unknown command %x\n", cmd
);
246 outp
->wldp_result
= WL_NOTSUPPORTED
;
257 wifi_cfg_phy(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
260 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
262 wl_phy_conf_t
*iw_phy
= (wl_phy_conf_t
*)inp
->wldp_buf
;
263 wl_phy_conf_t
*ow_phy
;
266 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_phy_conf_t
))) == NULL
)
268 outp
= (wldp_t
*)omp
->b_rptr
;
269 ow_phy
= (wl_phy_conf_t
*)outp
->wldp_buf
;
273 err
= wl_get_phy(ic
, ow_phy
);
277 err
= wl_set_phy(ic
, iw_phy
);
281 ieee80211_err("wifi_cfg_phy: unknown command %x\n", cmd
);
282 outp
->wldp_result
= WL_NOTSUPPORTED
;
293 wifi_cfg_wepkey(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
296 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
298 wl_wep_key_t
*iw_wepkey
= (wl_wep_key_t
*)inp
->wldp_buf
;
301 if ((omp
= wifi_getoutmsg(*mp
, cmd
, 0)) == NULL
)
303 outp
= (wldp_t
*)omp
->b_rptr
;
307 outp
->wldp_result
= WL_WRITEONLY
;
311 if (inp
->wldp_length
< sizeof (wl_wep_key_tab_t
)) {
312 ieee80211_err("wifi_cfg_wepkey: "
313 "parameter too short, %d, expected %d\n",
314 inp
->wldp_length
, sizeof (wl_wep_key_tab_t
));
315 outp
->wldp_result
= WL_NOTSUPPORTED
;
320 err
= wl_set_wepkey(ic
, iw_wepkey
);
323 ieee80211_err("wifi_cfg_wepkey: unknown command %x\n", cmd
);
324 outp
->wldp_result
= WL_NOTSUPPORTED
;
335 wifi_cfg_keyid(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
338 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
340 wl_wep_key_id_t
*iw_kid
= (wl_wep_key_id_t
*)inp
->wldp_buf
;
341 wl_wep_key_id_t
*ow_kid
;
344 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_wep_key_id_t
))) == NULL
)
346 outp
= (wldp_t
*)omp
->b_rptr
;
347 ow_kid
= (wl_wep_key_id_t
*)outp
->wldp_buf
;
351 *ow_kid
= (ic
->ic_def_txkey
== IEEE80211_KEYIX_NONE
) ?
352 0 : ic
->ic_def_txkey
;
355 if (*iw_kid
>= MAX_NWEPKEYS
) {
356 ieee80211_err("wifi_cfg_keyid: "
357 "keyid too large, %u\n", *iw_kid
);
358 outp
->wldp_result
= WL_NOTSUPPORTED
;
361 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wifi_cfg_keyid: "
362 "set keyid=%u\n", *iw_kid
);
363 ic
->ic_def_txkey
= *iw_kid
;
368 ieee80211_err("wifi_cfg_keyid: unknown command %x\n", cmd
);
369 outp
->wldp_result
= WL_NOTSUPPORTED
;
380 wifi_cfg_authmode(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
383 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
385 wl_authmode_t
*iw_auth
= (wl_authmode_t
*)inp
->wldp_buf
;
386 wl_authmode_t
*ow_auth
;
389 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_authmode_t
))) == NULL
)
391 outp
= (wldp_t
*)omp
->b_rptr
;
392 ow_auth
= (wl_authmode_t
*)outp
->wldp_buf
;
396 wl_get_authmode(ic
, ow_auth
);
399 err
= wl_set_authmode(ic
, iw_auth
);
402 ieee80211_err("wifi_cfg_authmode: unknown command %x\n", cmd
);
403 outp
->wldp_result
= WL_NOTSUPPORTED
;
414 wifi_cfg_encrypt(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
417 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
419 wl_encryption_t
*iw_encryp
= (wl_encryption_t
*)inp
->wldp_buf
;
420 wl_encryption_t
*ow_encryp
;
423 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_encryption_t
))) == NULL
)
425 outp
= (wldp_t
*)omp
->b_rptr
;
426 ow_encryp
= (wl_encryption_t
*)outp
->wldp_buf
;
430 wl_get_encrypt(ic
, ow_encryp
);
433 err
= wl_set_encrypt(ic
, iw_encryp
);
436 ieee80211_err("wifi_cfg_encrypt: unknown command %x\n", cmd
);
437 outp
->wldp_result
= WL_NOTSUPPORTED
;
448 wifi_cfg_bsstype(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
451 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
453 wl_bss_type_t
*iw_opmode
= (wl_bss_type_t
*)inp
->wldp_buf
;
454 wl_bss_type_t
*ow_opmode
;
457 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_bss_type_t
))) == NULL
)
459 outp
= (wldp_t
*)omp
->b_rptr
;
460 ow_opmode
= (wl_bss_type_t
*)outp
->wldp_buf
;
464 wl_get_bsstype(ic
, ow_opmode
);
467 if (*iw_opmode
== ic
->ic_opmode
)
470 err
= wl_set_bsstype(ic
, iw_opmode
);
473 ieee80211_err("wifi_cfg_bsstype: unknown command %x\n", cmd
);
474 outp
->wldp_result
= WL_NOTSUPPORTED
;
485 wifi_cfg_createibss(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
488 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
490 wl_create_ibss_t
*iw_ibss
= (wl_create_ibss_t
*)inp
->wldp_buf
;
491 wl_create_ibss_t
*ow_ibss
;
494 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_create_ibss_t
))) == NULL
)
496 outp
= (wldp_t
*)omp
->b_rptr
;
497 ow_ibss
= (wl_create_ibss_t
*)outp
->wldp_buf
;
501 wl_get_createibss(ic
, ow_ibss
);
504 err
= wl_set_createibss(ic
, iw_ibss
);
507 ieee80211_err("wifi_cfg_bsstype: unknown command %x\n", cmd
);
508 outp
->wldp_result
= WL_NOTSUPPORTED
;
519 wifi_cfg_linkstatus(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
523 wl_linkstatus_t
*ow_linkstat
;
526 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_linkstatus_t
))) == NULL
)
528 outp
= (wldp_t
*)omp
->b_rptr
;
529 ow_linkstat
= (wl_linkstatus_t
*)outp
->wldp_buf
;
533 wl_get_linkstatus(ic
, ow_linkstat
);
536 outp
->wldp_result
= WL_READONLY
;
540 ieee80211_err("wifi_cfg_linkstatus: unknown command %x\n", cmd
);
541 outp
->wldp_result
= WL_NOTSUPPORTED
;
552 wifi_cfg_suprates(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
556 wl_rates_t
*ow_rates
;
560 /* rate value (wl_rates_rates) is of type char */
561 buflen
= offsetof(wl_rates_t
, wl_rates_rates
) +
562 sizeof (char) * IEEE80211_MODE_MAX
* IEEE80211_RATE_MAXSIZE
;
563 if ((omp
= wifi_getoutmsg(*mp
, cmd
, buflen
)) == NULL
)
565 outp
= (wldp_t
*)omp
->b_rptr
;
566 ow_rates
= (wl_rates_t
*)outp
->wldp_buf
;
570 (void) wl_get_suprates(ic
, ow_rates
);
573 outp
->wldp_result
= WL_READONLY
;
577 ieee80211_err("wifi_cfg_suprates: unknown command %x\n", cmd
);
578 outp
->wldp_result
= WL_NOTSUPPORTED
;
589 wifi_cfg_desrates(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
591 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
592 wl_rates_t
*iw_rates
= (wl_rates_t
*)inp
->wldp_buf
;
595 wl_rates_t
*ow_rates
;
599 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_rates_t
))) == NULL
)
601 outp
= (wldp_t
*)omp
->b_rptr
;
602 ow_rates
= (wl_rates_t
*)outp
->wldp_buf
;
606 wl_get_desrates(ic
, ow_rates
);
609 err
= wl_set_desrates(ic
, iw_rates
);
612 ieee80211_err("wifi_cfg_desrates: unknown command %x\n", cmd
);
613 outp
->wldp_result
= WL_NOTSUPPORTED
;
624 * Rescale device's RSSI value to (0, 15) as required by WiFi
625 * driver IOCTLs (PSARC/2003/722)
628 wifi_getrssi(struct ieee80211_node
*in
)
630 struct ieee80211com
*ic
= in
->in_ic
;
631 wl_rssi_t rssi
, max_rssi
;
633 rssi
= ic
->ic_node_getrssi(in
);
634 max_rssi
= (ic
->ic_maxrssi
== 0) ? IEEE80211_MAXRSSI
: ic
->ic_maxrssi
;
637 else if (rssi
>= max_rssi
)
640 rssi
= rssi
* MAX_RSSI
/ max_rssi
+ 1;
646 wifi_cfg_rssi(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
653 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_rssi_t
))) == NULL
)
655 outp
= (wldp_t
*)omp
->b_rptr
;
656 ow_rssi
= (wl_rssi_t
*)outp
->wldp_buf
;
660 *ow_rssi
= wifi_getrssi(ic
->ic_bss
);
663 outp
->wldp_result
= WL_READONLY
;
667 ieee80211_err("wifi_cfg_rssi: unknown command %x\n", cmd
);
668 outp
->wldp_result
= WL_NOTSUPPORTED
;
678 * maximum scan wait time in second.
679 * Time spent on scaning one channel is usually 100~200ms. The maximum
680 * number of channels defined in wifi_ioctl.h is 99 (MAX_CHANNEL_NUM).
681 * As a result the maximum total scan time is defined as below in ms.
683 #define WAIT_SCAN_MAX (200 * MAX_CHANNEL_NUM)
686 wifi_wait_scan(struct ieee80211com
*ic
)
688 ieee80211_impl_t
*im
= ic
->ic_private
;
689 clock_t delta
= drv_usectohz(WAIT_SCAN_MAX
* 1000);
691 while ((ic
->ic_flags
& (IEEE80211_F_SCAN
| IEEE80211_F_ASCAN
)) != 0) {
692 if (cv_reltimedwait_sig(&im
->im_scan_cv
, &ic
->ic_genlock
,
693 delta
, TR_CLOCK_TICK
) != 0) {
699 #define WIFI_HAVE_CAP(in, flag) (((in)->in_capinfo & (flag)) ? 1 : 0)
700 #define WIFI_HAVE_HTCAP(in) (((in)->in_htcap != 0) ? 1 : 0)
703 * Callback function used by ieee80211_iterate_nodes() in
704 * wifi_cfg_esslist() to get info of each node in a node table
705 * arg output buffer, pointer to wl_ess_list_t
706 * in each node in the node table
709 wifi_read_ap(void *arg
, struct ieee80211_node
*in
)
711 wl_ess_list_t
*aps
= arg
;
712 ieee80211com_t
*ic
= in
->in_ic
;
713 struct ieee80211_channel
*chan
= in
->in_chan
;
714 struct ieee80211_rateset
*rates
= &(in
->in_rates
);
719 end
= (uint8_t *)aps
- WIFI_BUF_OFFSET
+ MAX_BUF_LEN
-
720 sizeof (wl_ess_list_t
);
721 conf
= &aps
->wl_ess_list_ess
[aps
->wl_ess_list_num
];
722 if ((uint8_t *)conf
> end
)
725 conf
->wl_ess_conf_length
= sizeof (struct wl_ess_conf
);
727 /* skip newly allocated NULL bss node */
728 if (IEEE80211_ADDR_EQ(in
->in_macaddr
, ic
->ic_macaddr
))
731 conf
->wl_ess_conf_essid
.wl_essid_length
= in
->in_esslen
;
732 bcopy(in
->in_essid
, conf
->wl_ess_conf_essid
.wl_essid_essid
,
734 bcopy(in
->in_bssid
, conf
->wl_ess_conf_bssid
, IEEE80211_ADDR_LEN
);
735 conf
->wl_ess_conf_wepenabled
=
736 (in
->in_capinfo
& IEEE80211_CAPINFO_PRIVACY
?
737 WL_ENC_WEP
: WL_NOENCRYPTION
);
738 conf
->wl_ess_conf_bsstype
=
739 (in
->in_capinfo
& IEEE80211_CAPINFO_ESS
?
740 WL_BSS_BSS
: WL_BSS_IBSS
);
741 conf
->wl_ess_conf_sl
= wifi_getrssi(in
);
742 conf
->wl_ess_conf_reserved
[0] = (in
->in_wpa_ie
== NULL
? 0 : 1);
744 /* physical (FH, DS, ERP) parameters */
745 if (IEEE80211_IS_CHAN_A(chan
) || IEEE80211_IS_CHAN_T(chan
)) {
747 (wl_ofdm_t
*)&((conf
->wl_phy_conf
).wl_phy_ofdm_conf
);
748 ofdm
->wl_ofdm_subtype
= WL_OFDM
;
749 ofdm
->wl_ofdm_frequency
= chan
->ich_freq
;
750 ofdm
->wl_ofdm_ht_enabled
= WIFI_HAVE_HTCAP(in
);
752 switch (in
->in_phytype
) {
753 case IEEE80211_T_FH
: {
754 wl_fhss_t
*fhss
= (wl_fhss_t
*)
755 &((conf
->wl_phy_conf
).wl_phy_fhss_conf
);
757 fhss
->wl_fhss_subtype
= WL_FHSS
;
758 fhss
->wl_fhss_channel
= ieee80211_chan2ieee(ic
, chan
);
759 fhss
->wl_fhss_dwelltime
= in
->in_fhdwell
;
762 case IEEE80211_T_DS
: {
763 wl_dsss_t
*dsss
= (wl_dsss_t
*)
764 &((conf
->wl_phy_conf
).wl_phy_dsss_conf
);
766 dsss
->wl_dsss_subtype
= WL_DSSS
;
767 dsss
->wl_dsss_channel
= ieee80211_chan2ieee(ic
, chan
);
768 dsss
->wl_dsss_have_short_preamble
= WIFI_HAVE_CAP(in
,
769 IEEE80211_CAPINFO_SHORT_PREAMBLE
);
770 dsss
->wl_dsss_agility_enabled
= WIFI_HAVE_CAP(in
,
771 IEEE80211_CAPINFO_CHNL_AGILITY
);
772 dsss
->wl_dsss_have_pbcc
= dsss
->wl_dsss_pbcc_enable
=
773 WIFI_HAVE_CAP(in
, IEEE80211_CAPINFO_PBCC
);
776 case IEEE80211_T_OFDM
: {
777 wl_erp_t
*erp
= (wl_erp_t
*)
778 &((conf
->wl_phy_conf
).wl_phy_erp_conf
);
780 erp
->wl_erp_subtype
= WL_ERP
;
781 erp
->wl_erp_channel
= ieee80211_chan2ieee(ic
, chan
);
782 erp
->wl_erp_have_short_preamble
= WIFI_HAVE_CAP(in
,
783 IEEE80211_CAPINFO_SHORT_PREAMBLE
);
784 erp
->wl_erp_have_agility
= erp
->wl_erp_agility_enabled
=
785 WIFI_HAVE_CAP(in
, IEEE80211_CAPINFO_CHNL_AGILITY
);
786 erp
->wl_erp_have_pbcc
= erp
->wl_erp_pbcc_enabled
=
787 WIFI_HAVE_CAP(in
, IEEE80211_CAPINFO_PBCC
);
788 erp
->wl_erp_dsss_ofdm_enabled
=
789 WIFI_HAVE_CAP(in
, IEEE80211_CAPINFO_DSSSOFDM
);
790 erp
->wl_erp_sst_enabled
= WIFI_HAVE_CAP(in
,
791 IEEE80211_CAPINFO_SHORT_SLOTTIME
);
792 erp
->wl_erp_ht_enabled
= WIFI_HAVE_HTCAP(in
);
794 } /* case IEEE80211_T_OFDM */
795 } /* switch in->in_phytype */
798 /* supported rates */
799 nrates
= MIN(rates
->ir_nrates
, MAX_SCAN_SUPPORT_RATES
);
801 * The number of supported rates might exceed
802 * MAX_SCAN_SUPPORT_RATES. Fill in highest rates
803 * first so userland command could properly show
804 * maximum speed of AP
806 for (i
= 0; i
< nrates
; i
++) {
807 conf
->wl_supported_rates
[i
] =
808 rates
->ir_rates
[rates
->ir_nrates
- i
- 1];
811 aps
->wl_ess_list_num
++;
815 wifi_cfg_esslist(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
819 wl_ess_list_t
*ow_aps
;
822 if ((omp
= wifi_getoutmsg(*mp
, cmd
, MAX_BUF_LEN
- WIFI_BUF_OFFSET
)) ==
826 outp
= (wldp_t
*)omp
->b_rptr
;
827 ow_aps
= (wl_ess_list_t
*)outp
->wldp_buf
;
831 ow_aps
->wl_ess_list_num
= 0;
832 ieee80211_iterate_nodes(&ic
->ic_scan
, wifi_read_ap
, ow_aps
);
833 outp
->wldp_length
= WIFI_BUF_OFFSET
+
834 offsetof(wl_ess_list_t
, wl_ess_list_ess
) +
835 ow_aps
->wl_ess_list_num
* sizeof (wl_ess_conf_t
);
836 omp
->b_wptr
= omp
->b_rptr
+ outp
->wldp_length
;
839 outp
->wldp_result
= WL_READONLY
;
843 ieee80211_err("wifi_cfg_esslist: unknown command %x\n", cmd
);
844 outp
->wldp_result
= WL_NOTSUPPORTED
;
855 * Scan the network for all available ESSs.
856 * IEEE80211_F_SCANONLY is set when current state is INIT. And
857 * with this flag, after scan the state will be changed back to
858 * INIT. The reason is at the end of SCAN stage, the STA will
859 * consequently connect to an AP. Then it looks unreasonable that
860 * for a disconnected device, A SCAN command causes it connected.
861 * So the state is changed back to INIT.
864 wifi_cmd_scan(struct ieee80211com
*ic
, mblk_t
*mp
)
866 int ostate
= ic
->ic_state
;
869 * Do not scan when current state is RUN. The reason is
870 * when connected, STA is on the same channel as AP. But
871 * to do scan, STA have to switch to each available channel,
872 * send probe request and wait certian time for probe
873 * response/beacon. Then when the STA switches to a channel
874 * different than AP's, as a result it cannot send/receive
875 * data packets to/from the connected WLAN. This eventually
876 * will cause data loss.
878 if (ostate
== IEEE80211_S_RUN
)
881 IEEE80211_UNLOCK(ic
);
883 ieee80211_new_state(ic
, IEEE80211_S_SCAN
, -1);
885 if (ostate
== IEEE80211_S_INIT
)
886 ic
->ic_flags
|= IEEE80211_F_SCANONLY
;
888 /* Don't wait on WPA mode */
889 if ((ic
->ic_flags
& IEEE80211_F_WPA
) == 0) {
890 /* wait scan complete */
894 wifi_setupoutmsg(mp
, 0);
899 wifi_loaddefdata(struct ieee80211com
*ic
)
901 struct ieee80211_node
*in
= ic
->ic_bss
;
904 ic
->ic_des_esslen
= 0;
905 bzero(ic
->ic_des_essid
, IEEE80211_NWID_LEN
);
906 ic
->ic_flags
&= ~IEEE80211_F_DESBSSID
;
907 bzero(ic
->ic_des_bssid
, IEEE80211_ADDR_LEN
);
908 bzero(ic
->ic_bss
->in_bssid
, IEEE80211_ADDR_LEN
);
909 ic
->ic_des_chan
= IEEE80211_CHAN_ANYC
;
910 ic
->ic_fixed_rate
= IEEE80211_FIXED_RATE_NONE
;
911 bzero(ic
->ic_nickname
, IEEE80211_NWID_LEN
);
912 in
->in_authmode
= IEEE80211_AUTH_OPEN
;
913 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
914 ic
->ic_flags
&= ~IEEE80211_F_WPA
; /* mask WPA mode */
915 ic
->ic_evq_head
= ic
->ic_evq_tail
= 0; /* reset Queue */
916 ic
->ic_def_txkey
= 0;
917 for (i
= 0; i
< MAX_NWEPKEYS
; i
++) {
918 ic
->ic_nw_keys
[i
].wk_keylen
= 0;
919 bzero(ic
->ic_nw_keys
[i
].wk_key
, IEEE80211_KEYBUF_SIZE
);
921 ic
->ic_curmode
= IEEE80211_MODE_AUTO
;
922 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
923 ic
->ic_opmode
= IEEE80211_M_STA
;
927 wifi_cmd_loaddefaults(struct ieee80211com
*ic
, mblk_t
*mp
)
929 wifi_loaddefdata(ic
);
930 wifi_setupoutmsg(mp
, 0);
935 wifi_cmd_disassoc(struct ieee80211com
*ic
, mblk_t
*mp
)
937 if (ic
->ic_state
!= IEEE80211_S_INIT
) {
938 IEEE80211_UNLOCK(ic
);
939 (void) ieee80211_new_state(ic
, IEEE80211_S_INIT
, -1);
942 wifi_loaddefdata(ic
);
943 wifi_setupoutmsg(mp
, 0);
948 * Get the capabilities of drivers.
951 wifi_cfg_caps(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
955 wl_capability_t
*o_caps
;
958 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_capability_t
))) == NULL
)
960 outp
= (wldp_t
*)omp
->b_rptr
;
961 o_caps
= (wl_capability_t
*)outp
->wldp_buf
;
965 wl_get_capability(ic
, o_caps
);
968 outp
->wldp_result
= WL_READONLY
;
972 ieee80211_err("wifi_cfg_caps: unknown command %x\n", cmd
);
973 outp
->wldp_result
= WL_NOTSUPPORTED
;
984 * Operating on WPA mode.
987 wifi_cfg_wpa(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
991 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
992 wl_wpa_t
*wpa
= (wl_wpa_t
*)inp
->wldp_buf
;
996 if ((omp
= wifi_getoutmsg(*mp
, cmd
, sizeof (wl_wpa_t
))) == NULL
)
998 outp
= (wldp_t
*)omp
->b_rptr
;
999 o_wpa
= (wl_wpa_t
*)outp
->wldp_buf
;
1002 case WLAN_GET_PARAM
:
1003 wl_get_wpa(ic
, o_wpa
);
1005 case WLAN_SET_PARAM
:
1006 err
= wl_set_wpa(ic
, wpa
);
1009 ieee80211_err("wifi_cfg_wpa: unknown command %x\n", cmd
);
1010 outp
->wldp_result
= WL_NOTSUPPORTED
;
1021 * WPA daemon set the WPA keys.
1022 * The WPA keys are negotiated with APs through wpa service.
1025 wifi_cfg_wpakey(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
1029 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
1030 wl_key_t
*ik
= (wl_key_t
*)(inp
->wldp_buf
);
1033 if ((omp
= wifi_getoutmsg(*mp
, cmd
, 0)) == NULL
)
1035 outp
= (wldp_t
*)omp
->b_rptr
;
1038 case WLAN_GET_PARAM
:
1039 outp
->wldp_result
= WL_WRITEONLY
;
1042 case WLAN_SET_PARAM
:
1043 err
= wl_set_wpakey(ic
, ik
);
1046 ieee80211_err("wifi_cfg_wpakey: unknown command %x\n", cmd
);
1047 outp
->wldp_result
= WL_NOTSUPPORTED
;
1058 * Delete obsolete keys - keys are dynamically exchanged between APs
1062 wifi_cfg_delkey(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
1066 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
1067 wl_del_key_t
*dk
= (wl_del_key_t
*)inp
->wldp_buf
;
1070 if ((omp
= wifi_getoutmsg(*mp
, cmd
, 0)) == NULL
)
1072 outp
= (wldp_t
*)omp
->b_rptr
;
1075 case WLAN_GET_PARAM
:
1076 outp
->wldp_result
= WL_WRITEONLY
;
1079 case WLAN_SET_PARAM
:
1080 err
= wl_set_delkey(ic
, dk
);
1083 ieee80211_err("wifi_cfg_delkey: unknown command %x\n", cmd
);
1084 outp
->wldp_result
= WL_NOTSUPPORTED
;
1095 * The OPTIE will be used in the association request.
1098 wifi_cfg_setoptie(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
1102 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
1103 wl_wpa_ie_t
*ie_in
= (wl_wpa_ie_t
*)inp
->wldp_buf
;
1106 if ((omp
= wifi_getoutmsg(*mp
, cmd
, 0)) == NULL
)
1108 outp
= (wldp_t
*)omp
->b_rptr
;
1111 case WLAN_GET_PARAM
:
1112 outp
->wldp_result
= WL_WRITEONLY
;
1115 case WLAN_SET_PARAM
:
1116 if ((err
= wl_set_optie(ic
, ie_in
)) == EINVAL
)
1117 outp
->wldp_result
= WL_NOTSUPPORTED
;
1120 ieee80211_err("wifi_cfg_setoptie: unknown command %x\n", cmd
);
1121 outp
->wldp_result
= WL_NOTSUPPORTED
;
1132 * To be compatible with drivers/tools of OpenSolaris.org,
1133 * we use a different ID to filter out those APs of WPA mode.
1136 wifi_cfg_scanresults(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
1141 ieee80211_node_t
*in
;
1142 ieee80211_node_table_t
*nt
;
1143 int len
, ap_num
= 0;
1146 if ((omp
= wifi_getoutmsg(*mp
, cmd
, MAX_BUF_LEN
- WIFI_BUF_OFFSET
)) ==
1150 outp
= (wldp_t
*)omp
->b_rptr
;
1151 sr
= (wl_wpa_ess_t
*)outp
->wldp_buf
;
1155 case WLAN_GET_PARAM
:
1156 ieee80211_dbg(IEEE80211_MSG_WPA
, "wifi_cfg_scanresults\n");
1158 IEEE80211_NODE_LOCK(nt
);
1159 in
= list_head(&nt
->nt_node
);
1160 while (in
!= NULL
) {
1161 /* filter out non-WPA APs */
1162 if (in
->in_wpa_ie
== NULL
) {
1163 in
= list_next(&nt
->nt_node
, in
);
1166 bcopy(in
->in_bssid
, sr
->ess
[ap_num
].bssid
,
1167 IEEE80211_ADDR_LEN
);
1168 sr
->ess
[ap_num
].ssid_len
= in
->in_esslen
;
1169 bcopy(in
->in_essid
, sr
->ess
[ap_num
].ssid
,
1171 sr
->ess
[ap_num
].freq
= in
->in_chan
->ich_freq
;
1173 len
= in
->in_wpa_ie
[1] + 2;
1174 bcopy(in
->in_wpa_ie
, sr
->ess
[ap_num
].wpa_ie
, len
);
1175 sr
->ess
[ap_num
].wpa_ie_len
= len
;
1178 in
= list_next(&nt
->nt_node
, in
);
1180 IEEE80211_NODE_UNLOCK(nt
);
1182 outp
->wldp_length
= WIFI_BUF_OFFSET
+
1183 offsetof(wl_wpa_ess_t
, ess
) +
1184 sr
->count
* sizeof (struct wpa_ess
);
1185 omp
->b_wptr
= omp
->b_rptr
+ outp
->wldp_length
;
1187 case WLAN_SET_PARAM
:
1188 outp
->wldp_result
= WL_READONLY
;
1192 ieee80211_err("wifi_cfg_scanresults: unknown cmmand %x\n", cmd
);
1193 outp
->wldp_result
= WL_NOTSUPPORTED
;
1204 * Manually control the state of AUTH | DEAUTH | DEASSOC | ASSOC
1207 wifi_cfg_setmlme(struct ieee80211com
*ic
, uint32_t cmd
, mblk_t
**mp
)
1211 wldp_t
*inp
= (wldp_t
*)(*mp
)->b_rptr
;
1212 wl_mlme_t
*mlme
= (wl_mlme_t
*)inp
->wldp_buf
;
1215 if ((omp
= wifi_getoutmsg(*mp
, cmd
, 0)) == NULL
)
1217 outp
= (wldp_t
*)omp
->b_rptr
;
1220 case WLAN_GET_PARAM
:
1221 outp
->wldp_result
= WL_WRITEONLY
;
1224 case WLAN_SET_PARAM
:
1225 err
= wl_set_mlme(ic
, mlme
);
1228 ieee80211_err("wifi_cfg_delkey: unknown command %x\n", cmd
);
1229 outp
->wldp_result
= WL_NOTSUPPORTED
;
1240 wifi_cfg_getset(struct ieee80211com
*ic
, mblk_t
**mp
, uint32_t cmd
)
1243 wldp_t
*wp
= (wldp_t
*)mp1
->b_rptr
;
1246 ASSERT(ic
!= NULL
&& mp1
!= NULL
);
1247 IEEE80211_LOCK_ASSERT(ic
);
1248 if (MBLKL(mp1
) < WIFI_BUF_OFFSET
) {
1249 ieee80211_err("wifi_cfg_getset: "
1250 "invalid input buffer, size=%d\n", MBLKL(mp1
));
1254 switch (wp
->wldp_id
) {
1257 err
= wifi_cmd_scan(ic
, mp1
);
1259 case WL_LOAD_DEFAULTS
:
1260 err
= wifi_cmd_loaddefaults(ic
, mp1
);
1262 case WL_DISASSOCIATE
:
1263 err
= wifi_cmd_disassoc(ic
, mp1
);
1267 err
= wifi_cfg_essid(ic
, cmd
, mp
);
1270 err
= wifi_cfg_bssid(ic
, cmd
, mp
);
1273 err
= wifi_cfg_nodename(ic
, cmd
, mp
);
1276 err
= wifi_cfg_phy(ic
, cmd
, mp
);
1278 case WL_WEP_KEY_TAB
:
1279 err
= wifi_cfg_wepkey(ic
, cmd
, mp
);
1282 err
= wifi_cfg_keyid(ic
, cmd
, mp
);
1285 err
= wifi_cfg_authmode(ic
, cmd
, mp
);
1288 err
= wifi_cfg_encrypt(ic
, cmd
, mp
);
1291 err
= wifi_cfg_bsstype(ic
, cmd
, mp
);
1293 case WL_CREATE_IBSS
:
1294 err
= wifi_cfg_createibss(ic
, cmd
, mp
);
1296 case WL_DESIRED_RATES
:
1297 err
= wifi_cfg_desrates(ic
, cmd
, mp
);
1300 err
= wifi_cfg_linkstatus(ic
, cmd
, mp
);
1303 err
= wifi_cfg_esslist(ic
, cmd
, mp
);
1305 case WL_SUPPORTED_RATES
:
1306 err
= wifi_cfg_suprates(ic
, cmd
, mp
);
1309 err
= wifi_cfg_rssi(ic
, cmd
, mp
);
1315 err
= wifi_cfg_caps(ic
, cmd
, mp
);
1318 err
= wifi_cfg_wpa(ic
, cmd
, mp
);
1321 err
= wifi_cfg_wpakey(ic
, cmd
, mp
);
1324 err
= wifi_cfg_delkey(ic
, cmd
, mp
);
1327 err
= wifi_cfg_setoptie(ic
, cmd
, mp
);
1329 case WL_SCANRESULTS
:
1330 err
= wifi_cfg_scanresults(ic
, cmd
, mp
);
1333 err
= wifi_cfg_setmlme(ic
, cmd
, mp
);
1336 wifi_setupoutmsg(mp1
, 0);
1337 wp
->wldp_result
= WL_LACK_FEATURE
;
1346 * Typically invoked by drivers in response to requests for
1347 * information or to change settings from the userland.
1349 * Return value should be checked by WiFi drivers. Return 0
1350 * on success. Otherwise, return non-zero value to indicate
1351 * the error. Driver should operate as below when the return
1353 * ENETRESET Reset wireless network and re-start to join a
1354 * WLAN. ENETRESET is returned when a configuration
1355 * parameter has been changed.
1356 * When acknowledge a M_IOCTL message, thie error
1360 ieee80211_ioctl(struct ieee80211com
*ic
, queue_t
*wq
, mblk_t
*mp
)
1362 struct iocblk
*iocp
;
1363 int32_t cmd
, err
, len
;
1364 boolean_t need_privilege
;
1367 if (MBLKL(mp
) < sizeof (struct iocblk
)) {
1368 ieee80211_err("ieee80211_ioctl: ioctl buffer too short, %u\n",
1370 miocnak(wq
, mp
, 0, EINVAL
);
1375 * Validate the command
1377 iocp
= (struct iocblk
*)mp
->b_rptr
;
1378 iocp
->ioc_error
= 0;
1379 cmd
= iocp
->ioc_cmd
;
1380 need_privilege
= B_TRUE
;
1382 case WLAN_SET_PARAM
:
1385 case WLAN_GET_PARAM
:
1386 need_privilege
= B_FALSE
;
1389 ieee80211_dbg(IEEE80211_MSG_ANY
, "ieee80211_ioctl(): "
1390 "unknown cmd 0x%x\n", cmd
);
1391 miocnak(wq
, mp
, 0, EINVAL
);
1395 if (need_privilege
&& (err
= secpolicy_dl_config(iocp
->ioc_cr
)) != 0) {
1396 miocnak(wq
, mp
, 0, err
);
1404 if (iocp
->ioc_count
== 0 || iocp
->ioc_count
< sizeof (wldp_t
) ||
1406 miocnak(wq
, mp
, 0, EINVAL
);
1407 IEEE80211_UNLOCK(ic
);
1411 /* assuming single data block */
1412 if (mp1
->b_cont
!= NULL
) {
1413 freemsg(mp1
->b_cont
);
1417 err
= wifi_cfg_getset(ic
, &mp1
, cmd
);
1419 IEEE80211_UNLOCK(ic
);
1421 len
= msgdsize(mp1
);
1422 /* ignore ENETRESET when acknowledge the M_IOCTL message */
1423 if (err
== 0 || err
== ENETRESET
)
1424 miocack(wq
, mp
, len
, 0);
1426 miocack(wq
, mp
, len
, err
);
1432 * The following routines are for brussels support
1439 wl_set_essid(struct ieee80211com
*ic
, const void *wldp_buf
)
1443 wl_essid_t
*iw_essid
= (wl_essid_t
*)wldp_buf
;
1445 if (iw_essid
->wl_essid_length
> IEEE80211_NWID_LEN
) {
1446 ieee80211_err("wl_set_essid: "
1447 "essid too long, %u, max %u\n",
1448 iw_essid
->wl_essid_length
, IEEE80211_NWID_LEN
);
1454 essid
= iw_essid
->wl_essid_essid
;
1455 essid
[IEEE80211_NWID_LEN
] = 0;
1457 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_essid: "
1458 "set essid=%s length=%d\n",
1459 essid
, iw_essid
->wl_essid_length
);
1461 ic
->ic_des_esslen
= iw_essid
->wl_essid_length
;
1462 if (ic
->ic_des_esslen
!= 0)
1463 bcopy(essid
, ic
->ic_des_essid
, ic
->ic_des_esslen
);
1464 if (ic
->ic_des_esslen
< IEEE80211_NWID_LEN
)
1465 ic
->ic_des_essid
[ic
->ic_des_esslen
] = 0;
1473 wl_get_essid(struct ieee80211com
*ic
, void *wldp_buf
)
1476 wl_essid_t ow_essid
;
1478 essid
= (char *)ic
->ic_des_essid
;
1479 if (essid
[0] == '\0')
1480 essid
= (char *)ic
->ic_bss
->in_essid
;
1482 bzero(&ow_essid
, sizeof (wl_essid_t
));
1483 ow_essid
.wl_essid_length
= wifi_strnlen((const char *)essid
,
1484 IEEE80211_NWID_LEN
);
1485 bcopy(essid
, ow_essid
.wl_essid_essid
,
1486 ow_essid
.wl_essid_length
);
1487 bcopy(&ow_essid
, wldp_buf
, sizeof (wl_essid_t
));
1495 wl_set_bssid(struct ieee80211com
*ic
, const void* wldp_buf
)
1498 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_bssid: "
1500 ieee80211_macaddr_sprintf(wldp_buf
));
1502 bcopy(wldp_buf
, ic
->ic_des_bssid
, sizeof (wl_bssid_t
));
1503 ic
->ic_flags
|= IEEE80211_F_DESBSSID
;
1509 wl_get_bssid(struct ieee80211com
*ic
, void *wldp_buf
)
1513 if (ic
->ic_flags
& IEEE80211_F_DESBSSID
)
1514 bssid
= ic
->ic_des_bssid
;
1516 bssid
= ic
->ic_bss
->in_bssid
;
1517 bcopy(bssid
, wldp_buf
, sizeof (wl_bssid_t
));
1522 * MAC_PROP_WL_BSSTYP
1525 wl_set_bsstype(struct ieee80211com
*ic
, const void *wldp_buf
)
1528 wl_bss_type_t
*iw_opmode
= (wl_bss_type_t
*)wldp_buf
;
1530 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_bsstype: "
1531 "set bsstype=%u\n", *iw_opmode
);
1533 switch (*iw_opmode
) {
1535 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
1536 ic
->ic_opmode
= IEEE80211_M_STA
;
1540 if ((ic
->ic_caps
& IEEE80211_C_IBSS
) == 0) {
1545 ic
->ic_opmode
= IEEE80211_M_IBSS
;
1549 ieee80211_err("wl_set_bsstype: "
1550 "unknown opmode\n");
1558 wl_get_bsstype(struct ieee80211com
*ic
, void *wldp_buf
)
1560 wl_bss_type_t ow_opmode
;
1562 switch (ic
->ic_opmode
) {
1563 case IEEE80211_M_STA
:
1564 ow_opmode
= WL_BSS_BSS
;
1566 case IEEE80211_M_IBSS
:
1567 ow_opmode
= WL_BSS_IBSS
;
1570 ow_opmode
= WL_BSS_ANY
;
1574 bcopy(&ow_opmode
, wldp_buf
, sizeof (wl_bss_type_t
));
1578 * MAC_PROP_WL_LINKSTATUS
1581 wl_get_linkstatus(struct ieee80211com
*ic
, void *wldp_buf
)
1583 wl_linkstatus_t ow_linkstat
;
1585 ow_linkstat
= (ic
->ic_state
== IEEE80211_S_RUN
) ?
1586 WL_CONNECTED
: WL_NOTCONNECTED
;
1587 if ((ic
->ic_flags
& IEEE80211_F_WPA
) &&
1588 (ieee80211_crypto_getciphertype(ic
) != WIFI_SEC_WPA
)) {
1589 ow_linkstat
= WL_NOTCONNECTED
;
1592 bcopy(&ow_linkstat
, wldp_buf
, sizeof (wl_linkstatus_t
));
1596 * MAC_PROP_WL_DESIRED_RATESa
1599 wl_set_desrates(struct ieee80211com
*ic
, const void *wldp_buf
)
1605 wl_rates_t
*iw_rates
= (wl_rates_t
*)wldp_buf
;
1606 struct ieee80211_node
*in
= ic
->ic_bss
;
1607 struct ieee80211_rateset
*rs
= &in
->in_rates
;
1609 drate
= iw_rates
->wl_rates_rates
[0];
1610 if (ic
->ic_fixed_rate
== drate
)
1613 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_desrates: "
1614 "set desired rate=%u\n", drate
);
1617 ic
->ic_fixed_rate
= IEEE80211_FIXED_RATE_NONE
;
1618 if (ic
->ic_state
== IEEE80211_S_RUN
) {
1619 IEEE80211_UNLOCK(ic
);
1620 ieee80211_new_state(ic
, IEEE80211_S_ASSOC
, 0);
1627 * Set desired rate. The desired rate is for data transfer
1628 * and usally is checked and used when driver changes to
1630 * If the driver is in AUTH | ASSOC | RUN state, desired
1631 * rate is checked anainst rates supported by current ESS.
1632 * If it's supported and current state is AUTH|ASSOC, nothing
1633 * needs to be done by driver since the desired rate will
1634 * be enabled when the device changes to RUN state. And
1635 * when current state is RUN, Re-associate with the ESS to
1636 * enable the desired rate.
1639 if (ic
->ic_state
!= IEEE80211_S_INIT
&&
1640 ic
->ic_state
!= IEEE80211_S_SCAN
) {
1641 for (i
= 0; i
< rs
->ir_nrates
; i
++) {
1642 if (drate
== IEEE80211_RV(rs
->ir_rates
[i
]))
1646 if (i
< rs
->ir_nrates
) {
1647 ic
->ic_fixed_rate
= drate
;
1648 if (ic
->ic_state
== IEEE80211_S_RUN
) {
1649 IEEE80211_UNLOCK(ic
);
1650 ieee80211_new_state(ic
,
1651 IEEE80211_S_ASSOC
, 0);
1659 * In INIT or SCAN state
1660 * check if the desired rate is supported by device
1663 for (i
= 0; i
< IEEE80211_MODE_MAX
; i
++) {
1664 rs
= &ic
->ic_sup_rates
[i
];
1665 for (j
= 0; j
< rs
->ir_nrates
; j
++) {
1666 if (drate
== IEEE80211_RV(rs
->ir_rates
[j
])) {
1675 ieee80211_err("wl_set_desrates: "
1676 "invald rate %d\n", drate
);
1680 ic
->ic_fixed_rate
= drate
;
1681 if (ic
->ic_state
!= IEEE80211_S_SCAN
)
1688 wl_get_desrates(struct ieee80211com
*ic
, void *wldp_buf
)
1691 wl_rates_t ow_rates
;
1692 struct ieee80211_node
*in
= ic
->ic_bss
;
1693 struct ieee80211_rateset
*rs
= &in
->in_rates
;
1695 srate
= rs
->ir_rates
[in
->in_txrate
] & IEEE80211_RATE_VAL
;
1696 ow_rates
.wl_rates_num
= 1;
1697 ow_rates
.wl_rates_rates
[0] =
1698 (ic
->ic_fixed_rate
== IEEE80211_FIXED_RATE_NONE
) ?
1699 srate
: ic
->ic_fixed_rate
;
1700 bcopy(&ow_rates
, wldp_buf
, sizeof (wl_rates_t
));
1705 * MAC_PROP_AUTH_MODE
1708 wl_set_authmode(struct ieee80211com
*ic
, const void *wldp_buf
)
1711 wl_authmode_t
*iw_auth
= (wl_authmode_t
*)wldp_buf
;
1713 if (*iw_auth
== ic
->ic_bss
->in_authmode
)
1716 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_authmode: "
1717 "set authmode=%u\n", *iw_auth
);
1722 ic
->ic_bss
->in_authmode
= *iw_auth
;
1726 ieee80211_err("wl_set_authmode: "
1727 "unknown authmode %u\n", *iw_auth
);
1736 wl_get_authmode(struct ieee80211com
*ic
, void *wldp_buf
)
1738 wl_authmode_t ow_auth
;
1740 ow_auth
= ic
->ic_bss
->in_authmode
;
1741 bcopy(&ow_auth
, wldp_buf
, sizeof (wl_authmode_t
));
1746 * MAC_PROP_WL_ENCRYPTION
1749 wl_set_encrypt(struct ieee80211com
*ic
, const void *wldp_buf
)
1753 wl_encryption_t
*iw_encryp
= (wl_encryption_t
*)wldp_buf
;
1755 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_encrypt: "
1756 "set encryption=%u\n", *iw_encryp
);
1758 flags
= ic
->ic_flags
;
1759 if (*iw_encryp
== WL_NOENCRYPTION
)
1760 flags
&= ~IEEE80211_F_PRIVACY
;
1762 flags
|= IEEE80211_F_PRIVACY
;
1764 if (ic
->ic_flags
!= flags
) {
1765 ic
->ic_flags
= flags
;
1773 wl_get_encrypt(struct ieee80211com
*ic
, void *wldp_buf
)
1775 wl_encryption_t
*ow_encryp
;
1777 ow_encryp
= (wl_encryption_t
*)wldp_buf
;
1778 *ow_encryp
= (ic
->ic_flags
& IEEE80211_F_PRIVACY
) ? 1 : 0;
1779 if (ic
->ic_flags
& IEEE80211_F_WPA
)
1780 *ow_encryp
= WL_ENC_WPA
;
1788 wl_get_rssi(struct ieee80211com
*ic
, void *wldp_buf
)
1792 ow_rssi
= (wl_rssi_t
*)wldp_buf
;
1793 *ow_rssi
= wifi_getrssi(ic
->ic_bss
);
1798 * MAC_PROP_WL_PHY_CONFIG
1802 wl_set_phy(struct ieee80211com
*ic
, const void* wldp_buf
)
1807 wl_phy_conf_t
*iw_phy
= (wl_phy_conf_t
*)wldp_buf
;
1809 dsss
= (wl_dsss_t
*)iw_phy
;
1810 ch
= dsss
->wl_dsss_channel
;
1812 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_phy: "
1813 "set channel=%d\n", ch
);
1815 if (ch
== 0 || ch
== (int16_t)IEEE80211_CHAN_ANY
) {
1816 ic
->ic_des_chan
= IEEE80211_CHAN_ANYC
;
1817 } else if ((uint_t
)ch
> IEEE80211_CHAN_MAX
||
1818 ieee80211_isclr(ic
->ic_chan_active
, ch
)) {
1822 ic
->ic_des_chan
= ic
->ic_ibss_chan
=
1823 &ic
->ic_sup_channels
[ch
];
1826 switch (ic
->ic_state
) {
1827 case IEEE80211_S_INIT
:
1828 case IEEE80211_S_SCAN
:
1833 * If hte desired channel has changed (to something
1834 * other than any) and we're not already scanning,
1835 * then kick the state machine.
1837 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
&&
1838 ic
->ic_bss
->in_chan
!= ic
->ic_des_chan
&&
1839 (ic
->ic_flags
& IEEE80211_F_SCAN
) == 0)
1847 #define WIFI_HT_MODE(in) (((in)->in_flags & IEEE80211_NODE_HT) ? 1 : 0)
1850 wl_get_phy(struct ieee80211com
*ic
, void *wldp_buf
)
1853 wl_phy_conf_t
*ow_phy
;
1854 struct ieee80211_channel
*ch
= ic
->ic_curchan
;
1855 struct ieee80211_node
*in
= ic
->ic_bss
;
1857 ow_phy
= (wl_phy_conf_t
*)wldp_buf
;
1858 bzero(wldp_buf
, sizeof (wl_phy_conf_t
));
1860 /* get current phy parameters: FH|DS|ERP */
1861 if (IEEE80211_IS_CHAN_A(ch
) || IEEE80211_IS_CHAN_T(ch
)) {
1862 wl_ofdm_t
*ofdm
= (wl_ofdm_t
*)ow_phy
;
1863 ofdm
->wl_ofdm_subtype
= WL_OFDM
;
1864 ofdm
->wl_ofdm_frequency
= ch
->ich_freq
;
1865 ofdm
->wl_ofdm_ht_enabled
= WIFI_HT_MODE(in
);
1867 switch (ic
->ic_phytype
) {
1868 case IEEE80211_T_FH
: {
1869 wl_fhss_t
*fhss
= (wl_fhss_t
*)ow_phy
;
1870 fhss
->wl_fhss_subtype
= WL_FHSS
;
1871 fhss
->wl_fhss_channel
=
1872 ieee80211_chan2ieee(ic
, ch
);
1875 case IEEE80211_T_DS
: {
1876 wl_dsss_t
*dsss
= (wl_dsss_t
*)ow_phy
;
1877 dsss
->wl_dsss_subtype
= WL_DSSS
;
1878 dsss
->wl_dsss_channel
=
1879 ieee80211_chan2ieee(ic
, ch
);
1882 case IEEE80211_T_OFDM
: {
1883 wl_erp_t
*erp
= (wl_erp_t
*)ow_phy
;
1884 erp
->wl_erp_subtype
= WL_ERP
;
1885 erp
->wl_erp_channel
=
1886 ieee80211_chan2ieee(ic
, ch
);
1887 erp
->wl_erp_ht_enabled
= WIFI_HT_MODE(in
);
1891 ieee80211_err("wl_get_phy: "
1892 "unknown phy type, %x\n", ic
->ic_phytype
);
1902 * MAC_PROP_WL_CAPABILITY
1905 wl_get_capability(struct ieee80211com
*ic
, void *wldp_buf
)
1907 wl_capability_t ow_caps
;
1909 ow_caps
.caps
= ic
->ic_caps
;
1910 bcopy(&ow_caps
, wldp_buf
, sizeof (wl_capability_t
));
1918 wl_set_wpa(struct ieee80211com
*ic
, const void *wldp_buf
)
1921 wl_wpa_t
*wpa
= (wl_wpa_t
*)wldp_buf
;
1923 ieee80211_dbg(IEEE80211_MSG_BRUSSELS
, "wl_set_wpa: "
1924 "set wpa=%u\n", wpa
->wpa_flag
);
1926 if (wpa
->wpa_flag
> 0) {
1927 /* enable wpa mode */
1928 ic
->ic_flags
|= IEEE80211_F_PRIVACY
;
1929 ic
->ic_flags
|= IEEE80211_F_WPA
;
1931 ic
->ic_flags
&= ~IEEE80211_F_PRIVACY
;
1932 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
1939 wl_get_wpa(struct ieee80211com
*ic
, void *wldp_buf
)
1943 wpa
= (wl_wpa_t
*)wldp_buf
;
1944 wpa
->wpa_flag
= ((ic
->ic_flags
& IEEE80211_F_WPA
) ? 1 : 0);
1946 ieee80211_dbg(IEEE80211_MSG_BRUSSELS
, "wl_get_wpa: "
1947 "get wpa=%u\n", wpa
->wpa_flag
);
1952 * MAC_PROP_WL_SCANRESULTS
1956 wl_get_scanresults(struct ieee80211com
*ic
, void *wldp_buf
)
1959 ieee80211_node_t
*in
;
1960 ieee80211_node_table_t
*nt
;
1964 sr
= (wl_wpa_ess_t
*)wldp_buf
;
1968 ieee80211_dbg(IEEE80211_MSG_WPA
, "wl_get_scanrelults\n");
1971 IEEE80211_NODE_LOCK(nt
);
1972 in
= list_head(&nt
->nt_node
);
1974 while (in
!= NULL
) {
1975 /* filter out non-wpa APs */
1976 if (in
->in_wpa_ie
== NULL
) {
1977 in
= list_next(&nt
->nt_node
, in
);
1980 bcopy(in
->in_bssid
, sr
->ess
[ap_num
].bssid
,
1981 IEEE80211_ADDR_LEN
);
1982 sr
->ess
[ap_num
].ssid_len
= in
->in_esslen
;
1983 bcopy(in
->in_essid
, sr
->ess
[ap_num
].ssid
,
1985 sr
->ess
[ap_num
].freq
= in
->in_chan
->ich_freq
;
1987 len
= in
->in_wpa_ie
[1] + 2;
1988 bcopy(in
->in_wpa_ie
, sr
->ess
[ap_num
].wpa_ie
, len
);
1989 sr
->ess
[ap_num
].wpa_ie_len
= len
;
1992 in
= list_next(&nt
->nt_node
, in
);
1994 IEEE80211_NODE_UNLOCK(nt
);
2000 * MAC_PROP_WL_ESS_LIST
2003 wl_get_esslist(struct ieee80211com
*ic
, void *wldp_buf
)
2005 wl_ess_list_t
*ess_list
;
2007 ess_list
= (wl_ess_list_t
*)wldp_buf
;
2009 ess_list
->wl_ess_list_num
= 0;
2010 ieee80211_iterate_nodes(&ic
->ic_scan
, wifi_read_ap
, ess_list
);
2015 * MAC_PROP_WL_WEP_KEY
2018 wl_set_wepkey(struct ieee80211com
*ic
, const void *wldp_buf
)
2023 struct ieee80211_key
*key
;
2024 wl_wep_key_t
*wepkey
= (wl_wep_key_t
*)wldp_buf
;
2026 /* set all valid keys */
2027 for (i
= 0; i
< MAX_NWEPKEYS
; i
++) {
2028 if (wepkey
[i
].wl_wep_operation
!= WL_ADD
)
2030 klen
= wepkey
[i
].wl_wep_length
;
2031 if (klen
> IEEE80211_KEYBUF_SIZE
) {
2032 ieee80211_err("wl_set_wepkey: "
2033 "invalid wepkey length, %u\n", klen
);
2035 continue; /* continue to set other keys */
2041 * Set key contents. Only WEP is supported
2043 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_wepkey: "
2044 "set key %u, len=%u\n", i
, klen
);
2045 key
= &ic
->ic_nw_keys
[i
];
2046 if (ieee80211_crypto_newkey(ic
, IEEE80211_CIPHER_WEP
,
2047 IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
, key
) == 0) {
2048 ieee80211_err("wl_set_wepkey: "
2049 "abort, create key failed. id=%u\n", i
);
2055 key
->wk_keylen
= (uint8_t)klen
;
2056 key
->wk_flags
|= IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
;
2057 bzero(key
->wk_key
, IEEE80211_KEYBUF_SIZE
);
2058 bcopy(wepkey
[i
].wl_wep_key
, key
->wk_key
, klen
);
2059 if (ieee80211_crypto_setkey(ic
, key
, ic
->ic_macaddr
)
2061 ieee80211_err("wl_set_wepkey: "
2062 "set key failed len=%u\n", klen
);
2073 * MAC_PROP_WL_SETOPTIE
2076 wl_set_optie(struct ieee80211com
*ic
, const void *wldp_buf
)
2080 wl_wpa_ie_t
*ie_in
= (wl_wpa_ie_t
*)wldp_buf
;
2082 if (ic
->ic_opmode
!= IEEE80211_M_STA
) {
2083 ieee80211_err("wl_set_optie: opmode err\n");
2087 if (ie_in
->wpa_ie_len
> IEEE80211_MAX_OPT_IE
) {
2089 ieee80211_err("wl_set_optie: optie is too long\n");
2095 ie
= ieee80211_malloc(ie_in
->wpa_ie_len
);
2096 (void) memcpy(ie
, ie_in
->wpa_ie
, ie_in
->wpa_ie_len
);
2097 if (ic
->ic_opt_ie
!= NULL
) {
2098 ieee80211_dbg(IEEE80211_MSG_BRUSSELS
,
2099 "wl_set_optie:ic_opt_ie!=NULL\n");
2100 ieee80211_free(ic
->ic_opt_ie
);
2103 ic
->ic_opt_ie_len
= ie_in
->wpa_ie_len
;
2109 * MAC_PROP_WL_DELKEY
2112 wl_set_delkey(struct ieee80211com
*ic
, const void *wldp_buf
)
2116 wl_del_key_t
*dk
= (wl_del_key_t
*)wldp_buf
;
2118 ieee80211_dbg(IEEE80211_MSG_BRUSSELS
, "wl_set_delkey(): "
2119 "keyix=%d\n", dk
->idk_keyix
);
2121 kid
= dk
->idk_keyix
;
2123 if (kid
== IEEE80211_KEYIX_NONE
||
2124 kid
>= IEEE80211_WEP_NKID
) {
2125 ieee80211_err("wl_set_delkey: incorrect keyix\n");
2129 (void) ieee80211_crypto_delkey(ic
,
2130 &ic
->ic_nw_keys
[kid
]);
2131 ieee80211_mac_update(ic
);
2142 wl_set_mlme(struct ieee80211com
*ic
, const void *wldp_buf
)
2146 ieee80211_node_t
*in
;
2147 wl_mlme_t
*mlme
= (wl_mlme_t
*)wldp_buf
;
2149 ieee80211_dbg(IEEE80211_MSG_WPA
, "wl_set_mlme: "
2150 "op=%d\n", mlme
->im_op
);
2152 switch (mlme
->im_op
) {
2153 case IEEE80211_MLME_DISASSOC
:
2154 case IEEE80211_MLME_DEAUTH
:
2155 if (ic
->ic_opmode
== IEEE80211_M_STA
) {
2157 * Mask ic_flags of IEEE80211_F_WPA to disable
2158 * ieee80211_notify temporarily.
2160 flags
= ic
->ic_flags
;
2161 ic
->ic_flags
&= ~IEEE80211_F_WPA
;
2163 IEEE80211_UNLOCK(ic
);
2164 ieee80211_new_state(ic
, IEEE80211_S_INIT
,
2168 ic
->ic_flags
= flags
;
2171 case IEEE80211_MLME_ASSOC
:
2172 if (ic
->ic_opmode
!= IEEE80211_M_STA
) {
2173 ieee80211_err("wifi_cfg_setmlme: opmode err\n");
2177 if (ic
->ic_des_esslen
!= 0) {
2179 * Desired ssid specified; must match both bssid and
2180 * ssid to distinguish ap advertising multiple ssid's.
2182 in
= ieee80211_find_node_with_ssid(&ic
->ic_scan
,
2188 * Normal case; just match bssid.
2190 in
= ieee80211_find_node(&ic
->ic_scan
,
2194 ieee80211_err("wifi_cfg_setmlme: "
2195 "no matched node\n");
2199 IEEE80211_UNLOCK(ic
);
2200 ieee80211_sta_join(ic
, in
);
2212 * MAC_PROP_WL_WPA_KEY
2215 wl_set_wpakey(struct ieee80211com
*ic
, const void *wldp_buf
)
2219 struct ieee80211_node
*in
;
2220 struct ieee80211_key
*wk
;
2223 bcopy(wldp_buf
, &ik
, sizeof (wl_key_t
));
2225 ieee80211_dbg(IEEE80211_MSG_BRUSSELS
, "wl_set_wpakey: "
2226 "idx=%d\n", ik
.ik_keyix
);
2229 * cipher support is verified by ieee80211_crypt_newkey
2230 * this also checks ik.ik_keylen > sizeof(wk->wk_key)
2232 if (ik
.ik_keylen
> sizeof (ik
.ik_keydata
)) {
2233 ieee80211_err("wl_set_wpakey: key is too long\n");
2238 if (kid
== IEEE80211_KEYIX_NONE
|| kid
>= IEEE80211_WEP_NKID
) {
2239 ieee80211_err("wl_set_wpakey: incorrect keyix\n");
2243 wk
= &ic
->ic_nw_keys
[kid
];
2245 * Globle slots start off w/o any assigned key index.
2246 * Force one here for consistency with WEPKEY.
2248 if (wk
->wk_keyix
== IEEE80211_KEYIX_NONE
)
2253 KEY_UPDATE_BEGIN(ic
);
2254 if (ieee80211_crypto_newkey(ic
, ik
.ik_type
,
2256 wk
->wk_keylen
= ik
.ik_keylen
;
2257 /* MIC presence is implied by cipher type */
2258 if (wk
->wk_keylen
> IEEE80211_KEYBUF_SIZE
)
2259 wk
->wk_keylen
= IEEE80211_KEYBUF_SIZE
;
2260 wk
->wk_keyrsc
= ik
.ik_keyrsc
;
2262 wk
->wk_flags
|= ik
.ik_flags
&
2263 (IEEE80211_KEY_XMIT
| IEEE80211_KEY_RECV
);
2264 (void) memset(wk
->wk_key
, 0, sizeof (wk
->wk_key
));
2265 (void) memcpy(wk
->wk_key
, ik
.ik_keydata
,
2267 if (!ieee80211_crypto_setkey(ic
, wk
,
2268 in
!= NULL
? in
->in_macaddr
: ik
.ik_macaddr
)) {
2270 } else if ((ik
.ik_flags
& IEEE80211_KEY_DEFAULT
)) {
2271 ic
->ic_def_txkey
= kid
;
2272 ieee80211_mac_update(ic
);
2283 * MAC_PROP_WL_SUP_RATE
2286 wl_get_suprates(struct ieee80211com
*ic
, void *wldp_buf
)
2291 wl_rates_t
*wl_rates
;
2292 const struct ieee80211_rateset
*srs
;
2294 wl_rates
= (wl_rates_t
*)wldp_buf
;
2296 wl_rates
->wl_rates_num
= 0;
2297 drates
= (uint8_t *)wl_rates
->wl_rates_rates
;
2298 for (i
= 0; i
< IEEE80211_MODE_MAX
; i
++) {
2299 srs
= &ic
->ic_sup_rates
[i
];
2300 if (srs
->ir_nrates
== 0)
2302 for (j
= 0; j
< srs
->ir_nrates
; j
++) {
2303 srates
= IEEE80211_RV(srs
->ir_rates
[j
]);
2304 /* sort & skip duplicated rates */
2305 for (k
= 0; k
< wl_rates
->wl_rates_num
; k
++) {
2306 if (srates
<= drates
[k
])
2309 if (srates
== drates
[k
])
2310 /* skip duplicated rates */
2313 for (l
= wl_rates
->wl_rates_num
; l
> k
; l
--)
2314 drates
[l
] = drates
[l
-1];
2316 wl_rates
->wl_rates_num
++;
2323 * MAC_PROP_WL_CREATE_IBSS
2326 wl_set_createibss(struct ieee80211com
*ic
, const void *wldp_buf
)
2328 wl_create_ibss_t
*iw_ibss
= (wl_create_ibss_t
*)wldp_buf
;
2331 ieee80211_dbg(IEEE80211_MSG_CONFIG
, "wl_set_ibss: "
2332 "set createibss=%u\n", *iw_ibss
);
2334 if ((ic
->ic_caps
& IEEE80211_C_IBSS
) == 0) {
2339 if ((ic
->ic_flags
& IEEE80211_F_IBSSON
) == 0) {
2340 ic
->ic_flags
|= IEEE80211_F_IBSSON
;
2341 ic
->ic_opmode
= IEEE80211_M_IBSS
;
2343 * Yech, slot time may change depending on the
2344 * operating mode so reset it to be sure
2345 * everything is setup appropriately.
2347 ieee80211_reset_erp(ic
);
2351 if (ic
->ic_flags
& IEEE80211_F_IBSSON
) {
2352 ic
->ic_flags
&= ~IEEE80211_F_IBSSON
;
2361 wl_get_createibss(struct ieee80211com
*ic
, void *wldp_buf
)
2363 wl_create_ibss_t
*ow_ibss
= (wl_create_ibss_t
*)wldp_buf
;
2365 *ow_ibss
= (ic
->ic_flags
& IEEE80211_F_IBSSON
)? 1 : 0;
2369 * Typically invoked by drivers in response to request for
2370 * information or to change settings from the userland.
2372 * Return value should be checked by WiFI drivers. Return 0
2373 * on success. Otherwise, return non-zero value to indicate
2374 * the error. Driver should operate as below when the return
2376 * ENETRESET Reset wireless network and re-start to join a
2377 * WLAN, ENETRESET is returned when a configuration
2378 * parameter has been changed.
2379 * When acknowledge a M_IOCTL message, this error
2384 ieee80211_setprop(void *ic_arg
, const char *pr_name
, mac_prop_id_t wldp_pr_num
,
2385 uint_t wldp_length
, const void *wldp_buf
)
2388 struct ieee80211com
*ic
= ic_arg
;
2393 switch (wldp_pr_num
) {
2395 case MAC_PROP_WL_ESSID
:
2396 err
= wl_set_essid(ic
, wldp_buf
);
2398 case MAC_PROP_WL_BSSID
:
2399 err
= wl_set_bssid(ic
, wldp_buf
);
2401 case MAC_PROP_WL_PHY_CONFIG
:
2402 err
= wl_set_phy(ic
, wldp_buf
);
2404 case MAC_PROP_WL_KEY_TAB
:
2405 err
= wl_set_wepkey(ic
, wldp_buf
);
2407 case MAC_PROP_WL_AUTH_MODE
:
2408 err
= wl_set_authmode(ic
, wldp_buf
);
2410 case MAC_PROP_WL_ENCRYPTION
:
2411 err
= wl_set_encrypt(ic
, wldp_buf
);
2413 case MAC_PROP_WL_BSSTYPE
:
2414 err
= wl_set_bsstype(ic
, wldp_buf
);
2416 case MAC_PROP_WL_DESIRED_RATES
:
2417 err
= wl_set_desrates(ic
, wldp_buf
);
2419 case MAC_PROP_WL_WPA
:
2420 err
= wl_set_wpa(ic
, wldp_buf
);
2422 case MAC_PROP_WL_KEY
:
2423 err
= wl_set_wpakey(ic
, wldp_buf
);
2425 case MAC_PROP_WL_DELKEY
:
2426 err
= wl_set_delkey(ic
, wldp_buf
);
2428 case MAC_PROP_WL_SETOPTIE
:
2429 err
= wl_set_optie(ic
, wldp_buf
);
2431 case MAC_PROP_WL_MLME
:
2432 err
= wl_set_mlme(ic
, wldp_buf
);
2434 case MAC_PROP_WL_CREATE_IBSS
:
2435 err
= wl_set_createibss(ic
, wldp_buf
);
2437 case MAC_PROP_WL_LINKSTATUS
:
2438 case MAC_PROP_WL_ESS_LIST
:
2439 case MAC_PROP_WL_SUPPORTED_RATES
:
2440 case MAC_PROP_WL_RSSI
:
2441 case MAC_PROP_WL_CAPABILITY
:
2442 case MAC_PROP_WL_SCANRESULTS
:
2443 ieee80211_err("ieee80211_setprop: opmode err\n");
2447 ieee80211_err("ieee80211_setprop: opmode not support\n");
2452 IEEE80211_UNLOCK(ic
);
2459 ieee80211_getprop(void *ic_arg
, const char *pr_name
, mac_prop_id_t wldp_pr_num
,
2460 uint_t wldp_length
, void *wldp_buf
)
2463 struct ieee80211com
*ic
= ic_arg
;
2468 switch (wldp_pr_num
) {
2470 case MAC_PROP_WL_ESSID
:
2471 wl_get_essid(ic
, wldp_buf
);
2473 case MAC_PROP_WL_BSSID
:
2474 wl_get_bssid(ic
, wldp_buf
);
2476 case MAC_PROP_WL_PHY_CONFIG
:
2477 err
= wl_get_phy(ic
, wldp_buf
);
2479 case MAC_PROP_WL_AUTH_MODE
:
2480 wl_get_authmode(ic
, wldp_buf
);
2482 case MAC_PROP_WL_ENCRYPTION
:
2483 wl_get_encrypt(ic
, wldp_buf
);
2485 case MAC_PROP_WL_BSSTYPE
:
2486 wl_get_bsstype(ic
, wldp_buf
);
2488 case MAC_PROP_WL_DESIRED_RATES
:
2489 wl_get_desrates(ic
, wldp_buf
);
2491 case MAC_PROP_WL_LINKSTATUS
:
2492 wl_get_linkstatus(ic
, wldp_buf
);
2494 case MAC_PROP_WL_ESS_LIST
:
2495 wl_get_esslist(ic
, wldp_buf
);
2497 case MAC_PROP_WL_SUPPORTED_RATES
:
2498 wl_get_suprates(ic
, wldp_buf
);
2500 case MAC_PROP_WL_RSSI
:
2501 wl_get_rssi(ic
, wldp_buf
);
2503 case MAC_PROP_WL_CAPABILITY
:
2504 wl_get_capability(ic
, wldp_buf
);
2506 case MAC_PROP_WL_WPA
:
2507 wl_get_wpa(ic
, wldp_buf
);
2509 case MAC_PROP_WL_SCANRESULTS
:
2510 wl_get_scanresults(ic
, wldp_buf
);
2512 case MAC_PROP_WL_CREATE_IBSS
:
2513 wl_get_createibss(ic
, wldp_buf
);
2515 case MAC_PROP_WL_KEY_TAB
:
2516 case MAC_PROP_WL_KEY
:
2517 case MAC_PROP_WL_DELKEY
:
2518 case MAC_PROP_WL_SETOPTIE
:
2519 case MAC_PROP_WL_MLME
:
2520 ieee80211_err("ieee80211_setprop: opmode err\n");
2524 ieee80211_err("ieee80211_setprop: opmode not support\n");
2529 IEEE80211_UNLOCK(ic
);
2534 void ieee80211_propinfo(void *ic_arg
, const char *pr_name
,
2535 mac_prop_id_t wldp_pr_num
, mac_prop_info_handle_t prh
)
2537 _NOTE(ARGUNUSED(pr_name
, ic_arg
));
2540 * By default permissions are read/write unless specified
2541 * otherwise by the driver.
2544 switch (wldp_pr_num
) {
2545 case MAC_PROP_WL_LINKSTATUS
:
2546 case MAC_PROP_WL_ESS_LIST
:
2547 case MAC_PROP_WL_SUPPORTED_RATES
:
2548 case MAC_PROP_WL_RSSI
:
2549 case MAC_PROP_WL_CAPABILITY
:
2550 case MAC_PROP_WL_SCANRESULTS
:
2551 case MAC_PROP_WL_CREATE_IBSS
:
2552 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);