1f595a68aSyz147064 /*
2f595a68aSyz147064 * CDDL HEADER START
3f595a68aSyz147064 *
4f595a68aSyz147064 * The contents of this file are subject to the terms of the
5f595a68aSyz147064 * Common Development and Distribution License (the "License").
6f595a68aSyz147064 * You may not use this file except in compliance with the License.
7f595a68aSyz147064 *
8f595a68aSyz147064 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9f595a68aSyz147064 * or http://www.opensolaris.org/os/licensing.
10f595a68aSyz147064 * See the License for the specific language governing permissions
11f595a68aSyz147064 * and limitations under the License.
12f595a68aSyz147064 *
13f595a68aSyz147064 * When distributing Covered Code, include this CDDL HEADER in each
14f595a68aSyz147064 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15f595a68aSyz147064 * If applicable, add the following below this CDDL HEADER, with the
16f595a68aSyz147064 * fields enclosed by brackets "[]" replaced with your own identifying
17f595a68aSyz147064 * information: Portions Copyright [yyyy] [name of copyright owner]
18f595a68aSyz147064 *
19f595a68aSyz147064 * CDDL HEADER END
20f595a68aSyz147064 */
21f595a68aSyz147064 /*
22*e2cf88acSQuaker Fang * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23f595a68aSyz147064 * Use is subject to license terms.
24f595a68aSyz147064 */
25f595a68aSyz147064
26f595a68aSyz147064 #include <libintl.h>
27f595a68aSyz147064 #include <stdio.h>
28f595a68aSyz147064 #include <stdlib.h>
29f595a68aSyz147064 #include <unistd.h>
30f595a68aSyz147064 #include <fcntl.h>
31d62bc4baSyz147064 #include <stddef.h>
32f595a68aSyz147064 #include <string.h>
33f595a68aSyz147064 #include <stropts.h>
34f595a68aSyz147064 #include <libdevinfo.h>
35f595a68aSyz147064 #include <net/if.h>
36f595a68aSyz147064 #include <net/if_dl.h>
37f595a68aSyz147064 #include <net/if_types.h>
38d62bc4baSyz147064 #include <libdlpi.h>
39d62bc4baSyz147064 #include <libdllink.h>
40a399b765Szf162725 #include <libscf.h>
41f595a68aSyz147064 #include <libdlwlan.h>
42d62bc4baSyz147064 #include <libdladm_impl.h>
43f595a68aSyz147064 #include <libdlwlan_impl.h>
44a399b765Szf162725 #include <net/wpa.h>
45f595a68aSyz147064
464ac67f02SAnurag S. Maskey static dladm_status_t wpa_instance_create(dladm_handle_t, datalink_id_t,
474ac67f02SAnurag S. Maskey void *);
484ac67f02SAnurag S. Maskey static dladm_status_t wpa_instance_delete(dladm_handle_t, datalink_id_t);
49f595a68aSyz147064
504ac67f02SAnurag S. Maskey static dladm_status_t do_get_bsstype(dladm_handle_t, datalink_id_t, void *,
514ac67f02SAnurag S. Maskey int);
524ac67f02SAnurag S. Maskey static dladm_status_t do_get_essid(dladm_handle_t, datalink_id_t, void *,
534ac67f02SAnurag S. Maskey int);
544ac67f02SAnurag S. Maskey static dladm_status_t do_get_bssid(dladm_handle_t, datalink_id_t, void *,
554ac67f02SAnurag S. Maskey int);
564ac67f02SAnurag S. Maskey static dladm_status_t do_get_signal(dladm_handle_t, datalink_id_t, void *,
574ac67f02SAnurag S. Maskey int);
584ac67f02SAnurag S. Maskey static dladm_status_t do_get_encryption(dladm_handle_t, datalink_id_t, void *,
594ac67f02SAnurag S. Maskey int);
604ac67f02SAnurag S. Maskey static dladm_status_t do_get_authmode(dladm_handle_t, datalink_id_t, void *,
614ac67f02SAnurag S. Maskey int);
624ac67f02SAnurag S. Maskey static dladm_status_t do_get_linkstatus(dladm_handle_t, datalink_id_t, void *,
634ac67f02SAnurag S. Maskey int);
644ac67f02SAnurag S. Maskey static dladm_status_t do_get_esslist(dladm_handle_t, datalink_id_t, void *,
654ac67f02SAnurag S. Maskey int);
664ac67f02SAnurag S. Maskey static dladm_status_t do_get_rate(dladm_handle_t, datalink_id_t, void *, int);
674ac67f02SAnurag S. Maskey static dladm_status_t do_get_mode(dladm_handle_t, datalink_id_t, void *, int);
684ac67f02SAnurag S. Maskey static dladm_status_t do_get_capability(dladm_handle_t, datalink_id_t, void *,
694ac67f02SAnurag S. Maskey int);
704ac67f02SAnurag S. Maskey static dladm_status_t do_get_wpamode(dladm_handle_t, datalink_id_t, void *,
714ac67f02SAnurag S. Maskey int);
72f595a68aSyz147064
734ac67f02SAnurag S. Maskey static dladm_status_t do_set_bsstype(dladm_handle_t, datalink_id_t,
744ac67f02SAnurag S. Maskey dladm_wlan_bsstype_t *);
754ac67f02SAnurag S. Maskey static dladm_status_t do_set_authmode(dladm_handle_t, datalink_id_t,
764ac67f02SAnurag S. Maskey dladm_wlan_auth_t *);
774ac67f02SAnurag S. Maskey static dladm_status_t do_set_encryption(dladm_handle_t, datalink_id_t,
78d62bc4baSyz147064 dladm_wlan_secmode_t *);
794ac67f02SAnurag S. Maskey static dladm_status_t do_set_essid(dladm_handle_t, datalink_id_t,
804ac67f02SAnurag S. Maskey dladm_wlan_essid_t *);
814ac67f02SAnurag S. Maskey static dladm_status_t do_set_createibss(dladm_handle_t, datalink_id_t,
824ac67f02SAnurag S. Maskey boolean_t *);
834ac67f02SAnurag S. Maskey static dladm_status_t do_set_key(dladm_handle_t, datalink_id_t,
844ac67f02SAnurag S. Maskey dladm_wlan_key_t *, uint_t);
854ac67f02SAnurag S. Maskey static dladm_status_t do_set_channel(dladm_handle_t, datalink_id_t,
864ac67f02SAnurag S. Maskey dladm_wlan_channel_t *);
87f595a68aSyz147064
884ac67f02SAnurag S. Maskey static dladm_status_t do_scan(dladm_handle_t, datalink_id_t, void *, int);
894ac67f02SAnurag S. Maskey static dladm_status_t do_connect(dladm_handle_t, datalink_id_t, void *, int,
90bcb5c89dSSowmini Varadhan dladm_wlan_attr_t *, boolean_t, void *, uint_t,
91bcb5c89dSSowmini Varadhan int);
924ac67f02SAnurag S. Maskey static dladm_status_t do_disconnect(dladm_handle_t, datalink_id_t, void *,
934ac67f02SAnurag S. Maskey int);
94d62bc4baSyz147064 static boolean_t find_val_by_name(const char *, val_desc_t *,
95d62bc4baSyz147064 uint_t, uint_t *);
96f595a68aSyz147064 static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **);
97f595a68aSyz147064 static void generate_essid(dladm_wlan_essid_t *);
98f595a68aSyz147064
99f595a68aSyz147064 static dladm_status_t dladm_wlan_wlresult2status(wldp_t *);
1004ac67f02SAnurag S. Maskey static dladm_status_t dladm_wlan_validate(dladm_handle_t, datalink_id_t);
101f595a68aSyz147064
102f595a68aSyz147064 static val_desc_t linkstatus_vals[] = {
103d62bc4baSyz147064 { "disconnected", DLADM_WLAN_LINK_DISCONNECTED },
104d62bc4baSyz147064 { "connected", DLADM_WLAN_LINK_CONNECTED }
105f595a68aSyz147064 };
106f595a68aSyz147064
107f595a68aSyz147064 static val_desc_t secmode_vals[] = {
108f595a68aSyz147064 { "none", DLADM_WLAN_SECMODE_NONE },
109a399b765Szf162725 { "wep", DLADM_WLAN_SECMODE_WEP },
110a399b765Szf162725 { "wpa", DLADM_WLAN_SECMODE_WPA }
111f595a68aSyz147064 };
112f595a68aSyz147064
113f595a68aSyz147064 static val_desc_t strength_vals[] = {
114f595a68aSyz147064 { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK },
115f595a68aSyz147064 { "weak", DLADM_WLAN_STRENGTH_WEAK },
116f595a68aSyz147064 { "good", DLADM_WLAN_STRENGTH_GOOD },
117f595a68aSyz147064 { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD },
118f595a68aSyz147064 { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT }
119f595a68aSyz147064 };
120f595a68aSyz147064
121f595a68aSyz147064 static val_desc_t mode_vals[] = {
122f595a68aSyz147064 { "a", DLADM_WLAN_MODE_80211A },
123f595a68aSyz147064 { "b", DLADM_WLAN_MODE_80211B },
124f595a68aSyz147064 { "g", DLADM_WLAN_MODE_80211G },
125*e2cf88acSQuaker Fang { "n", DLADM_WLAN_MODE_80211GN },
126*e2cf88acSQuaker Fang { "n", DLADM_WLAN_MODE_80211AN }
127f595a68aSyz147064 };
128f595a68aSyz147064
129f595a68aSyz147064 static val_desc_t auth_vals[] = {
130f595a68aSyz147064 { "open", DLADM_WLAN_AUTH_OPEN },
131f595a68aSyz147064 { "shared", DLADM_WLAN_AUTH_SHARED }
132f595a68aSyz147064 };
133f595a68aSyz147064
134f595a68aSyz147064 static val_desc_t bsstype_vals[] = {
135f595a68aSyz147064 { "bss", DLADM_WLAN_BSSTYPE_BSS },
136f595a68aSyz147064 { "ibss", DLADM_WLAN_BSSTYPE_IBSS },
137f595a68aSyz147064 { "any", DLADM_WLAN_BSSTYPE_ANY }
138f595a68aSyz147064 };
139f595a68aSyz147064
140bcb5c89dSSowmini Varadhan #define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET)
141f595a68aSyz147064
142f595a68aSyz147064 static dladm_status_t
dladm_wlan_wlresult2status(wldp_t * gbuf)143f595a68aSyz147064 dladm_wlan_wlresult2status(wldp_t *gbuf)
144f595a68aSyz147064 {
145f595a68aSyz147064 switch (gbuf->wldp_result) {
146f595a68aSyz147064 case WL_SUCCESS:
147f595a68aSyz147064 return (DLADM_STATUS_OK);
148f595a68aSyz147064
149f595a68aSyz147064 case WL_NOTSUPPORTED:
150f595a68aSyz147064 case WL_LACK_FEATURE:
151f595a68aSyz147064 return (DLADM_STATUS_NOTSUP);
152f595a68aSyz147064
153f595a68aSyz147064 case WL_READONLY:
154f595a68aSyz147064 return (DLADM_STATUS_PROPRDONLY);
155f595a68aSyz147064
156f595a68aSyz147064 default:
157f595a68aSyz147064 break;
158f595a68aSyz147064 }
159f595a68aSyz147064
160f595a68aSyz147064 return (DLADM_STATUS_FAILED);
161f595a68aSyz147064 }
162f595a68aSyz147064
163f595a68aSyz147064 static dladm_wlan_mode_t
do_convert_mode(wl_phy_conf_t * phyp)164f595a68aSyz147064 do_convert_mode(wl_phy_conf_t *phyp)
165f595a68aSyz147064 {
166*e2cf88acSQuaker Fang wl_erp_t *wlep = &phyp->wl_phy_erp_conf;
167*e2cf88acSQuaker Fang wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf;
168*e2cf88acSQuaker Fang
169f595a68aSyz147064 switch (phyp->wl_phy_fhss_conf.wl_fhss_subtype) {
170f595a68aSyz147064 case WL_ERP:
171*e2cf88acSQuaker Fang return (wlep->wl_erp_ht_enabled ?
172*e2cf88acSQuaker Fang DLADM_WLAN_MODE_80211GN : DLADM_WLAN_MODE_80211G);
173f595a68aSyz147064 case WL_OFDM:
174*e2cf88acSQuaker Fang return (wlop->wl_ofdm_ht_enabled ?
175*e2cf88acSQuaker Fang DLADM_WLAN_MODE_80211AN : DLADM_WLAN_MODE_80211A);
176f595a68aSyz147064 case WL_DSSS:
177f595a68aSyz147064 case WL_FHSS:
178f595a68aSyz147064 return (DLADM_WLAN_MODE_80211B);
179f595a68aSyz147064 default:
180f595a68aSyz147064 break;
181f595a68aSyz147064 }
182f595a68aSyz147064
183f595a68aSyz147064 return (DLADM_WLAN_MODE_NONE);
184f595a68aSyz147064 }
185f595a68aSyz147064
186d62bc4baSyz147064 boolean_t
i_dladm_wlan_convert_chan(wl_phy_conf_t * phyp,uint32_t * channelp)187d62bc4baSyz147064 i_dladm_wlan_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp)
188f595a68aSyz147064 {
189f595a68aSyz147064 wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf;
190f595a68aSyz147064 wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf;
191f595a68aSyz147064
192f595a68aSyz147064 switch (wlfp->wl_fhss_subtype) {
193f595a68aSyz147064 case WL_FHSS:
194f595a68aSyz147064 case WL_DSSS:
195f595a68aSyz147064 case WL_IRBASE:
196f595a68aSyz147064 case WL_HRDS:
197f595a68aSyz147064 case WL_ERP:
198f595a68aSyz147064 *channelp = wlfp->wl_fhss_channel;
199f595a68aSyz147064 break;
200f595a68aSyz147064 case WL_OFDM:
201f595a68aSyz147064 *channelp = DLADM_WLAN_OFDM2CHAN(wlop->wl_ofdm_frequency);
202f595a68aSyz147064 break;
203f595a68aSyz147064 default:
204f595a68aSyz147064 return (B_FALSE);
205f595a68aSyz147064 }
206f595a68aSyz147064 return (B_TRUE);
207f595a68aSyz147064 }
208f595a68aSyz147064
209f595a68aSyz147064 #define IEEE80211_RATE 0x7f
210f595a68aSyz147064 static void
fill_wlan_attr(wl_ess_conf_t * wlp,dladm_wlan_attr_t * attrp)211f595a68aSyz147064 fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp)
212f595a68aSyz147064 {
213f595a68aSyz147064 int i;
214f595a68aSyz147064
215f595a68aSyz147064 (void) memset(attrp, 0, sizeof (*attrp));
216f595a68aSyz147064
217f595a68aSyz147064 (void) snprintf(attrp->wa_essid.we_bytes, DLADM_WLAN_MAX_ESSID_LEN,
218f595a68aSyz147064 "%s", wlp->wl_ess_conf_essid.wl_essid_essid);
219f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID;
220f595a68aSyz147064
221f595a68aSyz147064 (void) memcpy(attrp->wa_bssid.wb_bytes, wlp->wl_ess_conf_bssid,
222f595a68aSyz147064 DLADM_WLAN_BSSID_LEN);
223f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID;
224f595a68aSyz147064
225f595a68aSyz147064 attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled ==
226f595a68aSyz147064 WL_ENC_WEP ? DLADM_WLAN_SECMODE_WEP : DLADM_WLAN_SECMODE_NONE);
227a399b765Szf162725 if (wlp->wl_ess_conf_reserved[0] > 0)
228a399b765Szf162725 attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA;
229f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE;
230f595a68aSyz147064
231f595a68aSyz147064 attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ?
232f595a68aSyz147064 DLADM_WLAN_BSSTYPE_BSS : DLADM_WLAN_BSSTYPE_IBSS);
233f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
234f595a68aSyz147064
235f595a68aSyz147064 attrp->wa_auth = (wlp->wl_ess_conf_authmode == 0 ?
236f595a68aSyz147064 DLADM_WLAN_AUTH_OPEN : DLADM_WLAN_AUTH_SHARED);
237f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH;
238f595a68aSyz147064
239f595a68aSyz147064 attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(wlp->wl_ess_conf_sl);
240f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH;
241f595a68aSyz147064
242f595a68aSyz147064 attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)&wlp->wl_phy_conf);
243f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_MODE;
244f595a68aSyz147064
245f595a68aSyz147064 for (i = 0; i < MAX_SCAN_SUPPORT_RATES; i++) {
246f595a68aSyz147064 wlp->wl_supported_rates[i] &= IEEE80211_RATE;
247f595a68aSyz147064 if (wlp->wl_supported_rates[i] > attrp->wa_speed)
248f595a68aSyz147064 attrp->wa_speed = wlp->wl_supported_rates[i];
249f595a68aSyz147064 }
250f595a68aSyz147064 if (attrp->wa_speed > 0)
251f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED;
252f595a68aSyz147064
253d62bc4baSyz147064 if (i_dladm_wlan_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf,
254f595a68aSyz147064 &attrp->wa_channel))
255f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_CHANNEL;
256f595a68aSyz147064 }
257f595a68aSyz147064
258f595a68aSyz147064 dladm_status_t
dladm_wlan_scan(dladm_handle_t handle,datalink_id_t linkid,void * arg,boolean_t (* func)(void *,dladm_wlan_attr_t *))2594ac67f02SAnurag S. Maskey dladm_wlan_scan(dladm_handle_t handle, datalink_id_t linkid, void *arg,
260f595a68aSyz147064 boolean_t (*func)(void *, dladm_wlan_attr_t *))
261f595a68aSyz147064 {
262d62bc4baSyz147064 int i;
263f595a68aSyz147064 uint32_t count;
264f595a68aSyz147064 wl_ess_conf_t *wlp;
265bcb5c89dSSowmini Varadhan wl_ess_list_t *wls = NULL;
266bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE];
267bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status;
268f595a68aSyz147064 dladm_wlan_attr_t wlattr;
269f595a68aSyz147064 dladm_status_t status;
270f595a68aSyz147064
2714ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK)
272d62bc4baSyz147064 goto done;
273f595a68aSyz147064
2744ac67f02SAnurag S. Maskey status = do_get_linkstatus(handle, linkid, &wl_status,
2754ac67f02SAnurag S. Maskey sizeof (wl_status));
276bcb5c89dSSowmini Varadhan if (status != DLADM_STATUS_OK)
277f595a68aSyz147064 goto done;
278f595a68aSyz147064
2794ac67f02SAnurag S. Maskey if ((status = do_scan(handle, linkid, buf, sizeof (buf))) !=
2804ac67f02SAnurag S. Maskey DLADM_STATUS_OK)
281f595a68aSyz147064 goto done;
282f595a68aSyz147064
283a399b765Szf162725 if (func == NULL) {
284a399b765Szf162725 status = DLADM_STATUS_OK;
285a399b765Szf162725 goto done;
286a399b765Szf162725 }
287a399b765Szf162725
288bcb5c89dSSowmini Varadhan wls = malloc(WLDP_BUFSIZE);
289bcb5c89dSSowmini Varadhan if (wls == NULL) {
290bcb5c89dSSowmini Varadhan status = DLADM_STATUS_NOMEM;
291bcb5c89dSSowmini Varadhan goto done;
292bcb5c89dSSowmini Varadhan }
293bcb5c89dSSowmini Varadhan
2944ac67f02SAnurag S. Maskey if ((status = do_get_esslist(handle, linkid, wls, WLDP_BUFSIZE))
295bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK)
296f595a68aSyz147064 goto done;
297f595a68aSyz147064
298bcb5c89dSSowmini Varadhan wlp = wls->wl_ess_list_ess;
299bcb5c89dSSowmini Varadhan count = wls->wl_ess_list_num;
300f595a68aSyz147064
301f595a68aSyz147064 for (i = 0; i < count; i++, wlp++) {
302f595a68aSyz147064 fill_wlan_attr(wlp, &wlattr);
303f595a68aSyz147064 if (!func(arg, &wlattr))
304f595a68aSyz147064 break;
305f595a68aSyz147064 }
306f595a68aSyz147064
307bcb5c89dSSowmini Varadhan if (wl_status != WL_CONNECTED) {
3084ac67f02SAnurag S. Maskey status = do_get_linkstatus(handle, linkid, &wl_status,
309bcb5c89dSSowmini Varadhan sizeof (&wl_status));
310d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
311f595a68aSyz147064 goto done;
312bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED)
3134ac67f02SAnurag S. Maskey (void) do_disconnect(handle, linkid, buf, sizeof (buf));
314f595a68aSyz147064 }
315f595a68aSyz147064
316f595a68aSyz147064 status = DLADM_STATUS_OK;
317f595a68aSyz147064 done:
318bcb5c89dSSowmini Varadhan free(wls);
319f595a68aSyz147064 return (status);
320f595a68aSyz147064 }
321f595a68aSyz147064
322f595a68aSyz147064 /*
323f595a68aSyz147064 * Structures used in building the list of eligible WLANs to connect to.
324f595a68aSyz147064 * Specifically, `connect_state' has the WLAN attributes that must be matched
325f595a68aSyz147064 * (in `cs_attr') and a growing list of WLANs that matched those attributes
326f595a68aSyz147064 * chained through `cs_list'. Each element in the list is of type `attr_node'
327f595a68aSyz147064 * and has the matching WLAN's attributes and a pointer to the next element.
328f595a68aSyz147064 * For convenience, `cs_count' tracks the number of elements in the list.
329f595a68aSyz147064 */
330f595a68aSyz147064 typedef struct attr_node {
331f595a68aSyz147064 dladm_wlan_attr_t an_attr;
332f595a68aSyz147064 struct attr_node *an_next;
333f595a68aSyz147064 } attr_node_t;
334f595a68aSyz147064
335f595a68aSyz147064 typedef struct connect_state {
336f595a68aSyz147064 dladm_wlan_attr_t *cs_attr;
337f595a68aSyz147064 uint_t cs_count;
338f595a68aSyz147064 attr_node_t *cs_list;
339f595a68aSyz147064 } connect_state_t;
340f595a68aSyz147064
341f595a68aSyz147064 /*
342f595a68aSyz147064 * Compare two sets of WLAN attributes. For now, we only consider strength
343f595a68aSyz147064 * and speed (in that order), which matches the documented default policy for
344f595a68aSyz147064 * dladm_wlan_connect().
345f595a68aSyz147064 */
346f595a68aSyz147064 static int
attr_compare(const void * p1,const void * p2)347f595a68aSyz147064 attr_compare(const void *p1, const void *p2)
348f595a68aSyz147064 {
349f595a68aSyz147064 dladm_wlan_attr_t *attrp1, *attrp2;
350f595a68aSyz147064
351f595a68aSyz147064 attrp1 = (*(dladm_wlan_attr_t **)p1);
352f595a68aSyz147064 attrp2 = (*(dladm_wlan_attr_t **)p2);
353f595a68aSyz147064
354f595a68aSyz147064 if (attrp1->wa_strength < attrp2->wa_strength)
355f595a68aSyz147064 return (1);
356f595a68aSyz147064
357f595a68aSyz147064 if (attrp1->wa_strength > attrp2->wa_strength)
358f595a68aSyz147064 return (-1);
359f595a68aSyz147064
360f595a68aSyz147064 return (attrp2->wa_speed - attrp1->wa_speed);
361f595a68aSyz147064 }
362f595a68aSyz147064
363f595a68aSyz147064 /*
364f595a68aSyz147064 * Callback function used by dladm_wlan_connect() to filter out unwanted
365f595a68aSyz147064 * WLANs when scanning for available WLANs. Always returns B_TRUE to
366f595a68aSyz147064 * continue the scan.
367f595a68aSyz147064 */
368f595a68aSyz147064 static boolean_t
connect_cb(void * arg,dladm_wlan_attr_t * attrp)369f595a68aSyz147064 connect_cb(void *arg, dladm_wlan_attr_t *attrp)
370f595a68aSyz147064 {
371f595a68aSyz147064 attr_node_t *nodep;
372f595a68aSyz147064 dladm_wlan_attr_t *fattrp;
373f595a68aSyz147064 connect_state_t *statep = (connect_state_t *)arg;
374f595a68aSyz147064
375f595a68aSyz147064 fattrp = statep->cs_attr;
376f595a68aSyz147064 if (fattrp == NULL)
377f595a68aSyz147064 goto append;
378f595a68aSyz147064
379f595a68aSyz147064 if ((fattrp->wa_valid & attrp->wa_valid) != fattrp->wa_valid)
380f595a68aSyz147064 return (B_TRUE);
381f595a68aSyz147064
382f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0 &&
383f595a68aSyz147064 strncmp(fattrp->wa_essid.we_bytes, attrp->wa_essid.we_bytes,
384f595a68aSyz147064 DLADM_WLAN_MAX_ESSID_LEN) != 0)
385f595a68aSyz147064 return (B_TRUE);
386f595a68aSyz147064
387f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0 &&
388f595a68aSyz147064 fattrp->wa_secmode != attrp->wa_secmode)
389f595a68aSyz147064 return (B_TRUE);
390f595a68aSyz147064
391f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0 &&
392f595a68aSyz147064 fattrp->wa_mode != attrp->wa_mode)
393f595a68aSyz147064 return (B_TRUE);
394f595a68aSyz147064
395f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_STRENGTH) != 0 &&
396f595a68aSyz147064 fattrp->wa_strength != attrp->wa_strength)
397f595a68aSyz147064 return (B_TRUE);
398f595a68aSyz147064
399f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_SPEED) != 0 &&
400f595a68aSyz147064 fattrp->wa_speed != attrp->wa_speed)
401f595a68aSyz147064 return (B_TRUE);
402f595a68aSyz147064
403f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) {
404f595a68aSyz147064 attrp->wa_auth = fattrp->wa_auth;
405f595a68aSyz147064 attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH;
406f595a68aSyz147064 }
407f595a68aSyz147064
408f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 &&
409f595a68aSyz147064 fattrp->wa_bsstype != attrp->wa_bsstype)
410f595a68aSyz147064 return (B_TRUE);
411f595a68aSyz147064
412f595a68aSyz147064 if ((fattrp->wa_valid & DLADM_WLAN_ATTR_BSSID) != 0 &&
413f595a68aSyz147064 memcmp(fattrp->wa_bssid.wb_bytes, attrp->wa_bssid.wb_bytes,
414f595a68aSyz147064 DLADM_WLAN_BSSID_LEN) != 0)
415f595a68aSyz147064 return (B_TRUE);
416f595a68aSyz147064 append:
417f595a68aSyz147064 nodep = malloc(sizeof (attr_node_t));
418f595a68aSyz147064 if (nodep == NULL)
419f595a68aSyz147064 return (B_TRUE);
420f595a68aSyz147064
421f595a68aSyz147064 (void) memcpy(&nodep->an_attr, attrp, sizeof (dladm_wlan_attr_t));
422f595a68aSyz147064 nodep->an_next = statep->cs_list;
423f595a68aSyz147064 statep->cs_list = nodep;
424f595a68aSyz147064 statep->cs_count++;
425f595a68aSyz147064
426f595a68aSyz147064 return (B_TRUE);
427f595a68aSyz147064 }
428f595a68aSyz147064
429a399b765Szf162725 #define IEEE80211_C_WPA 0x01800000
430a399b765Szf162725
431f595a68aSyz147064 static dladm_status_t
do_connect(dladm_handle_t handle,datalink_id_t linkid,void * buf,int bufsize,dladm_wlan_attr_t * attrp,boolean_t create_ibss,void * keys,uint_t key_count,int timeout)4324ac67f02SAnurag S. Maskey do_connect(dladm_handle_t handle, datalink_id_t linkid, void *buf, int bufsize,
433bcb5c89dSSowmini Varadhan dladm_wlan_attr_t *attrp, boolean_t create_ibss, void *keys,
434bcb5c89dSSowmini Varadhan uint_t key_count, int timeout)
435f595a68aSyz147064 {
436f595a68aSyz147064 dladm_wlan_secmode_t secmode;
437f595a68aSyz147064 dladm_wlan_auth_t authmode;
438f595a68aSyz147064 dladm_wlan_bsstype_t bsstype;
439f595a68aSyz147064 dladm_wlan_essid_t essid;
440f595a68aSyz147064 boolean_t essid_valid = B_FALSE;
441d62bc4baSyz147064 dladm_status_t status;
442f595a68aSyz147064 dladm_wlan_channel_t channel;
443f595a68aSyz147064 hrtime_t start;
444a399b765Szf162725 wl_capability_t *caps;
445bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status;
446f595a68aSyz147064
447f595a68aSyz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) {
448f595a68aSyz147064 channel = attrp->wa_channel;
4494ac67f02SAnurag S. Maskey status = do_set_channel(handle, linkid, &channel);
450d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
451f595a68aSyz147064 goto fail;
452f595a68aSyz147064 }
453f595a68aSyz147064
454f595a68aSyz147064 secmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) ?
455f595a68aSyz147064 attrp->wa_secmode : DLADM_WLAN_SECMODE_NONE;
456f595a68aSyz147064
4574ac67f02SAnurag S. Maskey if ((status = do_set_encryption(handle, linkid, &secmode)) !=
4584ac67f02SAnurag S. Maskey DLADM_STATUS_OK)
459f595a68aSyz147064 goto fail;
460f595a68aSyz147064
461f595a68aSyz147064 authmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) ?
462f595a68aSyz147064 attrp->wa_auth : DLADM_WLAN_AUTH_OPEN;
463f595a68aSyz147064
4644ac67f02SAnurag S. Maskey if ((status = do_set_authmode(handle, linkid, &authmode)) !=
4654ac67f02SAnurag S. Maskey DLADM_STATUS_OK)
466f595a68aSyz147064 goto fail;
467f595a68aSyz147064
468f595a68aSyz147064 bsstype = ((attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0) ?
469f595a68aSyz147064 attrp->wa_bsstype : DLADM_WLAN_BSSTYPE_BSS;
470f595a68aSyz147064
4714ac67f02SAnurag S. Maskey if ((status = do_set_bsstype(handle, linkid, &bsstype)) !=
4724ac67f02SAnurag S. Maskey DLADM_STATUS_OK)
473f595a68aSyz147064 goto fail;
474f595a68aSyz147064
475f595a68aSyz147064 if (secmode == DLADM_WLAN_SECMODE_WEP) {
476d62bc4baSyz147064 if (keys == NULL || key_count == 0 ||
477d62bc4baSyz147064 key_count > MAX_NWEPKEYS) {
478d62bc4baSyz147064 status = DLADM_STATUS_BADARG;
479d62bc4baSyz147064 goto fail;
480d62bc4baSyz147064 }
4814ac67f02SAnurag S. Maskey status = do_set_key(handle, linkid, keys, key_count);
482d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
483f595a68aSyz147064 goto fail;
484a399b765Szf162725 } else if (secmode == DLADM_WLAN_SECMODE_WPA) {
485d62bc4baSyz147064 if (keys == NULL || key_count == 0 ||
486d62bc4baSyz147064 key_count > MAX_NWEPKEYS) {
487d62bc4baSyz147064 status = DLADM_STATUS_BADARG;
488d62bc4baSyz147064 goto fail;
489d62bc4baSyz147064 }
4904ac67f02SAnurag S. Maskey status = do_get_capability(handle, linkid, buf, bufsize);
491d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
492a399b765Szf162725 goto fail;
493bcb5c89dSSowmini Varadhan caps = (wl_capability_t *)buf;
494a399b765Szf162725 if ((caps->caps & IEEE80211_C_WPA) == 0)
495a399b765Szf162725 return (DLADM_STATUS_NOTSUP);
496f595a68aSyz147064 }
497f595a68aSyz147064
498f595a68aSyz147064 if (create_ibss) {
4994ac67f02SAnurag S. Maskey status = do_set_channel(handle, linkid, &channel);
500d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
501f595a68aSyz147064 goto fail;
502f595a68aSyz147064
5034ac67f02SAnurag S. Maskey status = do_set_createibss(handle, linkid, &create_ibss);
504d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
505f595a68aSyz147064 goto fail;
506f595a68aSyz147064
507f595a68aSyz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0) {
508f595a68aSyz147064 generate_essid(&essid);
509f595a68aSyz147064 essid_valid = B_TRUE;
510f595a68aSyz147064 }
511f595a68aSyz147064 }
512f595a68aSyz147064
513f595a68aSyz147064 if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) != 0) {
514f595a68aSyz147064 essid = attrp->wa_essid;
515f595a68aSyz147064 essid_valid = B_TRUE;
516f595a68aSyz147064 }
517f595a68aSyz147064
518d62bc4baSyz147064 if (!essid_valid) {
519d62bc4baSyz147064 status = DLADM_STATUS_FAILED;
520d62bc4baSyz147064 goto fail;
521d62bc4baSyz147064 }
522d62bc4baSyz147064
5234ac67f02SAnurag S. Maskey if ((status = do_set_essid(handle, linkid, &essid)) != DLADM_STATUS_OK)
524f595a68aSyz147064 goto fail;
525f595a68aSyz147064
526a399b765Szf162725 /*
527a399b765Szf162725 * Because wpa daemon needs getting essid from driver,
528a399b765Szf162725 * we need call do_set_essid() first, then call wpa_instance_create().
529a399b765Szf162725 */
530a399b765Szf162725 if (secmode == DLADM_WLAN_SECMODE_WPA && keys != NULL)
5314ac67f02SAnurag S. Maskey (void) wpa_instance_create(handle, linkid, keys);
532a399b765Szf162725
533f595a68aSyz147064 start = gethrtime();
534f595a68aSyz147064 for (;;) {
5354ac67f02SAnurag S. Maskey status = do_get_linkstatus(handle, linkid, &wl_status,
536bcb5c89dSSowmini Varadhan sizeof (wl_status));
537d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
538f595a68aSyz147064 goto fail;
539f595a68aSyz147064
540bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED)
541f595a68aSyz147064 break;
542f595a68aSyz147064
543f595a68aSyz147064 (void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE);
544f595a68aSyz147064 if ((timeout >= 0) && (gethrtime() - start) /
545d62bc4baSyz147064 NANOSEC >= timeout) {
546d62bc4baSyz147064 status = DLADM_STATUS_TIMEDOUT;
547d62bc4baSyz147064 goto fail;
548f595a68aSyz147064 }
549d62bc4baSyz147064 }
550d62bc4baSyz147064 status = DLADM_STATUS_OK;
551f595a68aSyz147064 fail:
552d62bc4baSyz147064 return (status);
553f595a68aSyz147064 }
554f595a68aSyz147064
555f595a68aSyz147064 dladm_status_t
dladm_wlan_connect(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_attr_t * attrp,int timeout,void * keys,uint_t key_count,uint_t flags)5564ac67f02SAnurag S. Maskey dladm_wlan_connect(dladm_handle_t handle, datalink_id_t linkid,
5574ac67f02SAnurag S. Maskey dladm_wlan_attr_t *attrp, int timeout, void *keys, uint_t key_count,
5584ac67f02SAnurag S. Maskey uint_t flags)
559f595a68aSyz147064 {
560d62bc4baSyz147064 int i;
561bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE];
562f595a68aSyz147064 connect_state_t state = {0, NULL, NULL};
563f595a68aSyz147064 attr_node_t *nodep = NULL;
564f595a68aSyz147064 boolean_t create_ibss, set_authmode;
565f595a68aSyz147064 dladm_wlan_attr_t **wl_list = NULL;
566d62bc4baSyz147064 dladm_status_t status;
567bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status;
568f595a68aSyz147064
5694ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK)
570811fc8e1Syz147064 return (status);
571f595a68aSyz147064
5724ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status,
5734ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK)
574f595a68aSyz147064 goto done;
575f595a68aSyz147064
576bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED) {
577f595a68aSyz147064 status = DLADM_STATUS_ISCONN;
578f595a68aSyz147064 goto done;
579f595a68aSyz147064 }
580f595a68aSyz147064
581f595a68aSyz147064 set_authmode = ((attrp != NULL) &&
582f595a68aSyz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_MODE) != 0);
583f595a68aSyz147064 create_ibss = ((flags & DLADM_WLAN_CONNECT_CREATEIBSS) != 0 &&
584f595a68aSyz147064 attrp != NULL &&
585f595a68aSyz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0 &&
586f595a68aSyz147064 attrp->wa_bsstype == DLADM_WLAN_BSSTYPE_IBSS);
587f595a68aSyz147064
588f595a68aSyz147064 if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 ||
589f595a68aSyz147064 (create_ibss && attrp != NULL &&
590f595a68aSyz147064 (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) {
5914ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf), attrp,
592bcb5c89dSSowmini Varadhan create_ibss, keys, key_count, timeout);
593f595a68aSyz147064 goto done;
594f595a68aSyz147064 }
595f595a68aSyz147064
596f595a68aSyz147064 state.cs_attr = attrp;
597f595a68aSyz147064 state.cs_list = NULL;
598f595a68aSyz147064 state.cs_count = 0;
599f595a68aSyz147064
6004ac67f02SAnurag S. Maskey status = dladm_wlan_scan(handle, linkid, &state, connect_cb);
601f595a68aSyz147064 if (status != DLADM_STATUS_OK)
602f595a68aSyz147064 goto done;
603f595a68aSyz147064
604f595a68aSyz147064 if (state.cs_count == 0) {
605f595a68aSyz147064 if (!create_ibss) {
606f595a68aSyz147064 status = DLADM_STATUS_NOTFOUND;
607f595a68aSyz147064 goto done;
608f595a68aSyz147064 }
6094ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf),
610bcb5c89dSSowmini Varadhan attrp, create_ibss, keys, key_count, timeout);
611f595a68aSyz147064 goto done;
612f595a68aSyz147064 }
613f595a68aSyz147064
614f595a68aSyz147064 wl_list = malloc(state.cs_count * sizeof (dladm_wlan_attr_t *));
615f595a68aSyz147064 if (wl_list == NULL) {
616f595a68aSyz147064 status = DLADM_STATUS_NOMEM;
617f595a68aSyz147064 goto done;
618f595a68aSyz147064 }
619f595a68aSyz147064
620f595a68aSyz147064 nodep = state.cs_list;
621f595a68aSyz147064 for (i = 0; i < state.cs_count; i++) {
622f595a68aSyz147064 wl_list[i] = &nodep->an_attr;
623f595a68aSyz147064 nodep = nodep->an_next;
624f595a68aSyz147064 }
625f595a68aSyz147064 qsort(wl_list, state.cs_count, sizeof (dladm_wlan_attr_t *),
626f595a68aSyz147064 attr_compare);
627f595a68aSyz147064
628f595a68aSyz147064 for (i = 0; i < state.cs_count; i++) {
629f595a68aSyz147064 dladm_wlan_attr_t *ap = wl_list[i];
630f595a68aSyz147064
6314ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf),
632bcb5c89dSSowmini Varadhan ap, create_ibss, keys, key_count, timeout);
633f595a68aSyz147064 if (status == DLADM_STATUS_OK)
634f595a68aSyz147064 break;
635f595a68aSyz147064
636f595a68aSyz147064 if (!set_authmode) {
637f595a68aSyz147064 ap->wa_auth = DLADM_WLAN_AUTH_SHARED;
638f595a68aSyz147064 ap->wa_valid |= DLADM_WLAN_ATTR_AUTH;
6394ac67f02SAnurag S. Maskey status = do_connect(handle, linkid, buf, sizeof (buf),
640bcb5c89dSSowmini Varadhan ap, create_ibss, keys, key_count, timeout);
641f595a68aSyz147064 if (status == DLADM_STATUS_OK)
642f595a68aSyz147064 break;
643f595a68aSyz147064 }
644f595a68aSyz147064 }
645f595a68aSyz147064 done:
646f595a68aSyz147064 if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN))
6474ac67f02SAnurag S. Maskey (void) do_disconnect(handle, linkid, buf, sizeof (buf));
648f595a68aSyz147064
649f595a68aSyz147064 while (state.cs_list != NULL) {
650f595a68aSyz147064 nodep = state.cs_list;
651f595a68aSyz147064 state.cs_list = nodep->an_next;
652f595a68aSyz147064 free(nodep);
653f595a68aSyz147064 }
654f595a68aSyz147064 free(wl_list);
655f595a68aSyz147064 return (status);
656f595a68aSyz147064 }
657f595a68aSyz147064
658f595a68aSyz147064 dladm_status_t
dladm_wlan_disconnect(dladm_handle_t handle,datalink_id_t linkid)6594ac67f02SAnurag S. Maskey dladm_wlan_disconnect(dladm_handle_t handle, datalink_id_t linkid)
660f595a68aSyz147064 {
661bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE];
662f595a68aSyz147064 dladm_status_t status;
663bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status;
664f595a68aSyz147064
6654ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK)
666d62bc4baSyz147064 return (status);
667f595a68aSyz147064
6684ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status,
6694ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK)
670f595a68aSyz147064 goto done;
671f595a68aSyz147064
672bcb5c89dSSowmini Varadhan if (wl_status != WL_CONNECTED) {
673f595a68aSyz147064 status = DLADM_STATUS_NOTCONN;
674f595a68aSyz147064 goto done;
675f595a68aSyz147064 }
676f595a68aSyz147064
6774ac67f02SAnurag S. Maskey if ((status = do_disconnect(handle, linkid, buf, sizeof (buf)))
678bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK)
679f595a68aSyz147064 goto done;
680f595a68aSyz147064
6814ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status,
6824ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK)
683f595a68aSyz147064 goto done;
684f595a68aSyz147064
685bcb5c89dSSowmini Varadhan if (wl_status == WL_CONNECTED) {
686f595a68aSyz147064 status = DLADM_STATUS_FAILED;
687f595a68aSyz147064 goto done;
688f595a68aSyz147064 }
689f595a68aSyz147064
690f595a68aSyz147064 status = DLADM_STATUS_OK;
691f595a68aSyz147064 done:
692f595a68aSyz147064 return (status);
693f595a68aSyz147064 }
694f595a68aSyz147064
695f595a68aSyz147064 dladm_status_t
dladm_wlan_get_linkattr(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_linkattr_t * attrp)6964ac67f02SAnurag S. Maskey dladm_wlan_get_linkattr(dladm_handle_t handle, datalink_id_t linkid,
6974ac67f02SAnurag S. Maskey dladm_wlan_linkattr_t *attrp)
698f595a68aSyz147064 {
699f595a68aSyz147064 wl_rssi_t signal;
700f595a68aSyz147064 wl_bss_type_t bsstype;
701f595a68aSyz147064 wl_authmode_t authmode;
702f595a68aSyz147064 wl_encryption_t encryption;
703bcb5c89dSSowmini Varadhan wl_rates_t *ratesp = NULL;
704f595a68aSyz147064 dladm_wlan_attr_t *wl_attrp;
705d62bc4baSyz147064 dladm_status_t status;
706bcb5c89dSSowmini Varadhan char buf[WLDP_BUFSIZE];
707bcb5c89dSSowmini Varadhan wl_essid_t wls;
708bcb5c89dSSowmini Varadhan wl_phy_conf_t wl_phy_conf;
709bcb5c89dSSowmini Varadhan wl_linkstatus_t wl_status;
710f595a68aSyz147064
711f595a68aSyz147064 if (attrp == NULL)
712f595a68aSyz147064 return (DLADM_STATUS_BADARG);
713f595a68aSyz147064
7144ac67f02SAnurag S. Maskey if ((status = dladm_wlan_validate(handle, linkid)) != DLADM_STATUS_OK)
715d62bc4baSyz147064 goto done;
716f595a68aSyz147064
717f595a68aSyz147064 (void) memset(attrp, 0, sizeof (*attrp));
718f595a68aSyz147064 wl_attrp = &attrp->la_wlan_attr;
719f595a68aSyz147064
7204ac67f02SAnurag S. Maskey if ((status = do_get_linkstatus(handle, linkid, &wl_status,
7214ac67f02SAnurag S. Maskey sizeof (wl_status))) != DLADM_STATUS_OK)
722f595a68aSyz147064 goto done;
723f595a68aSyz147064
724f595a68aSyz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS;
725bcb5c89dSSowmini Varadhan if (wl_status != WL_CONNECTED)
726d62bc4baSyz147064 attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED;
727d62bc4baSyz147064 else
728d62bc4baSyz147064 attrp->la_status = DLADM_WLAN_LINK_CONNECTED;
729f595a68aSyz147064
7304ac67f02SAnurag S. Maskey if ((status = do_get_essid(handle, linkid, &wls, sizeof (wls)))
731bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK)
732f595a68aSyz147064 goto done;
733f595a68aSyz147064
734bcb5c89dSSowmini Varadhan (void) strlcpy(wl_attrp->wa_essid.we_bytes, wls.wl_essid_essid,
735f595a68aSyz147064 DLADM_WLAN_MAX_ESSID_LEN);
736f595a68aSyz147064
737f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID;
738f595a68aSyz147064
7394ac67f02SAnurag S. Maskey if ((status = do_get_bssid(handle, linkid, buf, sizeof (buf)))
740bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK)
741f595a68aSyz147064 goto done;
742f595a68aSyz147064
743bcb5c89dSSowmini Varadhan (void) memcpy(wl_attrp->wa_bssid.wb_bytes, buf, DLADM_WLAN_BSSID_LEN);
744f595a68aSyz147064
745f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID;
746f595a68aSyz147064
747d62bc4baSyz147064 if (attrp->la_status == DLADM_WLAN_LINK_DISCONNECTED) {
748a399b765Szf162725 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN;
749a399b765Szf162725 status = DLADM_STATUS_OK;
750a399b765Szf162725 goto done;
751a399b765Szf162725 }
752a399b765Szf162725
7534ac67f02SAnurag S. Maskey if ((status = do_get_encryption(handle, linkid, &encryption,
754bcb5c89dSSowmini Varadhan sizeof (encryption))) != DLADM_STATUS_OK)
755f595a68aSyz147064 goto done;
756f595a68aSyz147064
757f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE;
758f595a68aSyz147064
759f595a68aSyz147064 switch (encryption) {
760f595a68aSyz147064 case WL_NOENCRYPTION:
761f595a68aSyz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_NONE;
762f595a68aSyz147064 break;
763f595a68aSyz147064 case WL_ENC_WEP:
764f595a68aSyz147064 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP;
765f595a68aSyz147064 break;
766a399b765Szf162725 case WL_ENC_WPA:
767a399b765Szf162725 wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA;
768a399b765Szf162725 break;
769f595a68aSyz147064 default:
770f595a68aSyz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE;
771f595a68aSyz147064 break;
772f595a68aSyz147064 }
773f595a68aSyz147064
7744ac67f02SAnurag S. Maskey if ((status = do_get_signal(handle, linkid, &signal, sizeof (signal)))
775bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK)
776f595a68aSyz147064 goto done;
777f595a68aSyz147064
778f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH;
779f595a68aSyz147064 wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal);
780f595a68aSyz147064
781bcb5c89dSSowmini Varadhan ratesp = malloc(WLDP_BUFSIZE);
782bcb5c89dSSowmini Varadhan if (ratesp == NULL) {
783bcb5c89dSSowmini Varadhan status = DLADM_STATUS_NOMEM;
784bcb5c89dSSowmini Varadhan goto done;
785bcb5c89dSSowmini Varadhan }
786bcb5c89dSSowmini Varadhan
7874ac67f02SAnurag S. Maskey if ((status = do_get_rate(handle, linkid, ratesp, WLDP_BUFSIZE))
788bcb5c89dSSowmini Varadhan != DLADM_STATUS_OK)
789f595a68aSyz147064 goto done;
790f595a68aSyz147064
791f595a68aSyz147064 if (ratesp->wl_rates_num > 0) {
792f595a68aSyz147064 uint_t i, r = 0;
793f595a68aSyz147064
794f595a68aSyz147064 for (i = 0; i < ratesp->wl_rates_num; i++) {
795f595a68aSyz147064 if (ratesp->wl_rates_rates[i] > r)
796f595a68aSyz147064 r = ratesp->wl_rates_rates[i];
797f595a68aSyz147064 }
798f595a68aSyz147064 wl_attrp->wa_speed = r;
799f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED;
800f595a68aSyz147064 }
801f595a68aSyz147064
8024ac67f02SAnurag S. Maskey if ((status = do_get_authmode(handle, linkid, &authmode,
803bcb5c89dSSowmini Varadhan sizeof (authmode))) != DLADM_STATUS_OK)
804f595a68aSyz147064 goto done;
805f595a68aSyz147064
806f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH;
807f595a68aSyz147064
808f595a68aSyz147064 switch (authmode) {
809f595a68aSyz147064 case WL_OPENSYSTEM:
810f595a68aSyz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_OPEN;
811f595a68aSyz147064 break;
812f595a68aSyz147064 case WL_SHAREDKEY:
813f595a68aSyz147064 wl_attrp->wa_auth = DLADM_WLAN_AUTH_SHARED;
814f595a68aSyz147064 break;
815f595a68aSyz147064 default:
816f595a68aSyz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_AUTH;
817f595a68aSyz147064 break;
818f595a68aSyz147064 }
819f595a68aSyz147064
8204ac67f02SAnurag S. Maskey if ((status = do_get_bsstype(handle, linkid, &bsstype,
821bcb5c89dSSowmini Varadhan sizeof (bsstype))) != DLADM_STATUS_OK)
822f595a68aSyz147064 goto done;
823f595a68aSyz147064
824f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE;
825f595a68aSyz147064
826f595a68aSyz147064 switch (bsstype) {
827f595a68aSyz147064 case WL_BSS_BSS:
828f595a68aSyz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_BSS;
829f595a68aSyz147064 break;
830f595a68aSyz147064 case WL_BSS_IBSS:
831f595a68aSyz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_IBSS;
832f595a68aSyz147064 break;
833f595a68aSyz147064 case WL_BSS_ANY:
834f595a68aSyz147064 wl_attrp->wa_bsstype = DLADM_WLAN_BSSTYPE_ANY;
835f595a68aSyz147064 break;
836f595a68aSyz147064 default:
837f595a68aSyz147064 wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_BSSTYPE;
838f595a68aSyz147064 break;
839f595a68aSyz147064 }
840f595a68aSyz147064
8414ac67f02SAnurag S. Maskey if ((status = do_get_mode(handle, linkid, &wl_phy_conf,
842bcb5c89dSSowmini Varadhan sizeof (wl_phy_conf))) != DLADM_STATUS_OK)
843f595a68aSyz147064 goto done;
844f595a68aSyz147064
845bcb5c89dSSowmini Varadhan wl_attrp->wa_mode = do_convert_mode(&wl_phy_conf);
846f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE;
847f595a68aSyz147064 if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE)
848f595a68aSyz147064 wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE;
849f595a68aSyz147064
850f595a68aSyz147064 attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN;
851f595a68aSyz147064 status = DLADM_STATUS_OK;
852f595a68aSyz147064
853f595a68aSyz147064 done:
854bcb5c89dSSowmini Varadhan free(ratesp);
855f595a68aSyz147064 return (status);
856f595a68aSyz147064 }
857f595a68aSyz147064
858d62bc4baSyz147064 /*
859d62bc4baSyz147064 * Check to see if the link is wireless.
860d62bc4baSyz147064 */
861eae72b5bSSebastien Roy static dladm_status_t
dladm_wlan_validate(dladm_handle_t handle,datalink_id_t linkid)8624ac67f02SAnurag S. Maskey dladm_wlan_validate(dladm_handle_t handle, datalink_id_t linkid)
863eae72b5bSSebastien Roy {
864eae72b5bSSebastien Roy uint32_t media;
865eae72b5bSSebastien Roy dladm_status_t status;
866f595a68aSyz147064
8674ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, linkid, NULL, NULL, &media,
8684ac67f02SAnurag S. Maskey NULL, 0);
869eae72b5bSSebastien Roy if (status == DLADM_STATUS_OK) {
870eae72b5bSSebastien Roy if (media != DL_WIFI)
871eae72b5bSSebastien Roy status = DLADM_STATUS_LINKINVAL;
872eae72b5bSSebastien Roy }
873f595a68aSyz147064 return (status);
874f595a68aSyz147064 }
875f595a68aSyz147064
876f595a68aSyz147064 static boolean_t
find_val_by_name(const char * str,val_desc_t * vdp,uint_t cnt,uint_t * valp)877f595a68aSyz147064 find_val_by_name(const char *str, val_desc_t *vdp, uint_t cnt, uint_t *valp)
878f595a68aSyz147064 {
879f595a68aSyz147064 int i;
880f595a68aSyz147064
881f595a68aSyz147064 for (i = 0; i < cnt; i++) {
882f595a68aSyz147064 if (strcasecmp(str, vdp[i].vd_name) == 0) {
883f595a68aSyz147064 *valp = vdp[i].vd_val;
884f595a68aSyz147064 return (B_TRUE);
885f595a68aSyz147064 }
886f595a68aSyz147064 }
887f595a68aSyz147064 return (B_FALSE);
888f595a68aSyz147064 }
889f595a68aSyz147064
890f595a68aSyz147064 static boolean_t
find_name_by_val(uint_t val,val_desc_t * vdp,uint_t cnt,char ** strp)891f595a68aSyz147064 find_name_by_val(uint_t val, val_desc_t *vdp, uint_t cnt, char **strp)
892f595a68aSyz147064 {
893f595a68aSyz147064 int i;
894f595a68aSyz147064
895f595a68aSyz147064 for (i = 0; i < cnt; i++) {
896f595a68aSyz147064 if (val == vdp[i].vd_val) {
897f595a68aSyz147064 *strp = vdp[i].vd_name;
898f595a68aSyz147064 return (B_TRUE);
899f595a68aSyz147064 }
900f595a68aSyz147064 }
901f595a68aSyz147064 return (B_FALSE);
902f595a68aSyz147064 }
903f595a68aSyz147064
904f595a68aSyz147064 const char *
dladm_wlan_essid2str(dladm_wlan_essid_t * essid,char * buf)905f595a68aSyz147064 dladm_wlan_essid2str(dladm_wlan_essid_t *essid, char *buf)
906f595a68aSyz147064 {
907f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", essid->we_bytes);
908f595a68aSyz147064 return (buf);
909f595a68aSyz147064 }
910f595a68aSyz147064
911f595a68aSyz147064 const char *
dladm_wlan_bssid2str(dladm_wlan_bssid_t * bssid,char * buf)912f595a68aSyz147064 dladm_wlan_bssid2str(dladm_wlan_bssid_t *bssid, char *buf)
913f595a68aSyz147064 {
914f595a68aSyz147064 return (_link_ntoa(bssid->wb_bytes, buf, DLADM_WLAN_BSSID_LEN,
915f595a68aSyz147064 IFT_OTHER));
916f595a68aSyz147064 }
917f595a68aSyz147064
918f595a68aSyz147064 static const char *
dladm_wlan_val2str(uint_t val,val_desc_t * vdp,uint_t cnt,char * buf)919f595a68aSyz147064 dladm_wlan_val2str(uint_t val, val_desc_t *vdp, uint_t cnt, char *buf)
920f595a68aSyz147064 {
921f595a68aSyz147064 char *s;
922f595a68aSyz147064
923f595a68aSyz147064 if (!find_name_by_val(val, vdp, cnt, &s))
924f595a68aSyz147064 s = "";
925f595a68aSyz147064
926f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
927f595a68aSyz147064 return (buf);
928f595a68aSyz147064 }
929f595a68aSyz147064
930f595a68aSyz147064 const char *
dladm_wlan_secmode2str(dladm_wlan_secmode_t * secmode,char * buf)931f595a68aSyz147064 dladm_wlan_secmode2str(dladm_wlan_secmode_t *secmode, char *buf)
932f595a68aSyz147064 {
933f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*secmode, secmode_vals,
934f595a68aSyz147064 VALCNT(secmode_vals), buf));
935f595a68aSyz147064 }
936f595a68aSyz147064
937f595a68aSyz147064 const char *
dladm_wlan_strength2str(dladm_wlan_strength_t * strength,char * buf)938f595a68aSyz147064 dladm_wlan_strength2str(dladm_wlan_strength_t *strength, char *buf)
939f595a68aSyz147064 {
940f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*strength, strength_vals,
941f595a68aSyz147064 VALCNT(strength_vals), buf));
942f595a68aSyz147064 }
943f595a68aSyz147064
944f595a68aSyz147064 const char *
dladm_wlan_mode2str(dladm_wlan_mode_t * mode,char * buf)945f595a68aSyz147064 dladm_wlan_mode2str(dladm_wlan_mode_t *mode, char *buf)
946f595a68aSyz147064 {
947f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*mode, mode_vals,
948f595a68aSyz147064 VALCNT(mode_vals), buf));
949f595a68aSyz147064 }
950f595a68aSyz147064
951f595a68aSyz147064 const char *
dladm_wlan_speed2str(dladm_wlan_speed_t * speed,char * buf)952f595a68aSyz147064 dladm_wlan_speed2str(dladm_wlan_speed_t *speed, char *buf)
953f595a68aSyz147064 {
954f595a68aSyz147064 (void) snprintf(buf, DLADM_STRSIZE, "%.*f", *speed % 2,
955f595a68aSyz147064 (float)(*speed) / 2);
956f595a68aSyz147064 return (buf);
957f595a68aSyz147064 }
958f595a68aSyz147064
959f595a68aSyz147064 const char *
dladm_wlan_auth2str(dladm_wlan_auth_t * auth,char * buf)960f595a68aSyz147064 dladm_wlan_auth2str(dladm_wlan_auth_t *auth, char *buf)
961f595a68aSyz147064 {
962f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*auth, auth_vals,
963f595a68aSyz147064 VALCNT(auth_vals), buf));
964f595a68aSyz147064 }
965f595a68aSyz147064
966f595a68aSyz147064 const char *
dladm_wlan_bsstype2str(dladm_wlan_bsstype_t * bsstype,char * buf)967f595a68aSyz147064 dladm_wlan_bsstype2str(dladm_wlan_bsstype_t *bsstype, char *buf)
968f595a68aSyz147064 {
969f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*bsstype, bsstype_vals,
970f595a68aSyz147064 VALCNT(bsstype_vals), buf));
971f595a68aSyz147064 }
972f595a68aSyz147064
973f595a68aSyz147064 const char *
dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t * linkstatus,char * buf)974f595a68aSyz147064 dladm_wlan_linkstatus2str(dladm_wlan_linkstatus_t *linkstatus, char *buf)
975f595a68aSyz147064 {
976f595a68aSyz147064 return (dladm_wlan_val2str((uint_t)*linkstatus, linkstatus_vals,
977f595a68aSyz147064 VALCNT(linkstatus_vals), buf));
978f595a68aSyz147064 }
979f595a68aSyz147064
980f595a68aSyz147064 dladm_status_t
dladm_wlan_str2essid(const char * str,dladm_wlan_essid_t * essid)981f595a68aSyz147064 dladm_wlan_str2essid(const char *str, dladm_wlan_essid_t *essid)
982f595a68aSyz147064 {
9830d2f4bc9Sff224033 if (str[0] == '\0' || strlen(str) > DLADM_WLAN_MAX_ESSID_LEN - 1)
984f595a68aSyz147064 return (DLADM_STATUS_BADARG);
985f595a68aSyz147064
986f595a68aSyz147064 (void) strlcpy(essid->we_bytes, str, DLADM_WLAN_MAX_ESSID_LEN);
987f595a68aSyz147064 return (DLADM_STATUS_OK);
988f595a68aSyz147064 }
989f595a68aSyz147064
990f595a68aSyz147064 dladm_status_t
dladm_wlan_str2bssid(const char * str,dladm_wlan_bssid_t * bssid)991f595a68aSyz147064 dladm_wlan_str2bssid(const char *str, dladm_wlan_bssid_t *bssid)
992f595a68aSyz147064 {
993f595a68aSyz147064 int len;
994f595a68aSyz147064 uchar_t *buf;
995f595a68aSyz147064
996f595a68aSyz147064 buf = _link_aton(str, &len);
997f595a68aSyz147064 if (buf == NULL)
998f595a68aSyz147064 return (DLADM_STATUS_BADARG);
999f595a68aSyz147064
1000f595a68aSyz147064 if (len != DLADM_WLAN_BSSID_LEN) {
1001f595a68aSyz147064 free(buf);
1002f595a68aSyz147064 return (DLADM_STATUS_BADARG);
1003f595a68aSyz147064 }
1004f595a68aSyz147064
1005f595a68aSyz147064 (void) memcpy(bssid->wb_bytes, buf, len);
1006f595a68aSyz147064 free(buf);
1007f595a68aSyz147064 return (DLADM_STATUS_OK);
1008f595a68aSyz147064 }
1009f595a68aSyz147064
1010f595a68aSyz147064 dladm_status_t
dladm_wlan_str2secmode(const char * str,dladm_wlan_secmode_t * secmode)1011f595a68aSyz147064 dladm_wlan_str2secmode(const char *str, dladm_wlan_secmode_t *secmode)
1012f595a68aSyz147064 {
1013f595a68aSyz147064 uint_t val;
1014f595a68aSyz147064
1015f595a68aSyz147064 if (!find_val_by_name(str, secmode_vals, VALCNT(secmode_vals), &val))
1016f595a68aSyz147064 return (DLADM_STATUS_BADARG);
1017f595a68aSyz147064
1018f595a68aSyz147064 *secmode = (dladm_wlan_secmode_t)val;
1019f595a68aSyz147064 return (DLADM_STATUS_OK);
1020f595a68aSyz147064 }
1021f595a68aSyz147064
1022f595a68aSyz147064 dladm_status_t
dladm_wlan_str2strength(const char * str,dladm_wlan_strength_t * strength)1023f595a68aSyz147064 dladm_wlan_str2strength(const char *str, dladm_wlan_strength_t *strength)
1024f595a68aSyz147064 {
1025f595a68aSyz147064 uint_t val;
1026f595a68aSyz147064
1027f595a68aSyz147064 if (!find_val_by_name(str, strength_vals, VALCNT(strength_vals), &val))
1028f595a68aSyz147064 return (DLADM_STATUS_BADARG);
1029f595a68aSyz147064
1030f595a68aSyz147064 *strength = (dladm_wlan_strength_t)val;
1031f595a68aSyz147064 return (DLADM_STATUS_OK);
1032f595a68aSyz147064 }
1033f595a68aSyz147064
1034f595a68aSyz147064 dladm_status_t
dladm_wlan_str2mode(const char * str,dladm_wlan_mode_t * mode)1035f595a68aSyz147064 dladm_wlan_str2mode(const char *str, dladm_wlan_mode_t *mode)
1036f595a68aSyz147064 {
1037f595a68aSyz147064 uint_t val;
1038f595a68aSyz147064
1039f595a68aSyz147064 if (!find_val_by_name(str, mode_vals, VALCNT(mode_vals), &val))
1040f595a68aSyz147064 return (DLADM_STATUS_BADARG);
1041f595a68aSyz147064
1042f595a68aSyz147064 *mode = (dladm_wlan_mode_t)val;
1043f595a68aSyz147064 return (DLADM_STATUS_OK);
1044f595a68aSyz147064 }
1045f595a68aSyz147064
1046f595a68aSyz147064 dladm_status_t
dladm_wlan_str2speed(const char * str,dladm_wlan_speed_t * speed)1047f595a68aSyz147064 dladm_wlan_str2speed(const char *str, dladm_wlan_speed_t *speed)
1048f595a68aSyz147064 {
1049f595a68aSyz147064 *speed = (dladm_wlan_speed_t)(atof(str) * 2);
1050f595a68aSyz147064 return (DLADM_STATUS_OK);
1051f595a68aSyz147064 }
1052f595a68aSyz147064
1053f595a68aSyz147064 dladm_status_t
dladm_wlan_str2auth(const char * str,dladm_wlan_auth_t * auth)1054f595a68aSyz147064 dladm_wlan_str2auth(const char *str, dladm_wlan_auth_t *auth)
1055f595a68aSyz147064 {
1056f595a68aSyz147064 uint_t val;
1057f595a68aSyz147064
1058f595a68aSyz147064 if (!find_val_by_name(str, auth_vals, VALCNT(auth_vals), &val))
1059f595a68aSyz147064 return (DLADM_STATUS_BADARG);
1060f595a68aSyz147064
1061f595a68aSyz147064 *auth = (dladm_wlan_auth_t)val;
1062f595a68aSyz147064 return (DLADM_STATUS_OK);
1063f595a68aSyz147064 }
1064f595a68aSyz147064
1065f595a68aSyz147064 dladm_status_t
dladm_wlan_str2bsstype(const char * str,dladm_wlan_bsstype_t * bsstype)1066f595a68aSyz147064 dladm_wlan_str2bsstype(const char *str, dladm_wlan_bsstype_t *bsstype)
1067f595a68aSyz147064 {
1068f595a68aSyz147064 uint_t val;
1069f595a68aSyz147064
1070f595a68aSyz147064 if (!find_val_by_name(str, bsstype_vals, VALCNT(bsstype_vals), &val))
1071f595a68aSyz147064 return (DLADM_STATUS_BADARG);
1072f595a68aSyz147064
1073f595a68aSyz147064 *bsstype = (dladm_wlan_bsstype_t)val;
1074f595a68aSyz147064 return (DLADM_STATUS_OK);
1075f595a68aSyz147064 }
1076f595a68aSyz147064
1077f595a68aSyz147064 dladm_status_t
dladm_wlan_str2linkstatus(const char * str,dladm_wlan_linkstatus_t * linkstatus)1078f595a68aSyz147064 dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus)
1079f595a68aSyz147064 {
1080f595a68aSyz147064 uint_t val;
1081f595a68aSyz147064
1082d62bc4baSyz147064 if (!find_val_by_name(str, linkstatus_vals,
1083d62bc4baSyz147064 VALCNT(linkstatus_vals), &val)) {
1084f595a68aSyz147064 return (DLADM_STATUS_BADARG);
1085d62bc4baSyz147064 }
1086f595a68aSyz147064
1087f595a68aSyz147064 *linkstatus = (dladm_wlan_linkstatus_t)val;
1088f595a68aSyz147064 return (DLADM_STATUS_OK);
1089f595a68aSyz147064 }
1090f595a68aSyz147064
1091d62bc4baSyz147064 dladm_status_t
i_dladm_wlan_legacy_ioctl(dladm_handle_t handle,datalink_id_t linkid,wldp_t * gbuf,uint_t id,size_t len,uint_t cmd,size_t cmdlen)10924ac67f02SAnurag S. Maskey i_dladm_wlan_legacy_ioctl(dladm_handle_t handle, datalink_id_t linkid,
10934ac67f02SAnurag S. Maskey wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen)
1094f595a68aSyz147064 {
1095d62bc4baSyz147064 char linkname[MAXPATHLEN];
1096d62bc4baSyz147064 int fd, rc;
1097f595a68aSyz147064 struct strioctl stri;
1098d62bc4baSyz147064 uint32_t flags;
1099d62bc4baSyz147064 dladm_status_t status;
1100d62bc4baSyz147064 uint32_t media;
1101d62bc4baSyz147064 char link[MAXLINKNAMELEN];
1102d62bc4baSyz147064
11034ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
11044ac67f02SAnurag S. Maskey &media, link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
1105d62bc4baSyz147064 return (status);
1106d62bc4baSyz147064 }
1107d62bc4baSyz147064
1108d62bc4baSyz147064 if (media != DL_WIFI)
1109d62bc4baSyz147064 return (DLADM_STATUS_BADARG);
1110d62bc4baSyz147064
1111d62bc4baSyz147064 if (!(flags & DLADM_OPT_ACTIVE))
1112d62bc4baSyz147064 return (DLADM_STATUS_TEMPONLY);
1113d62bc4baSyz147064
1114d62bc4baSyz147064 /*
1115d62bc4baSyz147064 * dlpi_open() is not used here because libdlpi depends on libdladm,
1116d62bc4baSyz147064 * and we do not want to introduce recursive dependencies.
1117d62bc4baSyz147064 */
1118d62bc4baSyz147064 (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link);
1119d62bc4baSyz147064 if ((fd = open(linkname, O_RDWR)) < 0)
1120eae72b5bSSebastien Roy return (dladm_errno2status(errno));
1121f595a68aSyz147064
1122f595a68aSyz147064 gbuf->wldp_type = NET_802_11;
1123f595a68aSyz147064 gbuf->wldp_id = id;
1124f595a68aSyz147064 gbuf->wldp_length = len;
1125f595a68aSyz147064
1126f595a68aSyz147064 stri.ic_timout = 0;
1127f595a68aSyz147064 stri.ic_dp = (char *)gbuf;
1128f595a68aSyz147064 stri.ic_cmd = cmd;
1129f595a68aSyz147064 stri.ic_len = cmdlen;
1130f595a68aSyz147064
1131f595a68aSyz147064 if ((rc = ioctl(fd, I_STR, &stri)) != 0) {
1132d62bc4baSyz147064 if (rc > 0) {
1133d62bc4baSyz147064 /*
1134d62bc4baSyz147064 * Non-negative return value indicates the specific
1135d62bc4baSyz147064 * operation failed and the reason for the failure
1136d62bc4baSyz147064 * was stored in gbuf->wldp_result.
1137d62bc4baSyz147064 */
1138d62bc4baSyz147064 status = dladm_wlan_wlresult2status(gbuf);
1139d62bc4baSyz147064 } else {
1140d62bc4baSyz147064 /*
1141d62bc4baSyz147064 * Negative return value indicates the ioctl failed.
1142d62bc4baSyz147064 */
1143d62bc4baSyz147064 status = dladm_errno2status(errno);
1144f595a68aSyz147064 }
1145d62bc4baSyz147064 }
1146d62bc4baSyz147064 (void) close(fd);
1147d62bc4baSyz147064 return (status);
1148f595a68aSyz147064 }
1149f595a68aSyz147064
1150bcb5c89dSSowmini Varadhan static dladm_status_t
do_cmd_ioctl(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen,uint_t cmd)11514ac67f02SAnurag S. Maskey do_cmd_ioctl(dladm_handle_t handle, datalink_id_t linkid, void *buf,
11524ac67f02SAnurag S. Maskey int buflen, uint_t cmd)
1153f595a68aSyz147064 {
1154d62bc4baSyz147064 wldp_t *gbuf;
1155d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_OK;
1156d62bc4baSyz147064
1157d62bc4baSyz147064 if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
1158d62bc4baSyz147064 return (DLADM_STATUS_NOMEM);
1159d62bc4baSyz147064
1160f595a68aSyz147064 (void) memset(gbuf, 0, MAX_BUF_LEN);
11614ac67f02SAnurag S. Maskey status = i_dladm_wlan_legacy_ioctl(handle, linkid, gbuf, cmd,
11624ac67f02SAnurag S. Maskey WLDP_BUFSIZE, WLAN_COMMAND, sizeof (wldp_t));
1163bcb5c89dSSowmini Varadhan (void) memcpy(buf, gbuf->wldp_buf, buflen);
1164d62bc4baSyz147064 free(gbuf);
1165d62bc4baSyz147064 return (status);
1166f595a68aSyz147064 }
1167f595a68aSyz147064
1168d62bc4baSyz147064 static dladm_status_t
do_scan(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)11694ac67f02SAnurag S. Maskey do_scan(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
1170f595a68aSyz147064 {
11714ac67f02SAnurag S. Maskey return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_SCAN));
1172f595a68aSyz147064 }
1173f595a68aSyz147064
1174d62bc4baSyz147064 static dladm_status_t
do_disconnect(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)11754ac67f02SAnurag S. Maskey do_disconnect(dladm_handle_t handle, datalink_id_t linkid, void *buf,
11764ac67f02SAnurag S. Maskey int buflen)
1177f595a68aSyz147064 {
11784ac67f02SAnurag S. Maskey if (do_get_wpamode(handle, linkid, buf, buflen) == 0 &&
1179bcb5c89dSSowmini Varadhan ((wl_wpa_t *)(buf))->wpa_flag > 0)
11804ac67f02SAnurag S. Maskey (void) wpa_instance_delete(handle, linkid);
1181a399b765Szf162725
11824ac67f02SAnurag S. Maskey return (do_cmd_ioctl(handle, linkid, buf, buflen, WL_DISASSOCIATE));
1183f595a68aSyz147064 }
1184f595a68aSyz147064
1185d62bc4baSyz147064 static dladm_status_t
do_get_esslist(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)11864ac67f02SAnurag S. Maskey do_get_esslist(dladm_handle_t handle, datalink_id_t linkid, void *buf,
11874ac67f02SAnurag S. Maskey int buflen)
1188f595a68aSyz147064 {
11894ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESS_LIST,
1190bcb5c89dSSowmini Varadhan buflen, B_FALSE));
1191f595a68aSyz147064 }
1192f595a68aSyz147064
1193f595a68aSyz147064 static dladm_status_t
do_get_bssid(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)11944ac67f02SAnurag S. Maskey do_get_bssid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
1195f595a68aSyz147064 {
11964ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_BSSID,
1197bcb5c89dSSowmini Varadhan buflen, B_FALSE));
1198d62bc4baSyz147064 }
1199d62bc4baSyz147064
1200d62bc4baSyz147064 static dladm_status_t
do_get_essid(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12014ac67f02SAnurag S. Maskey do_get_essid(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
12024ac67f02SAnurag S. Maskey {
12034ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_ESSID,
12044ac67f02SAnurag S. Maskey buflen, B_FALSE));
12054ac67f02SAnurag S. Maskey }
12064ac67f02SAnurag S. Maskey
12074ac67f02SAnurag S. Maskey static dladm_status_t
do_get_bsstype(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12084ac67f02SAnurag S. Maskey do_get_bsstype(dladm_handle_t handle, datalink_id_t linkid, void *buf,
12094ac67f02SAnurag S. Maskey int buflen)
12104ac67f02SAnurag S. Maskey {
12114ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_BSSTYPE,
12124ac67f02SAnurag S. Maskey buflen, B_FALSE));
12134ac67f02SAnurag S. Maskey }
12144ac67f02SAnurag S. Maskey
12154ac67f02SAnurag S. Maskey static dladm_status_t
do_get_linkstatus(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12164ac67f02SAnurag S. Maskey do_get_linkstatus(dladm_handle_t handle, datalink_id_t linkid, void *buf,
12174ac67f02SAnurag S. Maskey int buflen)
12184ac67f02SAnurag S. Maskey {
12194ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_LINKSTATUS,
12204ac67f02SAnurag S. Maskey buflen, B_FALSE));
12214ac67f02SAnurag S. Maskey }
12224ac67f02SAnurag S. Maskey
12234ac67f02SAnurag S. Maskey static dladm_status_t
do_get_rate(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12244ac67f02SAnurag S. Maskey do_get_rate(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
12254ac67f02SAnurag S. Maskey {
12264ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf,
12274ac67f02SAnurag S. Maskey MAC_PROP_WL_DESIRED_RATES, buflen, B_FALSE));
12284ac67f02SAnurag S. Maskey }
12294ac67f02SAnurag S. Maskey
12304ac67f02SAnurag S. Maskey static dladm_status_t
do_get_authmode(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12314ac67f02SAnurag S. Maskey do_get_authmode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
12324ac67f02SAnurag S. Maskey int buflen)
12334ac67f02SAnurag S. Maskey {
12344ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf,
12354ac67f02SAnurag S. Maskey MAC_PROP_WL_AUTH_MODE, buflen, B_FALSE));
12364ac67f02SAnurag S. Maskey }
12374ac67f02SAnurag S. Maskey
12384ac67f02SAnurag S. Maskey static dladm_status_t
do_get_encryption(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12394ac67f02SAnurag S. Maskey do_get_encryption(dladm_handle_t handle, datalink_id_t linkid, void *buf,
12404ac67f02SAnurag S. Maskey int buflen)
12414ac67f02SAnurag S. Maskey {
12424ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf,
12434ac67f02SAnurag S. Maskey MAC_PROP_WL_ENCRYPTION, buflen, B_FALSE));
12444ac67f02SAnurag S. Maskey }
12454ac67f02SAnurag S. Maskey
12464ac67f02SAnurag S. Maskey static dladm_status_t
do_get_signal(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12474ac67f02SAnurag S. Maskey do_get_signal(dladm_handle_t handle, datalink_id_t linkid, void *buf,
12484ac67f02SAnurag S. Maskey int buflen)
12494ac67f02SAnurag S. Maskey {
12504ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_RSSI,
12514ac67f02SAnurag S. Maskey buflen, B_FALSE));
12524ac67f02SAnurag S. Maskey }
12534ac67f02SAnurag S. Maskey
12544ac67f02SAnurag S. Maskey static dladm_status_t
do_get_mode(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)12554ac67f02SAnurag S. Maskey do_get_mode(dladm_handle_t handle, datalink_id_t linkid, void *buf, int buflen)
12564ac67f02SAnurag S. Maskey {
12574ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_PHY_CONFIG,
12584ac67f02SAnurag S. Maskey buflen, B_FALSE));
12594ac67f02SAnurag S. Maskey }
12604ac67f02SAnurag S. Maskey
12614ac67f02SAnurag S. Maskey static dladm_status_t
do_set_bsstype(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_bsstype_t * bsstype)12624ac67f02SAnurag S. Maskey do_set_bsstype(dladm_handle_t handle, datalink_id_t linkid,
12634ac67f02SAnurag S. Maskey dladm_wlan_bsstype_t *bsstype)
1264f595a68aSyz147064 {
1265f595a68aSyz147064 wl_bss_type_t ibsstype;
1266f595a68aSyz147064
1267f595a68aSyz147064 switch (*bsstype) {
1268f595a68aSyz147064 case DLADM_WLAN_BSSTYPE_BSS:
1269f595a68aSyz147064 ibsstype = WL_BSS_BSS;
1270f595a68aSyz147064 break;
1271f595a68aSyz147064 case DLADM_WLAN_BSSTYPE_IBSS:
1272f595a68aSyz147064 ibsstype = WL_BSS_IBSS;
1273f595a68aSyz147064 break;
1274f595a68aSyz147064 default:
1275f595a68aSyz147064 ibsstype = WL_BSS_ANY;
1276f595a68aSyz147064 break;
1277f595a68aSyz147064 }
12784ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &ibsstype,
12794ac67f02SAnurag S. Maskey MAC_PROP_WL_BSSTYPE, sizeof (ibsstype), B_TRUE));
1280f595a68aSyz147064 }
1281f595a68aSyz147064
1282d62bc4baSyz147064 static dladm_status_t
do_set_authmode(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_auth_t * auth)12834ac67f02SAnurag S. Maskey do_set_authmode(dladm_handle_t handle, datalink_id_t linkid,
12844ac67f02SAnurag S. Maskey dladm_wlan_auth_t *auth)
1285f595a68aSyz147064 {
1286f595a68aSyz147064 wl_authmode_t auth_mode;
1287f595a68aSyz147064
1288f595a68aSyz147064 switch (*auth) {
1289f595a68aSyz147064 case DLADM_WLAN_AUTH_OPEN:
1290f595a68aSyz147064 auth_mode = WL_OPENSYSTEM;
1291f595a68aSyz147064 break;
1292f595a68aSyz147064 case DLADM_WLAN_AUTH_SHARED:
1293f595a68aSyz147064 auth_mode = WL_SHAREDKEY;
1294f595a68aSyz147064 break;
1295f595a68aSyz147064 default:
1296d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP);
1297f595a68aSyz147064 }
12984ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &auth_mode,
12994ac67f02SAnurag S. Maskey MAC_PROP_WL_AUTH_MODE, sizeof (auth_mode), B_TRUE));
1300f595a68aSyz147064 }
1301f595a68aSyz147064
1302d62bc4baSyz147064 static dladm_status_t
do_set_encryption(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_secmode_t * secmode)13034ac67f02SAnurag S. Maskey do_set_encryption(dladm_handle_t handle, datalink_id_t linkid,
13044ac67f02SAnurag S. Maskey dladm_wlan_secmode_t *secmode)
1305f595a68aSyz147064 {
1306f595a68aSyz147064 wl_encryption_t encryption;
1307f595a68aSyz147064
1308f595a68aSyz147064 switch (*secmode) {
1309f595a68aSyz147064 case DLADM_WLAN_SECMODE_NONE:
1310f595a68aSyz147064 encryption = WL_NOENCRYPTION;
1311f595a68aSyz147064 break;
1312f595a68aSyz147064 case DLADM_WLAN_SECMODE_WEP:
1313f595a68aSyz147064 encryption = WL_ENC_WEP;
1314f595a68aSyz147064 break;
1315a399b765Szf162725 case DLADM_WLAN_SECMODE_WPA:
1316a399b765Szf162725 return (0);
1317f595a68aSyz147064 default:
1318d62bc4baSyz147064 return (DLADM_STATUS_NOTSUP);
1319f595a68aSyz147064 }
13204ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &encryption,
13214ac67f02SAnurag S. Maskey MAC_PROP_WL_ENCRYPTION, sizeof (encryption), B_TRUE));
1322f595a68aSyz147064 }
1323f595a68aSyz147064
1324d62bc4baSyz147064 static dladm_status_t
do_set_key(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_key_t * keys,uint_t key_count)13254ac67f02SAnurag S. Maskey do_set_key(dladm_handle_t handle, datalink_id_t linkid, dladm_wlan_key_t *keys,
1326f595a68aSyz147064 uint_t key_count)
1327f595a68aSyz147064 {
1328f595a68aSyz147064 int i;
1329f595a68aSyz147064 wl_wep_key_t *wkp;
1330f595a68aSyz147064 wl_wep_key_tab_t wepkey_tab;
1331a399b765Szf162725 dladm_wlan_key_t *kp;
1332f595a68aSyz147064
1333f595a68aSyz147064 if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL)
1334d62bc4baSyz147064 return (DLADM_STATUS_BADARG);
1335f595a68aSyz147064
1336f595a68aSyz147064 (void) memset(wepkey_tab, 0, sizeof (wepkey_tab));
1337f595a68aSyz147064 for (i = 0; i < MAX_NWEPKEYS; i++)
1338f595a68aSyz147064 wepkey_tab[i].wl_wep_operation = WL_NUL;
1339f595a68aSyz147064
1340f595a68aSyz147064 for (i = 0; i < key_count; i++) {
1341f595a68aSyz147064 kp = &keys[i];
1342f595a68aSyz147064 if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS)
1343d62bc4baSyz147064 return (DLADM_STATUS_BADARG);
1344f595a68aSyz147064 if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN &&
1345f595a68aSyz147064 kp->wk_len != DLADM_WLAN_WEPKEY128_LEN)
1346d62bc4baSyz147064 return (DLADM_STATUS_BADARG);
1347f595a68aSyz147064
1348f595a68aSyz147064 wkp = &wepkey_tab[kp->wk_idx - 1];
1349f595a68aSyz147064 wkp->wl_wep_operation = WL_ADD;
1350f595a68aSyz147064 wkp->wl_wep_length = kp->wk_len;
1351f595a68aSyz147064 (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len);
1352f595a68aSyz147064 }
1353f595a68aSyz147064
13544ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wepkey_tab,
13554ac67f02SAnurag S. Maskey MAC_PROP_WL_KEY_TAB, sizeof (wepkey_tab), B_TRUE));
1356f595a68aSyz147064 }
1357f595a68aSyz147064
1358d62bc4baSyz147064 static dladm_status_t
do_set_essid(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_essid_t * essid)13594ac67f02SAnurag S. Maskey do_set_essid(dladm_handle_t handle, datalink_id_t linkid,
13604ac67f02SAnurag S. Maskey dladm_wlan_essid_t *essid)
1361f595a68aSyz147064 {
1362f595a68aSyz147064 wl_essid_t iessid;
1363f595a68aSyz147064
1364f595a68aSyz147064 (void) memset(&iessid, 0, sizeof (essid));
1365f595a68aSyz147064
1366f595a68aSyz147064 if (essid != NULL && essid->we_bytes[0] != '\0') {
1367f595a68aSyz147064 iessid.wl_essid_length = strlen(essid->we_bytes);
1368f595a68aSyz147064 (void) strlcpy(iessid.wl_essid_essid, essid->we_bytes,
1369f595a68aSyz147064 sizeof (iessid.wl_essid_essid));
1370f595a68aSyz147064 } else {
1371d62bc4baSyz147064 return (DLADM_STATUS_BADARG);
1372f595a68aSyz147064 }
13734ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &iessid, MAC_PROP_WL_ESSID,
1374bcb5c89dSSowmini Varadhan sizeof (iessid), B_TRUE));
1375f595a68aSyz147064 }
1376f595a68aSyz147064
1377f595a68aSyz147064 static dladm_status_t
do_set_channel(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_channel_t * channel)13784ac67f02SAnurag S. Maskey do_set_channel(dladm_handle_t handle, datalink_id_t linkid,
13794ac67f02SAnurag S. Maskey dladm_wlan_channel_t *channel)
1380f595a68aSyz147064 {
1381f595a68aSyz147064 wl_phy_conf_t phy_conf;
1382f595a68aSyz147064
1383f595a68aSyz147064 if (*channel > MAX_CHANNEL_NUM)
1384d62bc4baSyz147064 return (DLADM_STATUS_BADVAL);
1385f595a68aSyz147064
1386f595a68aSyz147064 (void) memset(&phy_conf, 0xff, sizeof (phy_conf));
1387f595a68aSyz147064 phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel;
1388f595a68aSyz147064
13894ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &phy_conf,
13904ac67f02SAnurag S. Maskey MAC_PROP_WL_PHY_CONFIG, sizeof (phy_conf), B_TRUE));
1391f595a68aSyz147064 }
1392f595a68aSyz147064
1393d62bc4baSyz147064 static dladm_status_t
do_set_createibss(dladm_handle_t handle,datalink_id_t linkid,boolean_t * create_ibss)13944ac67f02SAnurag S. Maskey do_set_createibss(dladm_handle_t handle, datalink_id_t linkid,
13954ac67f02SAnurag S. Maskey boolean_t *create_ibss)
1396f595a68aSyz147064 {
1397f595a68aSyz147064 wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss);
1398f595a68aSyz147064
13994ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &cr, MAC_PROP_WL_CREATE_IBSS,
1400bcb5c89dSSowmini Varadhan sizeof (cr), B_TRUE));
1401f595a68aSyz147064 }
1402f595a68aSyz147064
1403f595a68aSyz147064 static void
generate_essid(dladm_wlan_essid_t * essid)1404f595a68aSyz147064 generate_essid(dladm_wlan_essid_t *essid)
1405f595a68aSyz147064 {
1406f595a68aSyz147064 srandom(gethrtime());
1407f595a68aSyz147064 (void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d",
1408f595a68aSyz147064 random());
1409f595a68aSyz147064 }
1410a399b765Szf162725
1411d62bc4baSyz147064 static dladm_status_t
do_get_capability(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)14124ac67f02SAnurag S. Maskey do_get_capability(dladm_handle_t handle, datalink_id_t linkid, void *buf,
14134ac67f02SAnurag S. Maskey int buflen)
1414a399b765Szf162725 {
14154ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_CAPABILITY,
1416bcb5c89dSSowmini Varadhan buflen, B_FALSE));
1417a399b765Szf162725 }
1418a399b765Szf162725
1419a399b765Szf162725 static dladm_status_t
do_get_wpamode(dladm_handle_t handle,datalink_id_t linkid,void * buf,int buflen)14204ac67f02SAnurag S. Maskey do_get_wpamode(dladm_handle_t handle, datalink_id_t linkid, void *buf,
14214ac67f02SAnurag S. Maskey int buflen)
1422a399b765Szf162725 {
14234ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, buf, MAC_PROP_WL_WPA, buflen,
1424bcb5c89dSSowmini Varadhan B_FALSE));
1425a399b765Szf162725 }
1426a399b765Szf162725
1427a399b765Szf162725 dladm_status_t
dladm_wlan_wpa_get_sr(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_ess_t * sr,uint_t escnt,uint_t * estot)14284ac67f02SAnurag S. Maskey dladm_wlan_wpa_get_sr(dladm_handle_t handle, datalink_id_t linkid,
14294ac67f02SAnurag S. Maskey dladm_wlan_ess_t *sr, uint_t escnt, uint_t *estot)
1430a399b765Szf162725 {
1431a399b765Szf162725 int i, n;
1432a399b765Szf162725 wl_wpa_ess_t *es;
1433a399b765Szf162725 dladm_status_t status;
1434a399b765Szf162725
1435bcb5c89dSSowmini Varadhan es = malloc(WLDP_BUFSIZE);
1436bcb5c89dSSowmini Varadhan if (es == NULL)
1437a399b765Szf162725 return (DLADM_STATUS_NOMEM);
1438a399b765Szf162725
14394ac67f02SAnurag S. Maskey status = i_dladm_wlan_param(handle, linkid, es, MAC_PROP_WL_SCANRESULTS,
1440bcb5c89dSSowmini Varadhan WLDP_BUFSIZE, B_FALSE);
1441a399b765Szf162725
1442a399b765Szf162725 if (status == DLADM_STATUS_OK) {
1443a399b765Szf162725 n = (es->count > escnt) ? escnt : es->count;
1444a399b765Szf162725 for (i = 0; i < n; i ++) {
1445a399b765Szf162725 (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid,
1446a399b765Szf162725 DLADM_WLAN_BSSID_LEN);
1447a399b765Szf162725 sr[i].we_ssid_len = es->ess[i].ssid_len;
1448a399b765Szf162725 (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid,
1449a399b765Szf162725 es->ess[i].ssid_len);
1450a399b765Szf162725 sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len;
1451a399b765Szf162725 (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie,
1452a399b765Szf162725 es->ess[i].wpa_ie_len);
1453a399b765Szf162725 sr[i].we_freq = es->ess[i].freq;
1454a399b765Szf162725 }
1455a399b765Szf162725 *estot = n;
1456a399b765Szf162725 }
1457a399b765Szf162725
1458bcb5c89dSSowmini Varadhan free(es);
1459a399b765Szf162725 return (status);
1460a399b765Szf162725 }
1461a399b765Szf162725
1462a399b765Szf162725 dladm_status_t
dladm_wlan_wpa_set_ie(dladm_handle_t handle,datalink_id_t linkid,uint8_t * wpa_ie,uint_t wpa_ie_len)14634ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_ie(dladm_handle_t handle, datalink_id_t linkid,
14644ac67f02SAnurag S. Maskey uint8_t *wpa_ie, uint_t wpa_ie_len)
1465a399b765Szf162725 {
1466a399b765Szf162725 wl_wpa_ie_t *ie;
1467a399b765Szf162725 uint_t len;
1468a399b765Szf162725 dladm_status_t status;
1469a399b765Szf162725
1470a399b765Szf162725 if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN)
1471a399b765Szf162725 return (DLADM_STATUS_BADARG);
1472a399b765Szf162725 len = sizeof (wl_wpa_ie_t) + wpa_ie_len;
1473a399b765Szf162725 ie = malloc(len);
1474a399b765Szf162725 if (ie == NULL)
1475a399b765Szf162725 return (DLADM_STATUS_NOMEM);
1476a399b765Szf162725
1477a399b765Szf162725 (void) memset(ie, 0, len);
1478a399b765Szf162725 ie->wpa_ie_len = wpa_ie_len;
1479a399b765Szf162725 (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len);
1480a399b765Szf162725
14814ac67f02SAnurag S. Maskey status = i_dladm_wlan_param(handle, linkid, ie, MAC_PROP_WL_SETOPTIE,
14824ac67f02SAnurag S. Maskey len, B_TRUE);
1483a399b765Szf162725 free(ie);
1484a399b765Szf162725
1485a399b765Szf162725 return (status);
1486a399b765Szf162725 }
1487a399b765Szf162725
1488a399b765Szf162725 dladm_status_t
dladm_wlan_wpa_set_wpa(dladm_handle_t handle,datalink_id_t linkid,boolean_t flag)14894ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_wpa(dladm_handle_t handle, datalink_id_t linkid,
14904ac67f02SAnurag S. Maskey boolean_t flag)
1491a399b765Szf162725 {
1492a399b765Szf162725 wl_wpa_t wpa;
1493a399b765Szf162725
1494a399b765Szf162725 wpa.wpa_flag = flag;
14954ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wpa, MAC_PROP_WL_WPA,
1496bcb5c89dSSowmini Varadhan sizeof (wpa), B_TRUE));
1497a399b765Szf162725 }
1498a399b765Szf162725
1499a399b765Szf162725 dladm_status_t
dladm_wlan_wpa_del_key(dladm_handle_t handle,datalink_id_t linkid,uint_t key_idx,const dladm_wlan_bssid_t * addr)15004ac67f02SAnurag S. Maskey dladm_wlan_wpa_del_key(dladm_handle_t handle, datalink_id_t linkid,
15014ac67f02SAnurag S. Maskey uint_t key_idx, const dladm_wlan_bssid_t *addr)
1502a399b765Szf162725 {
1503a399b765Szf162725 wl_del_key_t wk;
1504a399b765Szf162725
1505a399b765Szf162725 wk.idk_keyix = key_idx;
1506a399b765Szf162725 if (addr != NULL)
1507a399b765Szf162725 (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes,
1508a399b765Szf162725 DLADM_WLAN_BSSID_LEN);
1509a399b765Szf162725
15104ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_DELKEY,
1511bcb5c89dSSowmini Varadhan sizeof (wk), B_TRUE));
1512a399b765Szf162725 }
1513a399b765Szf162725
1514a399b765Szf162725 dladm_status_t
dladm_wlan_wpa_set_key(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_cipher_t cipher,const dladm_wlan_bssid_t * addr,boolean_t set_tx,uint64_t seq,uint_t key_idx,uint8_t * key,uint_t key_len)15154ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_key(dladm_handle_t handle, datalink_id_t linkid,
15164ac67f02SAnurag S. Maskey dladm_wlan_cipher_t cipher, const dladm_wlan_bssid_t *addr,
15174ac67f02SAnurag S. Maskey boolean_t set_tx, uint64_t seq, uint_t key_idx, uint8_t *key,
15184ac67f02SAnurag S. Maskey uint_t key_len)
1519a399b765Szf162725 {
1520a399b765Szf162725 wl_key_t wk;
1521a399b765Szf162725
1522a399b765Szf162725 (void) memset(&wk, 0, sizeof (wl_key_t));
1523a399b765Szf162725 switch (cipher) {
1524a399b765Szf162725 case DLADM_WLAN_CIPHER_WEP:
1525a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_WEP;
1526a399b765Szf162725 break;
1527a399b765Szf162725 case DLADM_WLAN_CIPHER_TKIP:
1528a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_TKIP;
1529a399b765Szf162725 break;
1530a399b765Szf162725 case DLADM_WLAN_CIPHER_AES_OCB:
1531a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_OCB;
1532a399b765Szf162725 break;
1533a399b765Szf162725 case DLADM_WLAN_CIPHER_AES_CCM:
1534a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_AES_CCM;
1535a399b765Szf162725 break;
1536a399b765Szf162725 case DLADM_WLAN_CIPHER_CKIP:
1537a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_CKIP;
1538a399b765Szf162725 break;
1539a399b765Szf162725 case DLADM_WLAN_CIPHER_NONE:
1540a399b765Szf162725 wk.ik_type = IEEE80211_CIPHER_NONE;
1541a399b765Szf162725 break;
1542a399b765Szf162725 default:
1543a399b765Szf162725 return (DLADM_STATUS_BADARG);
1544a399b765Szf162725 }
1545a399b765Szf162725 wk.ik_flags = IEEE80211_KEY_RECV;
1546a399b765Szf162725 if (set_tx) {
1547a399b765Szf162725 wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
1548a399b765Szf162725 (void) memcpy(wk.ik_macaddr, addr->wb_bytes,
1549a399b765Szf162725 DLADM_WLAN_BSSID_LEN);
1550a399b765Szf162725 } else
1551a399b765Szf162725 (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN);
1552a399b765Szf162725 wk.ik_keyix = key_idx;
1553a399b765Szf162725 wk.ik_keylen = key_len;
1554a399b765Szf162725 (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */
1555a399b765Szf162725 (void) memcpy(wk.ik_keydata, key, key_len);
1556a399b765Szf162725
15574ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &wk, MAC_PROP_WL_KEY,
1558bcb5c89dSSowmini Varadhan sizeof (wk), B_TRUE));
1559a399b765Szf162725 }
1560a399b765Szf162725
1561a399b765Szf162725 dladm_status_t
dladm_wlan_wpa_set_mlme(dladm_handle_t handle,datalink_id_t linkid,dladm_wlan_mlme_op_t op,dladm_wlan_reason_t reason,dladm_wlan_bssid_t * bssid)15624ac67f02SAnurag S. Maskey dladm_wlan_wpa_set_mlme(dladm_handle_t handle, datalink_id_t linkid,
15634ac67f02SAnurag S. Maskey dladm_wlan_mlme_op_t op, dladm_wlan_reason_t reason,
15644ac67f02SAnurag S. Maskey dladm_wlan_bssid_t *bssid)
1565a399b765Szf162725 {
1566a399b765Szf162725 wl_mlme_t mlme;
1567a399b765Szf162725
1568a399b765Szf162725 (void) memset(&mlme, 0, sizeof (wl_mlme_t));
1569a399b765Szf162725 switch (op) {
1570a399b765Szf162725 case DLADM_WLAN_MLME_ASSOC:
1571a399b765Szf162725 mlme.im_op = IEEE80211_MLME_ASSOC;
1572a399b765Szf162725 break;
1573a399b765Szf162725 case DLADM_WLAN_MLME_DISASSOC:
1574a399b765Szf162725 mlme.im_op = IEEE80211_MLME_DISASSOC;
1575a399b765Szf162725 break;
1576a399b765Szf162725 default:
1577a399b765Szf162725 return (DLADM_STATUS_BADARG);
1578a399b765Szf162725 }
1579a399b765Szf162725 mlme.im_reason = reason;
1580a399b765Szf162725 if (bssid != NULL)
1581a399b765Szf162725 (void) memcpy(mlme.im_macaddr, bssid->wb_bytes,
1582a399b765Szf162725 DLADM_WLAN_BSSID_LEN);
1583a399b765Szf162725
15844ac67f02SAnurag S. Maskey return (i_dladm_wlan_param(handle, linkid, &mlme, MAC_PROP_WL_MLME,
1585bcb5c89dSSowmini Varadhan sizeof (mlme), B_TRUE));
1586a399b765Szf162725 }
1587a399b765Szf162725
1588a399b765Szf162725 /*
1589a399b765Szf162725 * routines of create instance
1590a399b765Szf162725 */
1591a399b765Szf162725 static scf_propertygroup_t *
add_property_group_to_instance(scf_handle_t * handle,scf_instance_t * instance,const char * pg_name,const char * pg_type)1592a399b765Szf162725 add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance,
1593a399b765Szf162725 const char *pg_name, const char *pg_type)
1594a399b765Szf162725 {
1595a399b765Szf162725 scf_propertygroup_t *pg;
1596a399b765Szf162725
1597a399b765Szf162725 pg = scf_pg_create(handle);
1598a399b765Szf162725 if (pg == NULL)
1599a399b765Szf162725 return (NULL);
1600a399b765Szf162725
1601a399b765Szf162725 if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) {
1602a399b765Szf162725 scf_pg_destroy(pg);
1603a399b765Szf162725 return (NULL);
1604a399b765Szf162725 }
1605a399b765Szf162725
1606a399b765Szf162725 return (pg);
1607a399b765Szf162725 }
1608a399b765Szf162725
1609d62bc4baSyz147064 static dladm_status_t
add_new_property(scf_handle_t * handle,const char * prop_name,scf_type_t type,const char * val,scf_transaction_t * tx)1610a399b765Szf162725 add_new_property(scf_handle_t *handle, const char *prop_name,
1611a399b765Szf162725 scf_type_t type, const char *val, scf_transaction_t *tx)
1612a399b765Szf162725 {
1613a399b765Szf162725 scf_value_t *value = NULL;
1614a399b765Szf162725 scf_transaction_entry_t *entry = NULL;
1615a399b765Szf162725
1616a399b765Szf162725 entry = scf_entry_create(handle);
1617a399b765Szf162725 if (entry == NULL)
1618a399b765Szf162725 goto out;
1619a399b765Szf162725
1620a399b765Szf162725 value = scf_value_create(handle);
1621a399b765Szf162725 if (value == NULL)
1622a399b765Szf162725 goto out;
1623a399b765Szf162725
1624a399b765Szf162725 if (scf_transaction_property_new(tx, entry, prop_name, type) != 0)
1625a399b765Szf162725 goto out;
1626a399b765Szf162725
1627a399b765Szf162725 if (scf_value_set_from_string(value, type, val) != 0)
1628a399b765Szf162725 goto out;
1629a399b765Szf162725
1630a399b765Szf162725 if (scf_entry_add_value(entry, value) != 0)
1631a399b765Szf162725 goto out;
1632a399b765Szf162725
1633d62bc4baSyz147064 return (DLADM_STATUS_OK);
1634a399b765Szf162725
1635a399b765Szf162725 out:
1636a399b765Szf162725 if (value != NULL)
1637a399b765Szf162725 scf_value_destroy(value);
1638a399b765Szf162725 if (entry != NULL)
1639a399b765Szf162725 scf_entry_destroy(entry);
1640a399b765Szf162725
1641d62bc4baSyz147064 return (DLADM_STATUS_FAILED);
1642a399b765Szf162725 }
1643a399b765Szf162725
1644d62bc4baSyz147064 static dladm_status_t
add_pg_method(scf_handle_t * handle,scf_instance_t * instance,const char * pg_name,const char * flags)1645a399b765Szf162725 add_pg_method(scf_handle_t *handle, scf_instance_t *instance,
1646a399b765Szf162725 const char *pg_name, const char *flags)
1647a399b765Szf162725 {
1648a399b765Szf162725 int rv, size;
1649d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED;
1650a399b765Szf162725 char *command = NULL;
1651a399b765Szf162725 scf_transaction_t *tran = NULL;
1652a399b765Szf162725 scf_propertygroup_t *pg;
1653a399b765Szf162725
1654a399b765Szf162725 pg = add_property_group_to_instance(handle, instance,
1655a399b765Szf162725 pg_name, SCF_GROUP_METHOD);
1656a399b765Szf162725 if (pg == NULL)
1657a399b765Szf162725 goto out;
1658a399b765Szf162725
1659a399b765Szf162725 tran = scf_transaction_create(handle);
1660a399b765Szf162725 if (tran == NULL)
1661a399b765Szf162725 goto out;
1662a399b765Szf162725
1663a399b765Szf162725 size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1;
1664a399b765Szf162725 command = malloc(size);
1665a399b765Szf162725 if (command == NULL) {
1666d62bc4baSyz147064 status = DLADM_STATUS_NOMEM;
1667a399b765Szf162725 goto out;
1668a399b765Szf162725 }
1669a399b765Szf162725 (void) snprintf(command, size, "%s %s", SVC_METHOD, flags);
1670a399b765Szf162725
1671a399b765Szf162725 do {
1672a399b765Szf162725 if (scf_transaction_start(tran, pg) != 0)
1673a399b765Szf162725 goto out;
1674a399b765Szf162725
1675a399b765Szf162725 if (add_new_property(handle, SCF_PROPERTY_EXEC,
1676d62bc4baSyz147064 SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) {
1677a399b765Szf162725 goto out;
1678a399b765Szf162725 }
1679a399b765Szf162725
1680a399b765Szf162725 rv = scf_transaction_commit(tran);
1681a399b765Szf162725 switch (rv) {
1682a399b765Szf162725 case 1:
1683d62bc4baSyz147064 status = DLADM_STATUS_OK;
1684a399b765Szf162725 goto out;
1685a399b765Szf162725 case 0:
1686a399b765Szf162725 scf_transaction_destroy_children(tran);
1687a399b765Szf162725 if (scf_pg_update(pg) == -1) {
1688a399b765Szf162725 goto out;
1689a399b765Szf162725 }
1690a399b765Szf162725 break;
1691a399b765Szf162725 case -1:
1692a399b765Szf162725 default:
1693a399b765Szf162725 goto out;
1694a399b765Szf162725 }
1695a399b765Szf162725 } while (rv == 0);
1696a399b765Szf162725
1697a399b765Szf162725 out:
1698a399b765Szf162725 if (tran != NULL) {
1699a399b765Szf162725 scf_transaction_destroy_children(tran);
1700a399b765Szf162725 scf_transaction_destroy(tran);
1701a399b765Szf162725 }
1702a399b765Szf162725
1703a399b765Szf162725 if (pg != NULL)
1704a399b765Szf162725 scf_pg_destroy(pg);
1705a399b765Szf162725
1706a399b765Szf162725 if (command != NULL)
1707a399b765Szf162725 free(command);
1708a399b765Szf162725
1709a399b765Szf162725 return (status);
1710a399b765Szf162725 }
1711a399b765Szf162725
1712d62bc4baSyz147064 static dladm_status_t
do_create_instance(scf_handle_t * handle,scf_service_t * svc,const char * instance_name,const char * command)1713a399b765Szf162725 do_create_instance(scf_handle_t *handle, scf_service_t *svc,
1714a399b765Szf162725 const char *instance_name, const char *command)
1715a399b765Szf162725 {
1716d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED;
1717a399b765Szf162725 char *buf;
1718a399b765Szf162725 ssize_t max_fmri_len;
1719a399b765Szf162725 scf_instance_t *instance;
1720a399b765Szf162725
1721a399b765Szf162725 instance = scf_instance_create(handle);
1722a399b765Szf162725 if (instance == NULL)
1723a399b765Szf162725 goto out;
1724a399b765Szf162725
1725a399b765Szf162725 if (scf_service_add_instance(svc, instance_name, instance) != 0) {
1726a399b765Szf162725 if (scf_error() == SCF_ERROR_EXISTS)
1727a399b765Szf162725 /* Let the caller deal with the duplicate instance */
1728d62bc4baSyz147064 status = DLADM_STATUS_EXIST;
1729a399b765Szf162725 goto out;
1730a399b765Szf162725 }
1731a399b765Szf162725
1732a399b765Szf162725 if (add_pg_method(handle, instance, "start",
1733d62bc4baSyz147064 command) != DLADM_STATUS_OK) {
1734a399b765Szf162725 goto out;
1735a399b765Szf162725 }
1736a399b765Szf162725
1737a399b765Szf162725 /* enabling the instance */
1738a399b765Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
1739a399b765Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL)
1740a399b765Szf162725 goto out;
1741a399b765Szf162725
1742a399b765Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) {
1743a399b765Szf162725 if ((smf_disable_instance(buf, 0) != 0) ||
1744a399b765Szf162725 (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) {
1745a399b765Szf162725 goto out;
1746a399b765Szf162725 }
1747d62bc4baSyz147064 status = DLADM_STATUS_OK;
1748a399b765Szf162725 }
1749a399b765Szf162725
1750a399b765Szf162725 out:
1751a399b765Szf162725 if (instance != NULL)
1752a399b765Szf162725 scf_instance_destroy(instance);
1753a399b765Szf162725 return (status);
1754a399b765Szf162725 }
1755a399b765Szf162725
1756d62bc4baSyz147064 static dladm_status_t
create_instance(const char * instance_name,const char * command)1757a399b765Szf162725 create_instance(const char *instance_name, const char *command)
1758a399b765Szf162725 {
1759d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED;
1760a399b765Szf162725 scf_service_t *svc = NULL;
1761a399b765Szf162725 scf_handle_t *handle = NULL;
1762a399b765Szf162725
1763a399b765Szf162725 handle = scf_handle_create(SCF_VERSION);
1764a399b765Szf162725 if (handle == NULL)
1765a399b765Szf162725 goto out;
1766a399b765Szf162725
1767a399b765Szf162725 if (scf_handle_bind(handle) == -1)
1768a399b765Szf162725 goto out;
1769a399b765Szf162725
1770a399b765Szf162725 if ((svc = scf_service_create(handle)) == NULL)
1771a399b765Szf162725 goto out;
1772a399b765Szf162725
1773a399b765Szf162725 if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc,
1774a399b765Szf162725 NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0)
1775a399b765Szf162725 goto out;
1776a399b765Szf162725
1777a399b765Szf162725 status = do_create_instance(handle, svc, instance_name, command);
1778a399b765Szf162725
1779a399b765Szf162725 out:
1780a399b765Szf162725 if (svc != NULL)
1781a399b765Szf162725 scf_service_destroy(svc);
1782a399b765Szf162725
1783a399b765Szf162725 if (handle != NULL) {
1784a399b765Szf162725 (void) scf_handle_unbind(handle);
1785a399b765Szf162725 scf_handle_destroy(handle);
1786a399b765Szf162725 }
1787a399b765Szf162725
1788a399b765Szf162725 return (status);
1789a399b765Szf162725 }
1790a399b765Szf162725
1791a399b765Szf162725 /*
1792a399b765Szf162725 * routines of delete instance
1793a399b765Szf162725 */
1794a399b765Szf162725 #define DEFAULT_TIMEOUT 60000000
1795a399b765Szf162725 #define INIT_WAIT_USECS 50000
1796a399b765Szf162725
1797a399b765Szf162725 static void
wait_until_disabled(scf_handle_t * handle,char * fmri)1798a399b765Szf162725 wait_until_disabled(scf_handle_t *handle, char *fmri)
1799a399b765Szf162725 {
1800a399b765Szf162725 char *state;
1801a399b765Szf162725 useconds_t max;
1802a399b765Szf162725 useconds_t usecs;
1803a399b765Szf162725 uint64_t *cp = NULL;
1804a399b765Szf162725 scf_simple_prop_t *sp = NULL;
1805a399b765Szf162725
1806a399b765Szf162725 max = DEFAULT_TIMEOUT;
1807a399b765Szf162725
1808a399b765Szf162725 if (((sp = scf_simple_prop_get(handle, fmri, "stop",
1809a399b765Szf162725 SCF_PROPERTY_TIMEOUT)) != NULL) &&
1810a399b765Szf162725 ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0))
1811a399b765Szf162725 max = (*cp) * 1000000; /* convert to usecs */
1812a399b765Szf162725
1813a399b765Szf162725 if (sp != NULL)
1814a399b765Szf162725 scf_simple_prop_free(sp);
1815a399b765Szf162725
1816a399b765Szf162725 for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) {
1817a399b765Szf162725 /* incremental wait */
1818a399b765Szf162725 usecs *= 2;
1819a399b765Szf162725 usecs = (usecs > max) ? max : usecs;
1820a399b765Szf162725
1821a399b765Szf162725 (void) usleep(usecs);
1822a399b765Szf162725
1823a399b765Szf162725 /* Check state after the wait */
1824a399b765Szf162725 if ((state = smf_get_state(fmri)) != NULL) {
1825a399b765Szf162725 if (strcmp(state, "disabled") == 0)
1826a399b765Szf162725 return;
1827a399b765Szf162725 }
1828a399b765Szf162725 }
1829a399b765Szf162725 }
1830a399b765Szf162725
1831d62bc4baSyz147064 static dladm_status_t
delete_instance(const char * instance_name)1832a399b765Szf162725 delete_instance(const char *instance_name)
1833a399b765Szf162725 {
1834d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED;
1835a399b765Szf162725 char *buf;
1836a399b765Szf162725 ssize_t max_fmri_len;
1837a399b765Szf162725 scf_scope_t *scope = NULL;
1838a399b765Szf162725 scf_service_t *svc = NULL;
1839a399b765Szf162725 scf_handle_t *handle = NULL;
1840a399b765Szf162725 scf_instance_t *instance;
1841a399b765Szf162725
1842a399b765Szf162725 handle = scf_handle_create(SCF_VERSION);
1843a399b765Szf162725 if (handle == NULL)
1844a399b765Szf162725 goto out;
1845a399b765Szf162725
1846a399b765Szf162725 if (scf_handle_bind(handle) == -1)
1847a399b765Szf162725 goto out;
1848a399b765Szf162725
1849a399b765Szf162725 if ((scope = scf_scope_create(handle)) == NULL)
1850a399b765Szf162725 goto out;
1851a399b765Szf162725
1852a399b765Szf162725 if ((svc = scf_service_create(handle)) == NULL)
1853a399b765Szf162725 goto out;
1854a399b765Szf162725
1855a399b765Szf162725 if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1)
1856a399b765Szf162725 goto out;
1857a399b765Szf162725
1858a399b765Szf162725 if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0)
1859a399b765Szf162725 goto out;
1860a399b765Szf162725
1861a399b765Szf162725 instance = scf_instance_create(handle);
1862a399b765Szf162725 if (instance == NULL)
1863a399b765Szf162725 goto out;
1864a399b765Szf162725
1865a399b765Szf162725 if (scf_service_get_instance(svc, instance_name, instance) != 0) {
1866a399b765Szf162725 scf_error_t scf_errnum = scf_error();
1867a399b765Szf162725
1868a399b765Szf162725 if (scf_errnum == SCF_ERROR_NOT_FOUND)
1869d62bc4baSyz147064 status = DLADM_STATUS_OK;
1870a399b765Szf162725
1871a399b765Szf162725 scf_instance_destroy(instance);
1872a399b765Szf162725 goto out;
1873a399b765Szf162725 }
1874a399b765Szf162725
1875a399b765Szf162725 max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
1876a399b765Szf162725 if ((buf = malloc(max_fmri_len + 1)) == NULL) {
1877a399b765Szf162725 scf_instance_destroy(instance);
1878a399b765Szf162725 goto out;
1879a399b765Szf162725 }
1880a399b765Szf162725
1881a399b765Szf162725 if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) {
1882a399b765Szf162725 char *state;
1883a399b765Szf162725
1884a399b765Szf162725 state = smf_get_state(buf);
1885a399b765Szf162725 if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 ||
1886a399b765Szf162725 strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) {
1887a399b765Szf162725 if (smf_disable_instance(buf, 0) == 0) {
1888a399b765Szf162725 /*
1889a399b765Szf162725 * Wait for some time till timeout to avoid
1890a399b765Szf162725 * a race with scf_instance_delete() below.
1891a399b765Szf162725 */
1892a399b765Szf162725 wait_until_disabled(handle, buf);
1893a399b765Szf162725 }
1894a399b765Szf162725 }
1895a399b765Szf162725 }
1896a399b765Szf162725
1897a399b765Szf162725 if (scf_instance_delete(instance) != 0) {
1898a399b765Szf162725 scf_instance_destroy(instance);
1899a399b765Szf162725 goto out;
1900a399b765Szf162725 }
1901a399b765Szf162725
1902a399b765Szf162725 scf_instance_destroy(instance);
1903a399b765Szf162725
1904d62bc4baSyz147064 status = DLADM_STATUS_OK;
1905a399b765Szf162725
1906a399b765Szf162725 out:
1907a399b765Szf162725 if (svc != NULL)
1908a399b765Szf162725 scf_service_destroy(svc);
1909a399b765Szf162725
1910a399b765Szf162725 if (scope != NULL)
1911a399b765Szf162725 scf_scope_destroy(scope);
1912a399b765Szf162725
1913a399b765Szf162725 if (handle != NULL) {
1914a399b765Szf162725 (void) scf_handle_unbind(handle);
1915a399b765Szf162725 scf_handle_destroy(handle);
1916a399b765Szf162725 }
1917a399b765Szf162725
1918a399b765Szf162725 return (status);
1919a399b765Szf162725 }
1920a399b765Szf162725
1921d62bc4baSyz147064 static dladm_status_t
wpa_instance_create(dladm_handle_t handle,datalink_id_t linkid,void * key)19224ac67f02SAnurag S. Maskey wpa_instance_create(dladm_handle_t handle, datalink_id_t linkid, void *key)
1923a399b765Szf162725 {
1924d62bc4baSyz147064 dladm_status_t status = DLADM_STATUS_FAILED;
1925a399b765Szf162725 char *command = NULL;
1926a399b765Szf162725 char *wk_name = ((dladm_wlan_key_t *)key)->wk_name;
1927a399b765Szf162725 int size;
1928d62bc4baSyz147064 char instance_name[MAXLINKNAMELEN];
1929d62bc4baSyz147064
1930d62bc4baSyz147064 /*
1931d62bc4baSyz147064 * Use the link name as the instance name of the network/wpad service.
1932d62bc4baSyz147064 */
19334ac67f02SAnurag S. Maskey status = dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL,
19344ac67f02SAnurag S. Maskey instance_name, sizeof (instance_name));
1935d62bc4baSyz147064 if (status != DLADM_STATUS_OK)
1936d62bc4baSyz147064 goto out;
1937a399b765Szf162725
1938a399b765Szf162725 size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1;
1939a399b765Szf162725 command = malloc(size);
1940a399b765Szf162725 if (command == NULL) {
1941d62bc4baSyz147064 status = DLADM_STATUS_NOMEM;
1942a399b765Szf162725 goto out;
1943a399b765Szf162725 }
1944a399b765Szf162725 (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name);
1945a399b765Szf162725
1946a399b765Szf162725 status = create_instance(instance_name, command);
1947d62bc4baSyz147064 if (status == DLADM_STATUS_EXIST) {
1948a399b765Szf162725 /*
1949a399b765Szf162725 * Delete the existing instance and create a new instance
1950a399b765Szf162725 * with the supplied arguments.
1951a399b765Szf162725 */
1952a399b765Szf162725 if ((status = delete_instance(instance_name)) ==
1953d62bc4baSyz147064 DLADM_STATUS_OK) {
1954a399b765Szf162725 status = create_instance(instance_name, command);
1955a399b765Szf162725 }
1956a399b765Szf162725 }
1957a399b765Szf162725
1958a399b765Szf162725 out:
1959a399b765Szf162725 if (command != NULL)
1960a399b765Szf162725 free(command);
1961a399b765Szf162725
1962a399b765Szf162725 return (status);
1963a399b765Szf162725 }
1964a399b765Szf162725
1965d62bc4baSyz147064 static dladm_status_t
wpa_instance_delete(dladm_handle_t handle,datalink_id_t linkid)19664ac67f02SAnurag S. Maskey wpa_instance_delete(dladm_handle_t handle, datalink_id_t linkid)
1967a399b765Szf162725 {
1968d62bc4baSyz147064 char instance_name[MAXLINKNAMELEN];
1969a399b765Szf162725
1970d62bc4baSyz147064 /*
1971d62bc4baSyz147064 * Get the instance name of the network/wpad service (the same as
1972d62bc4baSyz147064 * the link name).
1973d62bc4baSyz147064 */
19744ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(handle, linkid, NULL, NULL, NULL,
19754ac67f02SAnurag S. Maskey instance_name, sizeof (instance_name)) != DLADM_STATUS_OK)
1976d62bc4baSyz147064 return (DLADM_STATUS_FAILED);
1977a399b765Szf162725
1978d62bc4baSyz147064 return (delete_instance(instance_name));
1979a399b765Szf162725 }
1980