4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
34 #include <libdevinfo.h>
36 #include <net/if_dl.h>
37 #include <net/if_types.h>
39 #include <libdllink.h>
41 #include <libdlwlan.h>
42 #include <libdladm_impl.h>
43 #include <libdlwlan_impl.h>
46 static dladm_status_t
wpa_instance_create(dladm_handle_t
, datalink_id_t
,
48 static dladm_status_t
wpa_instance_delete(dladm_handle_t
, datalink_id_t
);
50 static dladm_status_t
do_get_bsstype(dladm_handle_t
, datalink_id_t
, void *,
52 static dladm_status_t
do_get_essid(dladm_handle_t
, datalink_id_t
, void *,
54 static dladm_status_t
do_get_bssid(dladm_handle_t
, datalink_id_t
, void *,
56 static dladm_status_t
do_get_signal(dladm_handle_t
, datalink_id_t
, void *,
58 static dladm_status_t
do_get_encryption(dladm_handle_t
, datalink_id_t
, void *,
60 static dladm_status_t
do_get_authmode(dladm_handle_t
, datalink_id_t
, void *,
62 static dladm_status_t
do_get_linkstatus(dladm_handle_t
, datalink_id_t
, void *,
64 static dladm_status_t
do_get_esslist(dladm_handle_t
, datalink_id_t
, void *,
66 static dladm_status_t
do_get_rate(dladm_handle_t
, datalink_id_t
, void *, int);
67 static dladm_status_t
do_get_mode(dladm_handle_t
, datalink_id_t
, void *, int);
68 static dladm_status_t
do_get_capability(dladm_handle_t
, datalink_id_t
, void *,
70 static dladm_status_t
do_get_wpamode(dladm_handle_t
, datalink_id_t
, void *,
73 static dladm_status_t
do_set_bsstype(dladm_handle_t
, datalink_id_t
,
74 dladm_wlan_bsstype_t
*);
75 static dladm_status_t
do_set_authmode(dladm_handle_t
, datalink_id_t
,
77 static dladm_status_t
do_set_encryption(dladm_handle_t
, datalink_id_t
,
78 dladm_wlan_secmode_t
*);
79 static dladm_status_t
do_set_essid(dladm_handle_t
, datalink_id_t
,
80 dladm_wlan_essid_t
*);
81 static dladm_status_t
do_set_createibss(dladm_handle_t
, datalink_id_t
,
83 static dladm_status_t
do_set_key(dladm_handle_t
, datalink_id_t
,
84 dladm_wlan_key_t
*, uint_t
);
85 static dladm_status_t
do_set_channel(dladm_handle_t
, datalink_id_t
,
86 dladm_wlan_channel_t
*);
88 static dladm_status_t
do_scan(dladm_handle_t
, datalink_id_t
, void *, int);
89 static dladm_status_t
do_connect(dladm_handle_t
, datalink_id_t
, void *, int,
90 dladm_wlan_attr_t
*, boolean_t
, void *, uint_t
,
92 static dladm_status_t
do_disconnect(dladm_handle_t
, datalink_id_t
, void *,
94 static boolean_t
find_val_by_name(const char *, val_desc_t
*,
96 static boolean_t
find_name_by_val(uint_t
, val_desc_t
*, uint_t
, char **);
97 static void generate_essid(dladm_wlan_essid_t
*);
99 static dladm_status_t
dladm_wlan_wlresult2status(wldp_t
*);
100 static dladm_status_t
dladm_wlan_validate(dladm_handle_t
, datalink_id_t
);
102 static val_desc_t linkstatus_vals
[] = {
103 { "disconnected", DLADM_WLAN_LINK_DISCONNECTED
},
104 { "connected", DLADM_WLAN_LINK_CONNECTED
}
107 static val_desc_t secmode_vals
[] = {
108 { "none", DLADM_WLAN_SECMODE_NONE
},
109 { "wep", DLADM_WLAN_SECMODE_WEP
},
110 { "wpa", DLADM_WLAN_SECMODE_WPA
}
113 static val_desc_t strength_vals
[] = {
114 { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK
},
115 { "weak", DLADM_WLAN_STRENGTH_WEAK
},
116 { "good", DLADM_WLAN_STRENGTH_GOOD
},
117 { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD
},
118 { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT
}
121 static val_desc_t mode_vals
[] = {
122 { "a", DLADM_WLAN_MODE_80211A
},
123 { "b", DLADM_WLAN_MODE_80211B
},
124 { "g", DLADM_WLAN_MODE_80211G
},
125 { "n", DLADM_WLAN_MODE_80211GN
},
126 { "n", DLADM_WLAN_MODE_80211AN
}
129 static val_desc_t auth_vals
[] = {
130 { "open", DLADM_WLAN_AUTH_OPEN
},
131 { "shared", DLADM_WLAN_AUTH_SHARED
}
134 static val_desc_t bsstype_vals
[] = {
135 { "bss", DLADM_WLAN_BSSTYPE_BSS
},
136 { "ibss", DLADM_WLAN_BSSTYPE_IBSS
},
137 { "any", DLADM_WLAN_BSSTYPE_ANY
}
140 #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
142 static dladm_status_t
143 dladm_wlan_wlresult2status(wldp_t
*gbuf
)
145 switch (gbuf
->wldp_result
) {
147 return (DLADM_STATUS_OK
);
149 case WL_NOTSUPPORTED
:
150 case WL_LACK_FEATURE
:
151 return (DLADM_STATUS_NOTSUP
);
154 return (DLADM_STATUS_PROPRDONLY
);
160 return (DLADM_STATUS_FAILED
);
163 static dladm_wlan_mode_t
164 do_convert_mode(wl_phy_conf_t
*phyp
)
166 wl_erp_t
*wlep
= &phyp
->wl_phy_erp_conf
;
167 wl_ofdm_t
*wlop
= &phyp
->wl_phy_ofdm_conf
;
169 switch (phyp
->wl_phy_fhss_conf
.wl_fhss_subtype
) {
171 return (wlep
->wl_erp_ht_enabled
?
172 DLADM_WLAN_MODE_80211GN
: DLADM_WLAN_MODE_80211G
);
174 return (wlop
->wl_ofdm_ht_enabled
?
175 DLADM_WLAN_MODE_80211AN
: DLADM_WLAN_MODE_80211A
);
178 return (DLADM_WLAN_MODE_80211B
);
183 return (DLADM_WLAN_MODE_NONE
);
187 i_dladm_wlan_convert_chan(wl_phy_conf_t
*phyp
, uint32_t *channelp
)
189 wl_fhss_t
*wlfp
= &phyp
->wl_phy_fhss_conf
;
190 wl_ofdm_t
*wlop
= &phyp
->wl_phy_ofdm_conf
;
192 switch (wlfp
->wl_fhss_subtype
) {
198 *channelp
= wlfp
->wl_fhss_channel
;
201 *channelp
= DLADM_WLAN_OFDM2CHAN(wlop
->wl_ofdm_frequency
);
209 #define IEEE80211_RATE 0x7f
211 fill_wlan_attr(wl_ess_conf_t
*wlp
, dladm_wlan_attr_t
*attrp
)
215 (void) memset(attrp
, 0, sizeof (*attrp
));
217 (void) snprintf(attrp
->wa_essid
.we_bytes
, DLADM_WLAN_MAX_ESSID_LEN
,
218 "%s", wlp
->wl_ess_conf_essid
.wl_essid_essid
);
219 attrp
->wa_valid
|= DLADM_WLAN_ATTR_ESSID
;
221 (void) memcpy(attrp
->wa_bssid
.wb_bytes
, wlp
->wl_ess_conf_bssid
,
222 DLADM_WLAN_BSSID_LEN
);
223 attrp
->wa_valid
|= DLADM_WLAN_ATTR_BSSID
;
225 attrp
->wa_secmode
= (wlp
->wl_ess_conf_wepenabled
==
226 WL_ENC_WEP
? DLADM_WLAN_SECMODE_WEP
: DLADM_WLAN_SECMODE_NONE
);
227 if (wlp
->wl_ess_conf_reserved
[0] > 0)
228 attrp
->wa_secmode
= DLADM_WLAN_SECMODE_WPA
;
229 attrp
->wa_valid
|= DLADM_WLAN_ATTR_SECMODE
;
231 attrp
->wa_bsstype
= (wlp
->wl_ess_conf_bsstype
== WL_BSS_BSS
?
232 DLADM_WLAN_BSSTYPE_BSS
: DLADM_WLAN_BSSTYPE_IBSS
);
233 attrp
->wa_valid
|= DLADM_WLAN_ATTR_BSSTYPE
;
235 attrp
->wa_auth
= (wlp
->wl_ess_conf_authmode
== 0 ?
236 DLADM_WLAN_AUTH_OPEN
: DLADM_WLAN_AUTH_SHARED
);
237 attrp
->wa_valid
|= DLADM_WLAN_ATTR_AUTH
;
239 attrp
->wa_strength
= DLADM_WLAN_SIGNAL2STRENGTH(wlp
->wl_ess_conf_sl
);
240 attrp
->wa_valid
|= DLADM_WLAN_ATTR_STRENGTH
;
242 attrp
->wa_mode
= do_convert_mode((wl_phy_conf_t
*)&wlp
->wl_phy_conf
);
243 attrp
->wa_valid
|= DLADM_WLAN_ATTR_MODE
;
245 for (i
= 0; i
< MAX_SCAN_SUPPORT_RATES
; i
++) {
246 wlp
->wl_supported_rates
[i
] &= IEEE80211_RATE
;
247 if (wlp
->wl_supported_rates
[i
] > attrp
->wa_speed
)
248 attrp
->wa_speed
= wlp
->wl_supported_rates
[i
];
250 if (attrp
->wa_speed
> 0)
251 attrp
->wa_valid
|= DLADM_WLAN_ATTR_SPEED
;
253 if (i_dladm_wlan_convert_chan((wl_phy_conf_t
*)&wlp
->wl_phy_conf
,
255 attrp
->wa_valid
|= DLADM_WLAN_ATTR_CHANNEL
;
259 dladm_wlan_scan(dladm_handle_t handle
, datalink_id_t linkid
, void *arg
,
260 boolean_t (*func
)(void *, dladm_wlan_attr_t
*))
265 wl_ess_list_t
*wls
= NULL
;
266 char buf
[WLDP_BUFSIZE
];
267 wl_linkstatus_t wl_status
;
268 dladm_wlan_attr_t wlattr
;
269 dladm_status_t status
;
271 if ((status
= dladm_wlan_validate(handle
, linkid
)) != DLADM_STATUS_OK
)
274 status
= do_get_linkstatus(handle
, linkid
, &wl_status
,
276 if (status
!= DLADM_STATUS_OK
)
279 if ((status
= do_scan(handle
, linkid
, buf
, sizeof (buf
))) !=
284 status
= DLADM_STATUS_OK
;
288 wls
= malloc(WLDP_BUFSIZE
);
290 status
= DLADM_STATUS_NOMEM
;
294 if ((status
= do_get_esslist(handle
, linkid
, wls
, WLDP_BUFSIZE
))
298 wlp
= wls
->wl_ess_list_ess
;
299 count
= wls
->wl_ess_list_num
;
301 for (i
= 0; i
< count
; i
++, wlp
++) {
302 fill_wlan_attr(wlp
, &wlattr
);
303 if (!func(arg
, &wlattr
))
307 if (wl_status
!= WL_CONNECTED
) {
308 status
= do_get_linkstatus(handle
, linkid
, &wl_status
,
309 sizeof (&wl_status
));
310 if (status
!= DLADM_STATUS_OK
)
312 if (wl_status
== WL_CONNECTED
)
313 (void) do_disconnect(handle
, linkid
, buf
, sizeof (buf
));
316 status
= DLADM_STATUS_OK
;
323 * Structures used in building the list of eligible WLANs to connect to.
324 * Specifically, `connect_state' has the WLAN attributes that must be matched
325 * (in `cs_attr') and a growing list of WLANs that matched those attributes
326 * chained through `cs_list'. Each element in the list is of type `attr_node'
327 * and has the matching WLAN's attributes and a pointer to the next element.
328 * For convenience, `cs_count' tracks the number of elements in the list.
330 typedef struct attr_node
{
331 dladm_wlan_attr_t an_attr
;
332 struct attr_node
*an_next
;
335 typedef struct connect_state
{
336 dladm_wlan_attr_t
*cs_attr
;
338 attr_node_t
*cs_list
;
342 * Compare two sets of WLAN attributes. For now, we only consider strength
343 * and speed (in that order), which matches the documented default policy for
344 * dladm_wlan_connect().
347 attr_compare(const void *p1
, const void *p2
)
349 dladm_wlan_attr_t
*attrp1
, *attrp2
;
351 attrp1
= (*(dladm_wlan_attr_t
**)p1
);
352 attrp2
= (*(dladm_wlan_attr_t
**)p2
);
354 if (attrp1
->wa_strength
< attrp2
->wa_strength
)
357 if (attrp1
->wa_strength
> attrp2
->wa_strength
)
360 return (attrp2
->wa_speed
- attrp1
->wa_speed
);
364 * Callback function used by dladm_wlan_connect() to filter out unwanted
365 * WLANs when scanning for available WLANs. Always returns B_TRUE to
369 connect_cb(void *arg
, dladm_wlan_attr_t
*attrp
)
372 dladm_wlan_attr_t
*fattrp
;
373 connect_state_t
*statep
= (connect_state_t
*)arg
;
375 fattrp
= statep
->cs_attr
;
379 if ((fattrp
->wa_valid
& attrp
->wa_valid
) != fattrp
->wa_valid
)
382 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_ESSID
) != 0 &&
383 strncmp(fattrp
->wa_essid
.we_bytes
, attrp
->wa_essid
.we_bytes
,
384 DLADM_WLAN_MAX_ESSID_LEN
) != 0)
387 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_SECMODE
) != 0 &&
388 fattrp
->wa_secmode
!= attrp
->wa_secmode
)
391 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_MODE
) != 0 &&
392 fattrp
->wa_mode
!= attrp
->wa_mode
)
395 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_STRENGTH
) != 0 &&
396 fattrp
->wa_strength
!= attrp
->wa_strength
)
399 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_SPEED
) != 0 &&
400 fattrp
->wa_speed
!= attrp
->wa_speed
)
403 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_AUTH
) != 0) {
404 attrp
->wa_auth
= fattrp
->wa_auth
;
405 attrp
->wa_valid
|= DLADM_WLAN_ATTR_AUTH
;
408 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_BSSTYPE
) != 0 &&
409 fattrp
->wa_bsstype
!= attrp
->wa_bsstype
)
412 if ((fattrp
->wa_valid
& DLADM_WLAN_ATTR_BSSID
) != 0 &&
413 memcmp(fattrp
->wa_bssid
.wb_bytes
, attrp
->wa_bssid
.wb_bytes
,
414 DLADM_WLAN_BSSID_LEN
) != 0)
417 nodep
= malloc(sizeof (attr_node_t
));
421 (void) memcpy(&nodep
->an_attr
, attrp
, sizeof (dladm_wlan_attr_t
));
422 nodep
->an_next
= statep
->cs_list
;
423 statep
->cs_list
= nodep
;
429 #define IEEE80211_C_WPA 0x01800000
431 static dladm_status_t
432 do_connect(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
, int bufsize
,
433 dladm_wlan_attr_t
*attrp
, boolean_t create_ibss
, void *keys
,
434 uint_t key_count
, int timeout
)
436 dladm_wlan_secmode_t secmode
;
437 dladm_wlan_auth_t authmode
;
438 dladm_wlan_bsstype_t bsstype
;
439 dladm_wlan_essid_t essid
;
440 boolean_t essid_valid
= B_FALSE
;
441 dladm_status_t status
;
442 dladm_wlan_channel_t channel
;
444 wl_capability_t
*caps
;
445 wl_linkstatus_t wl_status
;
447 if ((attrp
->wa_valid
& DLADM_WLAN_ATTR_CHANNEL
) != 0) {
448 channel
= attrp
->wa_channel
;
449 status
= do_set_channel(handle
, linkid
, &channel
);
450 if (status
!= DLADM_STATUS_OK
)
454 secmode
= ((attrp
->wa_valid
& DLADM_WLAN_ATTR_SECMODE
) != 0) ?
455 attrp
->wa_secmode
: DLADM_WLAN_SECMODE_NONE
;
457 if ((status
= do_set_encryption(handle
, linkid
, &secmode
)) !=
461 authmode
= ((attrp
->wa_valid
& DLADM_WLAN_ATTR_AUTH
) != 0) ?
462 attrp
->wa_auth
: DLADM_WLAN_AUTH_OPEN
;
464 if ((status
= do_set_authmode(handle
, linkid
, &authmode
)) !=
468 bsstype
= ((attrp
->wa_valid
& DLADM_WLAN_ATTR_BSSTYPE
) != 0) ?
469 attrp
->wa_bsstype
: DLADM_WLAN_BSSTYPE_BSS
;
471 if ((status
= do_set_bsstype(handle
, linkid
, &bsstype
)) !=
475 if (secmode
== DLADM_WLAN_SECMODE_WEP
) {
476 if (keys
== NULL
|| key_count
== 0 ||
477 key_count
> MAX_NWEPKEYS
) {
478 status
= DLADM_STATUS_BADARG
;
481 status
= do_set_key(handle
, linkid
, keys
, key_count
);
482 if (status
!= DLADM_STATUS_OK
)
484 } else if (secmode
== DLADM_WLAN_SECMODE_WPA
) {
485 if (keys
== NULL
|| key_count
== 0 ||
486 key_count
> MAX_NWEPKEYS
) {
487 status
= DLADM_STATUS_BADARG
;
490 status
= do_get_capability(handle
, linkid
, buf
, bufsize
);
491 if (status
!= DLADM_STATUS_OK
)
493 caps
= (wl_capability_t
*)buf
;
494 if ((caps
->caps
& IEEE80211_C_WPA
) == 0)
495 return (DLADM_STATUS_NOTSUP
);
499 status
= do_set_channel(handle
, linkid
, &channel
);
500 if (status
!= DLADM_STATUS_OK
)
503 status
= do_set_createibss(handle
, linkid
, &create_ibss
);
504 if (status
!= DLADM_STATUS_OK
)
507 if ((attrp
->wa_valid
& DLADM_WLAN_ATTR_ESSID
) == 0) {
508 generate_essid(&essid
);
509 essid_valid
= B_TRUE
;
513 if ((attrp
->wa_valid
& DLADM_WLAN_ATTR_ESSID
) != 0) {
514 essid
= attrp
->wa_essid
;
515 essid_valid
= B_TRUE
;
519 status
= DLADM_STATUS_FAILED
;
523 if ((status
= do_set_essid(handle
, linkid
, &essid
)) != DLADM_STATUS_OK
)
527 * Because wpa daemon needs getting essid from driver,
528 * we need call do_set_essid() first, then call wpa_instance_create().
530 if (secmode
== DLADM_WLAN_SECMODE_WPA
&& keys
!= NULL
)
531 (void) wpa_instance_create(handle
, linkid
, keys
);
535 status
= do_get_linkstatus(handle
, linkid
, &wl_status
,
537 if (status
!= DLADM_STATUS_OK
)
540 if (wl_status
== WL_CONNECTED
)
543 (void) poll(NULL
, 0, DLADM_WLAN_CONNECT_POLLRATE
);
544 if ((timeout
>= 0) && (gethrtime() - start
) /
545 NANOSEC
>= timeout
) {
546 status
= DLADM_STATUS_TIMEDOUT
;
550 status
= DLADM_STATUS_OK
;
556 dladm_wlan_connect(dladm_handle_t handle
, datalink_id_t linkid
,
557 dladm_wlan_attr_t
*attrp
, int timeout
, void *keys
, uint_t key_count
,
561 char buf
[WLDP_BUFSIZE
];
562 connect_state_t state
= {NULL
, 0, NULL
};
563 attr_node_t
*nodep
= NULL
;
564 boolean_t create_ibss
, set_authmode
;
565 dladm_wlan_attr_t
**wl_list
= NULL
;
566 dladm_status_t status
;
567 wl_linkstatus_t wl_status
;
569 if ((status
= dladm_wlan_validate(handle
, linkid
)) != DLADM_STATUS_OK
)
572 if ((status
= do_get_linkstatus(handle
, linkid
, &wl_status
,
573 sizeof (wl_status
))) != DLADM_STATUS_OK
)
576 if (wl_status
== WL_CONNECTED
) {
577 status
= DLADM_STATUS_ISCONN
;
581 set_authmode
= ((attrp
!= NULL
) &&
582 (attrp
->wa_valid
& DLADM_WLAN_ATTR_MODE
) != 0);
583 create_ibss
= ((flags
& DLADM_WLAN_CONNECT_CREATEIBSS
) != 0 &&
585 (attrp
->wa_valid
& DLADM_WLAN_ATTR_BSSTYPE
) != 0 &&
586 attrp
->wa_bsstype
== DLADM_WLAN_BSSTYPE_IBSS
);
588 if ((flags
& DLADM_WLAN_CONNECT_NOSCAN
) != 0 ||
589 (create_ibss
&& attrp
!= NULL
&&
590 (attrp
->wa_valid
& DLADM_WLAN_ATTR_ESSID
) == 0)) {
591 status
= do_connect(handle
, linkid
, buf
, sizeof (buf
), attrp
,
592 create_ibss
, keys
, key_count
, timeout
);
596 state
.cs_attr
= attrp
;
597 state
.cs_list
= NULL
;
600 status
= dladm_wlan_scan(handle
, linkid
, &state
, connect_cb
);
601 if (status
!= DLADM_STATUS_OK
)
604 if (state
.cs_count
== 0) {
606 status
= DLADM_STATUS_NOTFOUND
;
609 status
= do_connect(handle
, linkid
, buf
, sizeof (buf
),
610 attrp
, create_ibss
, keys
, key_count
, timeout
);
614 wl_list
= malloc(state
.cs_count
* sizeof (dladm_wlan_attr_t
*));
615 if (wl_list
== NULL
) {
616 status
= DLADM_STATUS_NOMEM
;
620 nodep
= state
.cs_list
;
621 for (i
= 0; i
< state
.cs_count
; i
++) {
622 wl_list
[i
] = &nodep
->an_attr
;
623 nodep
= nodep
->an_next
;
625 qsort(wl_list
, state
.cs_count
, sizeof (dladm_wlan_attr_t
*),
628 for (i
= 0; i
< state
.cs_count
; i
++) {
629 dladm_wlan_attr_t
*ap
= wl_list
[i
];
631 status
= do_connect(handle
, linkid
, buf
, sizeof (buf
),
632 ap
, create_ibss
, keys
, key_count
, timeout
);
633 if (status
== DLADM_STATUS_OK
)
637 ap
->wa_auth
= DLADM_WLAN_AUTH_SHARED
;
638 ap
->wa_valid
|= DLADM_WLAN_ATTR_AUTH
;
639 status
= do_connect(handle
, linkid
, buf
, sizeof (buf
),
640 ap
, create_ibss
, keys
, key_count
, timeout
);
641 if (status
== DLADM_STATUS_OK
)
646 if ((status
!= DLADM_STATUS_OK
) && (status
!= DLADM_STATUS_ISCONN
))
647 (void) do_disconnect(handle
, linkid
, buf
, sizeof (buf
));
649 while (state
.cs_list
!= NULL
) {
650 nodep
= state
.cs_list
;
651 state
.cs_list
= nodep
->an_next
;
659 dladm_wlan_disconnect(dladm_handle_t handle
, datalink_id_t linkid
)
661 char buf
[WLDP_BUFSIZE
];
662 dladm_status_t status
;
663 wl_linkstatus_t wl_status
;
665 if ((status
= dladm_wlan_validate(handle
, linkid
)) != DLADM_STATUS_OK
)
668 if ((status
= do_get_linkstatus(handle
, linkid
, &wl_status
,
669 sizeof (wl_status
))) != DLADM_STATUS_OK
)
672 if (wl_status
!= WL_CONNECTED
) {
673 status
= DLADM_STATUS_NOTCONN
;
677 if ((status
= do_disconnect(handle
, linkid
, buf
, sizeof (buf
)))
681 if ((status
= do_get_linkstatus(handle
, linkid
, &wl_status
,
682 sizeof (wl_status
))) != DLADM_STATUS_OK
)
685 if (wl_status
== WL_CONNECTED
) {
686 status
= DLADM_STATUS_FAILED
;
690 status
= DLADM_STATUS_OK
;
696 dladm_wlan_get_linkattr(dladm_handle_t handle
, datalink_id_t linkid
,
697 dladm_wlan_linkattr_t
*attrp
)
700 wl_bss_type_t bsstype
;
701 wl_authmode_t authmode
;
702 wl_encryption_t encryption
;
703 wl_rates_t
*ratesp
= NULL
;
704 dladm_wlan_attr_t
*wl_attrp
;
705 dladm_status_t status
;
706 char buf
[WLDP_BUFSIZE
];
708 wl_phy_conf_t wl_phy_conf
;
709 wl_linkstatus_t wl_status
;
712 return (DLADM_STATUS_BADARG
);
714 if ((status
= dladm_wlan_validate(handle
, linkid
)) != DLADM_STATUS_OK
)
717 (void) memset(attrp
, 0, sizeof (*attrp
));
718 wl_attrp
= &attrp
->la_wlan_attr
;
720 if ((status
= do_get_linkstatus(handle
, linkid
, &wl_status
,
721 sizeof (wl_status
))) != DLADM_STATUS_OK
)
724 attrp
->la_valid
|= DLADM_WLAN_LINKATTR_STATUS
;
725 if (wl_status
!= WL_CONNECTED
)
726 attrp
->la_status
= DLADM_WLAN_LINK_DISCONNECTED
;
728 attrp
->la_status
= DLADM_WLAN_LINK_CONNECTED
;
730 if ((status
= do_get_essid(handle
, linkid
, &wls
, sizeof (wls
)))
734 (void) strlcpy(wl_attrp
->wa_essid
.we_bytes
, wls
.wl_essid_essid
,
735 DLADM_WLAN_MAX_ESSID_LEN
);
737 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_ESSID
;
739 if ((status
= do_get_bssid(handle
, linkid
, buf
, sizeof (buf
)))
743 (void) memcpy(wl_attrp
->wa_bssid
.wb_bytes
, buf
, DLADM_WLAN_BSSID_LEN
);
745 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_BSSID
;
747 if (attrp
->la_status
== DLADM_WLAN_LINK_DISCONNECTED
) {
748 attrp
->la_valid
|= DLADM_WLAN_LINKATTR_WLAN
;
749 status
= DLADM_STATUS_OK
;
753 if ((status
= do_get_encryption(handle
, linkid
, &encryption
,
754 sizeof (encryption
))) != DLADM_STATUS_OK
)
757 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_SECMODE
;
759 switch (encryption
) {
760 case WL_NOENCRYPTION
:
761 wl_attrp
->wa_secmode
= DLADM_WLAN_SECMODE_NONE
;
764 wl_attrp
->wa_secmode
= DLADM_WLAN_SECMODE_WEP
;
767 wl_attrp
->wa_secmode
= DLADM_WLAN_SECMODE_WPA
;
770 wl_attrp
->wa_valid
&= ~DLADM_WLAN_ATTR_SECMODE
;
774 if ((status
= do_get_signal(handle
, linkid
, &signal
, sizeof (signal
)))
778 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_STRENGTH
;
779 wl_attrp
->wa_strength
= DLADM_WLAN_SIGNAL2STRENGTH(signal
);
781 ratesp
= malloc(WLDP_BUFSIZE
);
782 if (ratesp
== NULL
) {
783 status
= DLADM_STATUS_NOMEM
;
787 if ((status
= do_get_rate(handle
, linkid
, ratesp
, WLDP_BUFSIZE
))
791 if (ratesp
->wl_rates_num
> 0) {
794 for (i
= 0; i
< ratesp
->wl_rates_num
; i
++) {
795 if (ratesp
->wl_rates_rates
[i
] > r
)
796 r
= ratesp
->wl_rates_rates
[i
];
798 wl_attrp
->wa_speed
= r
;
799 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_SPEED
;
802 if ((status
= do_get_authmode(handle
, linkid
, &authmode
,
803 sizeof (authmode
))) != DLADM_STATUS_OK
)
806 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_AUTH
;
810 wl_attrp
->wa_auth
= DLADM_WLAN_AUTH_OPEN
;
813 wl_attrp
->wa_auth
= DLADM_WLAN_AUTH_SHARED
;
816 wl_attrp
->wa_valid
&= ~DLADM_WLAN_ATTR_AUTH
;
820 if ((status
= do_get_bsstype(handle
, linkid
, &bsstype
,
821 sizeof (bsstype
))) != DLADM_STATUS_OK
)
824 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_BSSTYPE
;
828 wl_attrp
->wa_bsstype
= DLADM_WLAN_BSSTYPE_BSS
;
831 wl_attrp
->wa_bsstype
= DLADM_WLAN_BSSTYPE_IBSS
;
834 wl_attrp
->wa_bsstype
= DLADM_WLAN_BSSTYPE_ANY
;
837 wl_attrp
->wa_valid
&= ~DLADM_WLAN_ATTR_BSSTYPE
;
841 if ((status
= do_get_mode(handle
, linkid
, &wl_phy_conf
,
842 sizeof (wl_phy_conf
))) != DLADM_STATUS_OK
)
845 wl_attrp
->wa_mode
= do_convert_mode(&wl_phy_conf
);
846 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_MODE
;
847 if (wl_attrp
->wa_mode
!= DLADM_WLAN_MODE_NONE
)
848 wl_attrp
->wa_valid
|= DLADM_WLAN_ATTR_MODE
;
850 attrp
->la_valid
|= DLADM_WLAN_LINKATTR_WLAN
;
851 status
= DLADM_STATUS_OK
;
859 * Check to see if the link is wireless.
861 static dladm_status_t
862 dladm_wlan_validate(dladm_handle_t handle
, datalink_id_t linkid
)
865 dladm_status_t status
;
867 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, NULL
, &media
,
869 if (status
== DLADM_STATUS_OK
) {
870 if (media
!= DL_WIFI
)
871 status
= DLADM_STATUS_LINKINVAL
;
877 find_val_by_name(const char *str
, val_desc_t
*vdp
, uint_t cnt
, uint_t
*valp
)
881 for (i
= 0; i
< cnt
; i
++) {
882 if (strcasecmp(str
, vdp
[i
].vd_name
) == 0) {
883 *valp
= vdp
[i
].vd_val
;
891 find_name_by_val(uint_t val
, val_desc_t
*vdp
, uint_t cnt
, char **strp
)
895 for (i
= 0; i
< cnt
; i
++) {
896 if (val
== vdp
[i
].vd_val
) {
897 *strp
= vdp
[i
].vd_name
;
905 dladm_wlan_essid2str(dladm_wlan_essid_t
*essid
, char *buf
)
907 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", essid
->we_bytes
);
912 dladm_wlan_bssid2str(dladm_wlan_bssid_t
*bssid
, char *buf
)
914 return (_link_ntoa(bssid
->wb_bytes
, buf
, DLADM_WLAN_BSSID_LEN
,
919 dladm_wlan_val2str(uint_t val
, val_desc_t
*vdp
, uint_t cnt
, char *buf
)
923 if (!find_name_by_val(val
, vdp
, cnt
, &s
))
926 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", s
);
931 dladm_wlan_secmode2str(dladm_wlan_secmode_t
*secmode
, char *buf
)
933 return (dladm_wlan_val2str((uint_t
)*secmode
, secmode_vals
,
934 VALCNT(secmode_vals
), buf
));
938 dladm_wlan_strength2str(dladm_wlan_strength_t
*strength
, char *buf
)
940 return (dladm_wlan_val2str((uint_t
)*strength
, strength_vals
,
941 VALCNT(strength_vals
), buf
));
945 dladm_wlan_mode2str(dladm_wlan_mode_t
*mode
, char *buf
)
947 return (dladm_wlan_val2str((uint_t
)*mode
, mode_vals
,
948 VALCNT(mode_vals
), buf
));
952 dladm_wlan_speed2str(dladm_wlan_speed_t
*speed
, char *buf
)
954 (void) snprintf(buf
, DLADM_STRSIZE
, "%.*f", *speed
% 2,
955 (float)(*speed
) / 2);
960 dladm_wlan_auth2str(dladm_wlan_auth_t
*auth
, char *buf
)
962 return (dladm_wlan_val2str((uint_t
)*auth
, auth_vals
,
963 VALCNT(auth_vals
), buf
));
967 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t
*bsstype
, char *buf
)
969 return (dladm_wlan_val2str((uint_t
)*bsstype
, bsstype_vals
,
970 VALCNT(bsstype_vals
), buf
));
974 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t
*linkstatus
, char *buf
)
976 return (dladm_wlan_val2str((uint_t
)*linkstatus
, linkstatus_vals
,
977 VALCNT(linkstatus_vals
), buf
));
981 dladm_wlan_str2essid(const char *str
, dladm_wlan_essid_t
*essid
)
983 if (str
[0] == '\0' || strlen(str
) > DLADM_WLAN_MAX_ESSID_LEN
- 1)
984 return (DLADM_STATUS_BADARG
);
986 (void) strlcpy(essid
->we_bytes
, str
, DLADM_WLAN_MAX_ESSID_LEN
);
987 return (DLADM_STATUS_OK
);
991 dladm_wlan_str2bssid(const char *str
, dladm_wlan_bssid_t
*bssid
)
996 buf
= _link_aton(str
, &len
);
998 return (DLADM_STATUS_BADARG
);
1000 if (len
!= DLADM_WLAN_BSSID_LEN
) {
1002 return (DLADM_STATUS_BADARG
);
1005 (void) memcpy(bssid
->wb_bytes
, buf
, len
);
1007 return (DLADM_STATUS_OK
);
1011 dladm_wlan_str2secmode(const char *str
, dladm_wlan_secmode_t
*secmode
)
1015 if (!find_val_by_name(str
, secmode_vals
, VALCNT(secmode_vals
), &val
))
1016 return (DLADM_STATUS_BADARG
);
1018 *secmode
= (dladm_wlan_secmode_t
)val
;
1019 return (DLADM_STATUS_OK
);
1023 dladm_wlan_str2strength(const char *str
, dladm_wlan_strength_t
*strength
)
1027 if (!find_val_by_name(str
, strength_vals
, VALCNT(strength_vals
), &val
))
1028 return (DLADM_STATUS_BADARG
);
1030 *strength
= (dladm_wlan_strength_t
)val
;
1031 return (DLADM_STATUS_OK
);
1035 dladm_wlan_str2mode(const char *str
, dladm_wlan_mode_t
*mode
)
1039 if (!find_val_by_name(str
, mode_vals
, VALCNT(mode_vals
), &val
))
1040 return (DLADM_STATUS_BADARG
);
1042 *mode
= (dladm_wlan_mode_t
)val
;
1043 return (DLADM_STATUS_OK
);
1047 dladm_wlan_str2speed(const char *str
, dladm_wlan_speed_t
*speed
)
1049 *speed
= (dladm_wlan_speed_t
)(atof(str
) * 2);
1050 return (DLADM_STATUS_OK
);
1054 dladm_wlan_str2auth(const char *str
, dladm_wlan_auth_t
*auth
)
1058 if (!find_val_by_name(str
, auth_vals
, VALCNT(auth_vals
), &val
))
1059 return (DLADM_STATUS_BADARG
);
1061 *auth
= (dladm_wlan_auth_t
)val
;
1062 return (DLADM_STATUS_OK
);
1066 dladm_wlan_str2bsstype(const char *str
, dladm_wlan_bsstype_t
*bsstype
)
1070 if (!find_val_by_name(str
, bsstype_vals
, VALCNT(bsstype_vals
), &val
))
1071 return (DLADM_STATUS_BADARG
);
1073 *bsstype
= (dladm_wlan_bsstype_t
)val
;
1074 return (DLADM_STATUS_OK
);
1078 dladm_wlan_str2linkstatus(const char *str
, dladm_wlan_linkstatus_t
*linkstatus
)
1082 if (!find_val_by_name(str
, linkstatus_vals
,
1083 VALCNT(linkstatus_vals
), &val
)) {
1084 return (DLADM_STATUS_BADARG
);
1087 *linkstatus
= (dladm_wlan_linkstatus_t
)val
;
1088 return (DLADM_STATUS_OK
);
1092 i_dladm_wlan_legacy_ioctl(dladm_handle_t handle
, datalink_id_t linkid
,
1093 wldp_t
*gbuf
, uint_t id
, size_t len
, uint_t cmd
, size_t cmdlen
)
1095 char linkname
[MAXPATHLEN
];
1097 struct strioctl stri
;
1099 dladm_status_t status
;
1101 char link
[MAXLINKNAMELEN
];
1103 if ((status
= dladm_datalink_id2info(handle
, linkid
, &flags
, NULL
,
1104 &media
, link
, MAXLINKNAMELEN
)) != DLADM_STATUS_OK
) {
1108 if (media
!= DL_WIFI
)
1109 return (DLADM_STATUS_BADARG
);
1111 if (!(flags
& DLADM_OPT_ACTIVE
))
1112 return (DLADM_STATUS_TEMPONLY
);
1115 * dlpi_open() is not used here because libdlpi depends on libdladm,
1116 * and we do not want to introduce recursive dependencies.
1118 (void) snprintf(linkname
, MAXPATHLEN
, "/dev/net/%s", link
);
1119 if ((fd
= open(linkname
, O_RDWR
)) < 0)
1120 return (dladm_errno2status(errno
));
1122 gbuf
->wldp_type
= NET_802_11
;
1124 gbuf
->wldp_length
= len
;
1127 stri
.ic_dp
= (char *)gbuf
;
1129 stri
.ic_len
= cmdlen
;
1131 if ((rc
= ioctl(fd
, I_STR
, &stri
)) != 0) {
1134 * Non-negative return value indicates the specific
1135 * operation failed and the reason for the failure
1136 * was stored in gbuf->wldp_result.
1138 status
= dladm_wlan_wlresult2status(gbuf
);
1141 * Negative return value indicates the ioctl failed.
1143 status
= dladm_errno2status(errno
);
1150 static dladm_status_t
1151 do_cmd_ioctl(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1152 int buflen
, uint_t cmd
)
1155 dladm_status_t status
= DLADM_STATUS_OK
;
1157 if ((gbuf
= malloc(MAX_BUF_LEN
)) == NULL
)
1158 return (DLADM_STATUS_NOMEM
);
1160 (void) memset(gbuf
, 0, MAX_BUF_LEN
);
1161 status
= i_dladm_wlan_legacy_ioctl(handle
, linkid
, gbuf
, cmd
,
1162 WLDP_BUFSIZE
, WLAN_COMMAND
, sizeof (wldp_t
));
1163 (void) memcpy(buf
, gbuf
->wldp_buf
, buflen
);
1168 static dladm_status_t
1169 do_scan(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
, int buflen
)
1171 return (do_cmd_ioctl(handle
, linkid
, buf
, buflen
, WL_SCAN
));
1174 static dladm_status_t
1175 do_disconnect(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1178 if (do_get_wpamode(handle
, linkid
, buf
, buflen
) == 0 &&
1179 ((wl_wpa_t
*)(buf
))->wpa_flag
> 0)
1180 (void) wpa_instance_delete(handle
, linkid
);
1182 return (do_cmd_ioctl(handle
, linkid
, buf
, buflen
, WL_DISASSOCIATE
));
1185 static dladm_status_t
1186 do_get_esslist(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1189 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_ESS_LIST
,
1193 static dladm_status_t
1194 do_get_bssid(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
, int buflen
)
1196 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_BSSID
,
1200 static dladm_status_t
1201 do_get_essid(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
, int buflen
)
1203 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_ESSID
,
1207 static dladm_status_t
1208 do_get_bsstype(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1211 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_BSSTYPE
,
1215 static dladm_status_t
1216 do_get_linkstatus(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1219 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_LINKSTATUS
,
1223 static dladm_status_t
1224 do_get_rate(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
, int buflen
)
1226 return (i_dladm_wlan_param(handle
, linkid
, buf
,
1227 MAC_PROP_WL_DESIRED_RATES
, buflen
, B_FALSE
));
1230 static dladm_status_t
1231 do_get_authmode(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1234 return (i_dladm_wlan_param(handle
, linkid
, buf
,
1235 MAC_PROP_WL_AUTH_MODE
, buflen
, B_FALSE
));
1238 static dladm_status_t
1239 do_get_encryption(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1242 return (i_dladm_wlan_param(handle
, linkid
, buf
,
1243 MAC_PROP_WL_ENCRYPTION
, buflen
, B_FALSE
));
1246 static dladm_status_t
1247 do_get_signal(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1250 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_RSSI
,
1254 static dladm_status_t
1255 do_get_mode(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
, int buflen
)
1257 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_PHY_CONFIG
,
1261 static dladm_status_t
1262 do_set_bsstype(dladm_handle_t handle
, datalink_id_t linkid
,
1263 dladm_wlan_bsstype_t
*bsstype
)
1265 wl_bss_type_t ibsstype
;
1268 case DLADM_WLAN_BSSTYPE_BSS
:
1269 ibsstype
= WL_BSS_BSS
;
1271 case DLADM_WLAN_BSSTYPE_IBSS
:
1272 ibsstype
= WL_BSS_IBSS
;
1275 ibsstype
= WL_BSS_ANY
;
1278 return (i_dladm_wlan_param(handle
, linkid
, &ibsstype
,
1279 MAC_PROP_WL_BSSTYPE
, sizeof (ibsstype
), B_TRUE
));
1282 static dladm_status_t
1283 do_set_authmode(dladm_handle_t handle
, datalink_id_t linkid
,
1284 dladm_wlan_auth_t
*auth
)
1286 wl_authmode_t auth_mode
;
1289 case DLADM_WLAN_AUTH_OPEN
:
1290 auth_mode
= WL_OPENSYSTEM
;
1292 case DLADM_WLAN_AUTH_SHARED
:
1293 auth_mode
= WL_SHAREDKEY
;
1296 return (DLADM_STATUS_NOTSUP
);
1298 return (i_dladm_wlan_param(handle
, linkid
, &auth_mode
,
1299 MAC_PROP_WL_AUTH_MODE
, sizeof (auth_mode
), B_TRUE
));
1302 static dladm_status_t
1303 do_set_encryption(dladm_handle_t handle
, datalink_id_t linkid
,
1304 dladm_wlan_secmode_t
*secmode
)
1306 wl_encryption_t encryption
;
1309 case DLADM_WLAN_SECMODE_NONE
:
1310 encryption
= WL_NOENCRYPTION
;
1312 case DLADM_WLAN_SECMODE_WEP
:
1313 encryption
= WL_ENC_WEP
;
1315 case DLADM_WLAN_SECMODE_WPA
:
1318 return (DLADM_STATUS_NOTSUP
);
1320 return (i_dladm_wlan_param(handle
, linkid
, &encryption
,
1321 MAC_PROP_WL_ENCRYPTION
, sizeof (encryption
), B_TRUE
));
1324 static dladm_status_t
1325 do_set_key(dladm_handle_t handle
, datalink_id_t linkid
, dladm_wlan_key_t
*keys
,
1330 wl_wep_key_tab_t wepkey_tab
;
1331 dladm_wlan_key_t
*kp
;
1333 if (key_count
== 0 || key_count
> MAX_NWEPKEYS
|| keys
== NULL
)
1334 return (DLADM_STATUS_BADARG
);
1336 (void) memset(wepkey_tab
, 0, sizeof (wepkey_tab
));
1337 for (i
= 0; i
< MAX_NWEPKEYS
; i
++)
1338 wepkey_tab
[i
].wl_wep_operation
= WL_NUL
;
1340 for (i
= 0; i
< key_count
; i
++) {
1342 if (kp
->wk_idx
== 0 || kp
->wk_idx
> MAX_NWEPKEYS
)
1343 return (DLADM_STATUS_BADARG
);
1344 if (kp
->wk_len
!= DLADM_WLAN_WEPKEY64_LEN
&&
1345 kp
->wk_len
!= DLADM_WLAN_WEPKEY128_LEN
)
1346 return (DLADM_STATUS_BADARG
);
1348 wkp
= &wepkey_tab
[kp
->wk_idx
- 1];
1349 wkp
->wl_wep_operation
= WL_ADD
;
1350 wkp
->wl_wep_length
= kp
->wk_len
;
1351 (void) memcpy(wkp
->wl_wep_key
, kp
->wk_val
, kp
->wk_len
);
1354 return (i_dladm_wlan_param(handle
, linkid
, &wepkey_tab
,
1355 MAC_PROP_WL_KEY_TAB
, sizeof (wepkey_tab
), B_TRUE
));
1358 static dladm_status_t
1359 do_set_essid(dladm_handle_t handle
, datalink_id_t linkid
,
1360 dladm_wlan_essid_t
*essid
)
1364 (void) memset(&iessid
, 0, sizeof (essid
));
1366 if (essid
!= NULL
&& essid
->we_bytes
[0] != '\0') {
1367 iessid
.wl_essid_length
= strlen(essid
->we_bytes
);
1368 (void) strlcpy(iessid
.wl_essid_essid
, essid
->we_bytes
,
1369 sizeof (iessid
.wl_essid_essid
));
1371 return (DLADM_STATUS_BADARG
);
1373 return (i_dladm_wlan_param(handle
, linkid
, &iessid
, MAC_PROP_WL_ESSID
,
1374 sizeof (iessid
), B_TRUE
));
1377 static dladm_status_t
1378 do_set_channel(dladm_handle_t handle
, datalink_id_t linkid
,
1379 dladm_wlan_channel_t
*channel
)
1381 wl_phy_conf_t phy_conf
;
1383 if (*channel
> MAX_CHANNEL_NUM
)
1384 return (DLADM_STATUS_BADVAL
);
1386 (void) memset(&phy_conf
, 0xff, sizeof (phy_conf
));
1387 phy_conf
.wl_phy_dsss_conf
.wl_dsss_channel
= *channel
;
1389 return (i_dladm_wlan_param(handle
, linkid
, &phy_conf
,
1390 MAC_PROP_WL_PHY_CONFIG
, sizeof (phy_conf
), B_TRUE
));
1393 static dladm_status_t
1394 do_set_createibss(dladm_handle_t handle
, datalink_id_t linkid
,
1395 boolean_t
*create_ibss
)
1397 wl_create_ibss_t cr
= (wl_create_ibss_t
)(*create_ibss
);
1399 return (i_dladm_wlan_param(handle
, linkid
, &cr
, MAC_PROP_WL_CREATE_IBSS
,
1400 sizeof (cr
), B_TRUE
));
1404 generate_essid(dladm_wlan_essid_t
*essid
)
1406 srandom(gethrtime());
1407 (void) snprintf(essid
->we_bytes
, DLADM_WLAN_MAX_ESSID_LEN
, "%d",
1411 static dladm_status_t
1412 do_get_capability(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1415 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_CAPABILITY
,
1419 static dladm_status_t
1420 do_get_wpamode(dladm_handle_t handle
, datalink_id_t linkid
, void *buf
,
1423 return (i_dladm_wlan_param(handle
, linkid
, buf
, MAC_PROP_WL_WPA
, buflen
,
1428 dladm_wlan_wpa_get_sr(dladm_handle_t handle
, datalink_id_t linkid
,
1429 dladm_wlan_ess_t
*sr
, uint_t escnt
, uint_t
*estot
)
1433 dladm_status_t status
;
1435 es
= malloc(WLDP_BUFSIZE
);
1437 return (DLADM_STATUS_NOMEM
);
1439 status
= i_dladm_wlan_param(handle
, linkid
, es
, MAC_PROP_WL_SCANRESULTS
,
1440 WLDP_BUFSIZE
, B_FALSE
);
1442 if (status
== DLADM_STATUS_OK
) {
1443 n
= (es
->count
> escnt
) ? escnt
: es
->count
;
1444 for (i
= 0; i
< n
; i
++) {
1445 (void) memcpy(sr
[i
].we_bssid
.wb_bytes
, es
->ess
[i
].bssid
,
1446 DLADM_WLAN_BSSID_LEN
);
1447 sr
[i
].we_ssid_len
= es
->ess
[i
].ssid_len
;
1448 (void) memcpy(sr
[i
].we_ssid
.we_bytes
, es
->ess
[i
].ssid
,
1449 es
->ess
[i
].ssid_len
);
1450 sr
[i
].we_wpa_ie_len
= es
->ess
[i
].wpa_ie_len
;
1451 (void) memcpy(sr
[i
].we_wpa_ie
, es
->ess
[i
].wpa_ie
,
1452 es
->ess
[i
].wpa_ie_len
);
1453 sr
[i
].we_freq
= es
->ess
[i
].freq
;
1463 dladm_wlan_wpa_set_ie(dladm_handle_t handle
, datalink_id_t linkid
,
1464 uint8_t *wpa_ie
, uint_t wpa_ie_len
)
1468 dladm_status_t status
;
1470 if (wpa_ie_len
> DLADM_WLAN_MAX_WPA_IE_LEN
)
1471 return (DLADM_STATUS_BADARG
);
1472 len
= sizeof (wl_wpa_ie_t
) + wpa_ie_len
;
1475 return (DLADM_STATUS_NOMEM
);
1477 (void) memset(ie
, 0, len
);
1478 ie
->wpa_ie_len
= wpa_ie_len
;
1479 (void) memcpy(ie
->wpa_ie
, wpa_ie
, wpa_ie_len
);
1481 status
= i_dladm_wlan_param(handle
, linkid
, ie
, MAC_PROP_WL_SETOPTIE
,
1489 dladm_wlan_wpa_set_wpa(dladm_handle_t handle
, datalink_id_t linkid
,
1494 wpa
.wpa_flag
= flag
;
1495 return (i_dladm_wlan_param(handle
, linkid
, &wpa
, MAC_PROP_WL_WPA
,
1496 sizeof (wpa
), B_TRUE
));
1500 dladm_wlan_wpa_del_key(dladm_handle_t handle
, datalink_id_t linkid
,
1501 uint_t key_idx
, const dladm_wlan_bssid_t
*addr
)
1505 wk
.idk_keyix
= key_idx
;
1507 (void) memcpy((char *)wk
.idk_macaddr
, addr
->wb_bytes
,
1508 DLADM_WLAN_BSSID_LEN
);
1510 return (i_dladm_wlan_param(handle
, linkid
, &wk
, MAC_PROP_WL_DELKEY
,
1511 sizeof (wk
), B_TRUE
));
1515 dladm_wlan_wpa_set_key(dladm_handle_t handle
, datalink_id_t linkid
,
1516 dladm_wlan_cipher_t cipher
, const dladm_wlan_bssid_t
*addr
,
1517 boolean_t set_tx
, uint64_t seq
, uint_t key_idx
, uint8_t *key
,
1522 (void) memset(&wk
, 0, sizeof (wl_key_t
));
1524 case DLADM_WLAN_CIPHER_WEP
:
1525 wk
.ik_type
= IEEE80211_CIPHER_WEP
;
1527 case DLADM_WLAN_CIPHER_TKIP
:
1528 wk
.ik_type
= IEEE80211_CIPHER_TKIP
;
1530 case DLADM_WLAN_CIPHER_AES_OCB
:
1531 wk
.ik_type
= IEEE80211_CIPHER_AES_OCB
;
1533 case DLADM_WLAN_CIPHER_AES_CCM
:
1534 wk
.ik_type
= IEEE80211_CIPHER_AES_CCM
;
1536 case DLADM_WLAN_CIPHER_CKIP
:
1537 wk
.ik_type
= IEEE80211_CIPHER_CKIP
;
1539 case DLADM_WLAN_CIPHER_NONE
:
1540 wk
.ik_type
= IEEE80211_CIPHER_NONE
;
1543 return (DLADM_STATUS_BADARG
);
1545 wk
.ik_flags
= IEEE80211_KEY_RECV
;
1547 wk
.ik_flags
|= IEEE80211_KEY_XMIT
| IEEE80211_KEY_DEFAULT
;
1548 (void) memcpy(wk
.ik_macaddr
, addr
->wb_bytes
,
1549 DLADM_WLAN_BSSID_LEN
);
1551 (void) memset(wk
.ik_macaddr
, 0, DLADM_WLAN_BSSID_LEN
);
1552 wk
.ik_keyix
= key_idx
;
1553 wk
.ik_keylen
= key_len
;
1554 (void) memcpy(&wk
.ik_keyrsc
, &seq
, 6); /* only use 48-bit of seq */
1555 (void) memcpy(wk
.ik_keydata
, key
, key_len
);
1557 return (i_dladm_wlan_param(handle
, linkid
, &wk
, MAC_PROP_WL_KEY
,
1558 sizeof (wk
), B_TRUE
));
1562 dladm_wlan_wpa_set_mlme(dladm_handle_t handle
, datalink_id_t linkid
,
1563 dladm_wlan_mlme_op_t op
, dladm_wlan_reason_t reason
,
1564 dladm_wlan_bssid_t
*bssid
)
1568 (void) memset(&mlme
, 0, sizeof (wl_mlme_t
));
1570 case DLADM_WLAN_MLME_ASSOC
:
1571 mlme
.im_op
= IEEE80211_MLME_ASSOC
;
1573 case DLADM_WLAN_MLME_DISASSOC
:
1574 mlme
.im_op
= IEEE80211_MLME_DISASSOC
;
1577 return (DLADM_STATUS_BADARG
);
1579 mlme
.im_reason
= reason
;
1581 (void) memcpy(mlme
.im_macaddr
, bssid
->wb_bytes
,
1582 DLADM_WLAN_BSSID_LEN
);
1584 return (i_dladm_wlan_param(handle
, linkid
, &mlme
, MAC_PROP_WL_MLME
,
1585 sizeof (mlme
), B_TRUE
));
1589 * routines of create instance
1591 static scf_propertygroup_t
*
1592 add_property_group_to_instance(scf_handle_t
*handle
, scf_instance_t
*instance
,
1593 const char *pg_name
, const char *pg_type
)
1595 scf_propertygroup_t
*pg
;
1597 pg
= scf_pg_create(handle
);
1601 if (scf_instance_add_pg(instance
, pg_name
, pg_type
, 0, pg
) != 0) {
1609 static dladm_status_t
1610 add_new_property(scf_handle_t
*handle
, const char *prop_name
,
1611 scf_type_t type
, const char *val
, scf_transaction_t
*tx
)
1613 scf_value_t
*value
= NULL
;
1614 scf_transaction_entry_t
*entry
= NULL
;
1616 entry
= scf_entry_create(handle
);
1620 value
= scf_value_create(handle
);
1624 if (scf_transaction_property_new(tx
, entry
, prop_name
, type
) != 0)
1627 if (scf_value_set_from_string(value
, type
, val
) != 0)
1630 if (scf_entry_add_value(entry
, value
) != 0)
1633 return (DLADM_STATUS_OK
);
1637 scf_value_destroy(value
);
1639 scf_entry_destroy(entry
);
1641 return (DLADM_STATUS_FAILED
);
1644 static dladm_status_t
1645 add_pg_method(scf_handle_t
*handle
, scf_instance_t
*instance
,
1646 const char *pg_name
, const char *flags
)
1649 dladm_status_t status
= DLADM_STATUS_FAILED
;
1650 char *command
= NULL
;
1651 scf_transaction_t
*tran
= NULL
;
1652 scf_propertygroup_t
*pg
;
1654 pg
= add_property_group_to_instance(handle
, instance
,
1655 pg_name
, SCF_GROUP_METHOD
);
1659 tran
= scf_transaction_create(handle
);
1663 size
= strlen(SVC_METHOD
) + strlen(" ") + strlen(flags
) + 1;
1664 command
= malloc(size
);
1665 if (command
== NULL
) {
1666 status
= DLADM_STATUS_NOMEM
;
1669 (void) snprintf(command
, size
, "%s %s", SVC_METHOD
, flags
);
1672 if (scf_transaction_start(tran
, pg
) != 0)
1675 if (add_new_property(handle
, SCF_PROPERTY_EXEC
,
1676 SCF_TYPE_ASTRING
, command
, tran
) != DLADM_STATUS_OK
) {
1680 rv
= scf_transaction_commit(tran
);
1683 status
= DLADM_STATUS_OK
;
1686 scf_transaction_destroy_children(tran
);
1687 if (scf_pg_update(pg
) == -1) {
1699 scf_transaction_destroy_children(tran
);
1700 scf_transaction_destroy(tran
);
1711 static dladm_status_t
1712 do_create_instance(scf_handle_t
*handle
, scf_service_t
*svc
,
1713 const char *instance_name
, const char *command
)
1715 dladm_status_t status
= DLADM_STATUS_FAILED
;
1717 ssize_t max_fmri_len
;
1718 scf_instance_t
*instance
;
1720 instance
= scf_instance_create(handle
);
1721 if (instance
== NULL
)
1724 if (scf_service_add_instance(svc
, instance_name
, instance
) != 0) {
1725 if (scf_error() == SCF_ERROR_EXISTS
)
1726 /* Let the caller deal with the duplicate instance */
1727 status
= DLADM_STATUS_EXIST
;
1731 if (add_pg_method(handle
, instance
, "start",
1732 command
) != DLADM_STATUS_OK
) {
1736 /* enabling the instance */
1737 max_fmri_len
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
);
1738 if ((buf
= malloc(max_fmri_len
+ 1)) == NULL
)
1741 if (scf_instance_to_fmri(instance
, buf
, max_fmri_len
+ 1) > 0) {
1742 if ((smf_disable_instance(buf
, 0) != 0) ||
1743 (smf_enable_instance(buf
, SMF_TEMPORARY
) != 0)) {
1746 status
= DLADM_STATUS_OK
;
1750 if (instance
!= NULL
)
1751 scf_instance_destroy(instance
);
1755 static dladm_status_t
1756 create_instance(const char *instance_name
, const char *command
)
1758 dladm_status_t status
= DLADM_STATUS_FAILED
;
1759 scf_service_t
*svc
= NULL
;
1760 scf_handle_t
*handle
= NULL
;
1762 handle
= scf_handle_create(SCF_VERSION
);
1766 if (scf_handle_bind(handle
) == -1)
1769 if ((svc
= scf_service_create(handle
)) == NULL
)
1772 if (scf_handle_decode_fmri(handle
, SERVICE_NAME
, NULL
, svc
,
1773 NULL
, NULL
, NULL
, SCF_DECODE_FMRI_EXACT
) != 0)
1776 status
= do_create_instance(handle
, svc
, instance_name
, command
);
1780 scf_service_destroy(svc
);
1782 if (handle
!= NULL
) {
1783 (void) scf_handle_unbind(handle
);
1784 scf_handle_destroy(handle
);
1791 * routines of delete instance
1793 #define DEFAULT_TIMEOUT 60000000
1794 #define INIT_WAIT_USECS 50000
1797 wait_until_disabled(scf_handle_t
*handle
, char *fmri
)
1802 uint64_t *cp
= NULL
;
1803 scf_simple_prop_t
*sp
= NULL
;
1805 max
= DEFAULT_TIMEOUT
;
1807 if (((sp
= scf_simple_prop_get(handle
, fmri
, "stop",
1808 SCF_PROPERTY_TIMEOUT
)) != NULL
) &&
1809 ((cp
= scf_simple_prop_next_count(sp
)) != NULL
) && (*cp
!= 0))
1810 max
= (*cp
) * 1000000; /* convert to usecs */
1813 scf_simple_prop_free(sp
);
1815 for (usecs
= INIT_WAIT_USECS
; max
> 0; max
-= usecs
) {
1816 /* incremental wait */
1818 usecs
= (usecs
> max
) ? max
: usecs
;
1820 (void) usleep(usecs
);
1822 /* Check state after the wait */
1823 if ((state
= smf_get_state(fmri
)) != NULL
) {
1824 if (strcmp(state
, "disabled") == 0)
1830 static dladm_status_t
1831 delete_instance(const char *instance_name
)
1833 dladm_status_t status
= DLADM_STATUS_FAILED
;
1835 ssize_t max_fmri_len
;
1836 scf_scope_t
*scope
= NULL
;
1837 scf_service_t
*svc
= NULL
;
1838 scf_handle_t
*handle
= NULL
;
1839 scf_instance_t
*instance
;
1841 handle
= scf_handle_create(SCF_VERSION
);
1845 if (scf_handle_bind(handle
) == -1)
1848 if ((scope
= scf_scope_create(handle
)) == NULL
)
1851 if ((svc
= scf_service_create(handle
)) == NULL
)
1854 if (scf_handle_get_scope(handle
, SCF_SCOPE_LOCAL
, scope
) == -1)
1857 if (scf_scope_get_service(scope
, SERVICE_NAME
, svc
) < 0)
1860 instance
= scf_instance_create(handle
);
1861 if (instance
== NULL
)
1864 if (scf_service_get_instance(svc
, instance_name
, instance
) != 0) {
1865 scf_error_t scf_errnum
= scf_error();
1867 if (scf_errnum
== SCF_ERROR_NOT_FOUND
)
1868 status
= DLADM_STATUS_OK
;
1870 scf_instance_destroy(instance
);
1874 max_fmri_len
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
);
1875 if ((buf
= malloc(max_fmri_len
+ 1)) == NULL
) {
1876 scf_instance_destroy(instance
);
1880 if (scf_instance_to_fmri(instance
, buf
, max_fmri_len
+ 1) > 0) {
1883 state
= smf_get_state(buf
);
1884 if (state
&& (strcmp(state
, SCF_STATE_STRING_ONLINE
) == 0 ||
1885 strcmp(state
, SCF_STATE_STRING_DEGRADED
) == 0)) {
1886 if (smf_disable_instance(buf
, 0) == 0) {
1888 * Wait for some time till timeout to avoid
1889 * a race with scf_instance_delete() below.
1891 wait_until_disabled(handle
, buf
);
1896 if (scf_instance_delete(instance
) != 0) {
1897 scf_instance_destroy(instance
);
1901 scf_instance_destroy(instance
);
1903 status
= DLADM_STATUS_OK
;
1907 scf_service_destroy(svc
);
1910 scf_scope_destroy(scope
);
1912 if (handle
!= NULL
) {
1913 (void) scf_handle_unbind(handle
);
1914 scf_handle_destroy(handle
);
1920 static dladm_status_t
1921 wpa_instance_create(dladm_handle_t handle
, datalink_id_t linkid
, void *key
)
1923 dladm_status_t status
= DLADM_STATUS_FAILED
;
1924 char *command
= NULL
;
1925 char *wk_name
= ((dladm_wlan_key_t
*)key
)->wk_name
;
1927 char instance_name
[MAXLINKNAMELEN
];
1930 * Use the link name as the instance name of the network/wpad service.
1932 status
= dladm_datalink_id2info(handle
, linkid
, NULL
, NULL
, NULL
,
1933 instance_name
, sizeof (instance_name
));
1934 if (status
!= DLADM_STATUS_OK
)
1937 size
= strlen(instance_name
) + strlen(" -i -k ") + strlen(wk_name
) + 1;
1938 command
= malloc(size
);
1939 if (command
== NULL
) {
1940 status
= DLADM_STATUS_NOMEM
;
1943 (void) snprintf(command
, size
, "-i %s -k %s", instance_name
, wk_name
);
1945 status
= create_instance(instance_name
, command
);
1946 if (status
== DLADM_STATUS_EXIST
) {
1948 * Delete the existing instance and create a new instance
1949 * with the supplied arguments.
1951 if ((status
= delete_instance(instance_name
)) ==
1953 status
= create_instance(instance_name
, command
);
1963 static dladm_status_t
1964 wpa_instance_delete(dladm_handle_t handle
, datalink_id_t linkid
)
1966 char instance_name
[MAXLINKNAMELEN
];
1969 * Get the instance name of the network/wpad service (the same as
1972 if (dladm_datalink_id2info(handle
, linkid
, NULL
, NULL
, NULL
,
1973 instance_name
, sizeof (instance_name
)) != DLADM_STATUS_OK
)
1974 return (DLADM_STATUS_FAILED
);
1976 return (delete_instance(instance_name
));