diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/dladm/dladm.c | 17 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdlwlan.c | 368 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/libdlwlan_impl.h | 13 | ||||
-rw-r--r-- | usr/src/lib/libdladm/common/linkprop.c | 519 | ||||
-rw-r--r-- | usr/src/uts/common/io/ath/ath_main.c | 57 | ||||
-rw-r--r-- | usr/src/uts/common/io/iwk/iwk2.c | 53 | ||||
-rw-r--r-- | usr/src/uts/common/io/net80211/net80211_impl.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/io/net80211/net80211_ioctl.c | 1630 | ||||
-rw-r--r-- | usr/src/uts/common/io/wpi/wpi.c | 53 | ||||
-rw-r--r-- | usr/src/uts/common/sys/mac.h | 22 | ||||
-rw-r--r-- | usr/src/uts/common/sys/net80211.h | 6 |
11 files changed, 1856 insertions, 887 deletions
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c index 62c4860594..eacd59fee5 100644 --- a/usr/src/cmd/dladm/dladm.c +++ b/usr/src/cmd/dladm/dladm.c @@ -4480,6 +4480,19 @@ skip: return (""); } +static boolean_t +linkprop_is_supported(datalink_id_t linkid, const char *propname, + show_linkprop_state_t *statep) +{ + dladm_status_t status; + uint_t valcnt = DLADM_MAX_PROP_VALCNT; + + status = dladm_get_linkprop(linkid, DLADM_PROP_VAL_DEFAULT, + propname, statep->ls_propvals, &valcnt); + + return (status != DLADM_STATUS_NOTSUP); +} + static int show_linkprop(datalink_id_t linkid, const char *propname, void *arg) { @@ -4496,6 +4509,9 @@ show_linkprop(datalink_id_t linkid, const char *propname, void *arg) if (!statep->ls_parseable) print_header(&statep->ls_print); } + if (!linkprop_is_supported(linkid, propname, statep)) + return (DLADM_WALK_CONTINUE); + dladm_print_output(&statep->ls_print, statep->ls_parseable, linkprop_callback, (void *)&ls_arg); @@ -5851,7 +5867,6 @@ show_ether_xprop(datalink_id_t linkid, void *arg) (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype), "%s", "peeradv"); (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state), ""); - (void) dladm_get_single_mac_stat(linkid, "lp_cap_autoneg", KSTAT_DATA_UINT32, &autoneg); (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg), diff --git a/usr/src/lib/libdladm/common/libdlwlan.c b/usr/src/lib/libdladm/common/libdlwlan.c index ee46fca3ee..9694c5350b 100644 --- a/usr/src/lib/libdladm/common/libdlwlan.c +++ b/usr/src/lib/libdladm/common/libdlwlan.c @@ -46,18 +46,18 @@ static dladm_status_t wpa_instance_create(datalink_id_t, void *); static dladm_status_t wpa_instance_delete(datalink_id_t); -static dladm_status_t do_get_bsstype(datalink_id_t, wldp_t *); -static dladm_status_t do_get_essid(datalink_id_t, wldp_t *); -static dladm_status_t do_get_bssid(datalink_id_t, wldp_t *); -static dladm_status_t do_get_signal(datalink_id_t, wldp_t *); -static dladm_status_t do_get_encryption(datalink_id_t, wldp_t *); -static dladm_status_t do_get_authmode(datalink_id_t, wldp_t *); -static dladm_status_t do_get_linkstatus(datalink_id_t, wldp_t *); -static dladm_status_t do_get_esslist(datalink_id_t, wldp_t *); -static dladm_status_t do_get_rate(datalink_id_t, wldp_t *); -static dladm_status_t do_get_mode(datalink_id_t, wldp_t *); -static dladm_status_t do_get_capability(datalink_id_t, wldp_t *); -static dladm_status_t do_get_wpamode(datalink_id_t, wldp_t *); +static dladm_status_t do_get_bsstype(datalink_id_t, void *, int); +static dladm_status_t do_get_essid(datalink_id_t, void *, int); +static dladm_status_t do_get_bssid(datalink_id_t, void *, int); +static dladm_status_t do_get_signal(datalink_id_t, void *, int); +static dladm_status_t do_get_encryption(datalink_id_t, void *, int); +static dladm_status_t do_get_authmode(datalink_id_t, void *, int); +static dladm_status_t do_get_linkstatus(datalink_id_t, void *, int); +static dladm_status_t do_get_esslist(datalink_id_t, void *, int); +static dladm_status_t do_get_rate(datalink_id_t, void *, int); +static dladm_status_t do_get_mode(datalink_id_t, void *, int); +static dladm_status_t do_get_capability(datalink_id_t, void *, int); +static dladm_status_t do_get_wpamode(datalink_id_t, void *, int); static dladm_status_t do_set_bsstype(datalink_id_t, dladm_wlan_bsstype_t *); static dladm_status_t do_set_authmode(datalink_id_t, dladm_wlan_auth_t *); @@ -68,10 +68,11 @@ static dladm_status_t do_set_createibss(datalink_id_t, boolean_t *); static dladm_status_t do_set_key(datalink_id_t, dladm_wlan_key_t *, uint_t); static dladm_status_t do_set_channel(datalink_id_t, dladm_wlan_channel_t *); -static dladm_status_t do_scan(datalink_id_t, wldp_t *); -static dladm_status_t do_connect(datalink_id_t, wldp_t *, dladm_wlan_attr_t *, - boolean_t, void *, uint_t, int); -static dladm_status_t do_disconnect(datalink_id_t, wldp_t *); +static dladm_status_t do_scan(datalink_id_t, void *, int); +static dladm_status_t do_connect(datalink_id_t, void *, int, + dladm_wlan_attr_t *, boolean_t, void *, uint_t, + int); +static dladm_status_t do_disconnect(datalink_id_t, void *, int); static boolean_t find_val_by_name(const char *, val_desc_t *, uint_t, uint_t *); static boolean_t find_name_by_val(uint_t, val_desc_t *, uint_t, char **); @@ -116,8 +117,7 @@ static val_desc_t bsstype_vals[] = { { "any", DLADM_WLAN_BSSTYPE_ANY } }; -#define IS_CONNECTED(gbuf) \ - ((*(wl_linkstatus_t *)((gbuf)->wldp_buf) == WL_CONNECTED)) +#define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET) static dladm_status_t dladm_wlan_wlresult2status(wldp_t *gbuf) @@ -237,24 +237,20 @@ dladm_wlan_scan(datalink_id_t linkid, void *arg, int i; uint32_t count; wl_ess_conf_t *wlp; - wldp_t *gbuf = NULL; + wl_ess_list_t *wls = NULL; + char buf[WLDP_BUFSIZE]; + wl_linkstatus_t wl_status; dladm_wlan_attr_t wlattr; dladm_status_t status; - boolean_t connected; if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) goto done; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { - status = DLADM_STATUS_NOMEM; - goto done; - } - - if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) + status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status)); + if (status != DLADM_STATUS_OK) goto done; - connected = IS_CONNECTED(gbuf); - if ((status = do_scan(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_scan(linkid, buf, sizeof (buf))) != DLADM_STATUS_OK) goto done; if (func == NULL) { @@ -262,11 +258,18 @@ dladm_wlan_scan(datalink_id_t linkid, void *arg, goto done; } - if ((status = do_get_esslist(linkid, gbuf)) != DLADM_STATUS_OK) + wls = malloc(WLDP_BUFSIZE); + if (wls == NULL) { + status = DLADM_STATUS_NOMEM; + goto done; + } + + if ((status = do_get_esslist(linkid, wls, WLDP_BUFSIZE)) + != DLADM_STATUS_OK) goto done; - wlp = ((wl_ess_list_t *)gbuf->wldp_buf)->wl_ess_list_ess; - count = ((wl_ess_list_t *)(gbuf->wldp_buf))->wl_ess_list_num; + wlp = wls->wl_ess_list_ess; + count = wls->wl_ess_list_num; for (i = 0; i < count; i++, wlp++) { fill_wlan_attr(wlp, &wlattr); @@ -274,17 +277,18 @@ dladm_wlan_scan(datalink_id_t linkid, void *arg, break; } - if (!connected) { - status = do_get_linkstatus(linkid, gbuf); + if (wl_status != WL_CONNECTED) { + status = do_get_linkstatus(linkid, &wl_status, + sizeof (&wl_status)); if (status != DLADM_STATUS_OK) goto done; - if (IS_CONNECTED(gbuf)) - (void) do_disconnect(linkid, gbuf); + if (wl_status == WL_CONNECTED) + (void) do_disconnect(linkid, buf, sizeof (buf)); } status = DLADM_STATUS_OK; done: - free(gbuf); + free(wls); return (status); } @@ -398,8 +402,9 @@ append: #define IEEE80211_C_WPA 0x01800000 static dladm_status_t -do_connect(datalink_id_t linkid, wldp_t *gbuf, dladm_wlan_attr_t *attrp, - boolean_t create_ibss, void *keys, uint_t key_count, int timeout) +do_connect(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) { dladm_wlan_secmode_t secmode; dladm_wlan_auth_t authmode; @@ -410,6 +415,7 @@ do_connect(datalink_id_t linkid, wldp_t *gbuf, dladm_wlan_attr_t *attrp, dladm_wlan_channel_t channel; hrtime_t start; wl_capability_t *caps; + wl_linkstatus_t wl_status; if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) { channel = attrp->wa_channel; @@ -451,10 +457,10 @@ do_connect(datalink_id_t linkid, wldp_t *gbuf, dladm_wlan_attr_t *attrp, status = DLADM_STATUS_BADARG; goto fail; } - status = do_get_capability(linkid, gbuf); + status = do_get_capability(linkid, buf, bufsize); if (status != DLADM_STATUS_OK) goto fail; - caps = (wl_capability_t *)(gbuf->wldp_buf); + caps = (wl_capability_t *)buf; if ((caps->caps & IEEE80211_C_WPA) == 0) return (DLADM_STATUS_NOTSUP); } @@ -496,11 +502,12 @@ do_connect(datalink_id_t linkid, wldp_t *gbuf, dladm_wlan_attr_t *attrp, start = gethrtime(); for (;;) { - status = do_get_linkstatus(linkid, gbuf); + status = do_get_linkstatus(linkid, &wl_status, + sizeof (wl_status)); if (status != DLADM_STATUS_OK) goto fail; - if (IS_CONNECTED(gbuf)) + if (wl_status == WL_CONNECTED) break; (void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE); @@ -520,23 +527,22 @@ dladm_wlan_connect(datalink_id_t linkid, dladm_wlan_attr_t *attrp, int timeout, void *keys, uint_t key_count, uint_t flags) { int i; - wldp_t *gbuf = NULL; + char buf[WLDP_BUFSIZE]; connect_state_t state = {0, NULL, NULL}; attr_node_t *nodep = NULL; boolean_t create_ibss, set_authmode; dladm_wlan_attr_t **wl_list = NULL; dladm_status_t status; + wl_linkstatus_t wl_status; if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) return (status); - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) - return (DLADM_STATUS_NOMEM); - - if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) + != DLADM_STATUS_OK) goto done; - if (IS_CONNECTED(gbuf)) { + if (wl_status == WL_CONNECTED) { status = DLADM_STATUS_ISCONN; goto done; } @@ -551,8 +557,8 @@ dladm_wlan_connect(datalink_id_t linkid, dladm_wlan_attr_t *attrp, if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0 || (create_ibss && attrp != NULL && (attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0)) { - status = do_connect(linkid, gbuf, attrp, create_ibss, keys, - key_count, timeout); + status = do_connect(linkid, buf, sizeof (buf), attrp, + create_ibss, keys, key_count, timeout); goto done; } @@ -569,8 +575,8 @@ dladm_wlan_connect(datalink_id_t linkid, dladm_wlan_attr_t *attrp, status = DLADM_STATUS_NOTFOUND; goto done; } - status = do_connect(linkid, gbuf, attrp, create_ibss, keys, - key_count, timeout); + status = do_connect(linkid, buf, sizeof (buf), + attrp, create_ibss, keys, key_count, timeout); goto done; } @@ -591,30 +597,29 @@ dladm_wlan_connect(datalink_id_t linkid, dladm_wlan_attr_t *attrp, for (i = 0; i < state.cs_count; i++) { dladm_wlan_attr_t *ap = wl_list[i]; - status = do_connect(linkid, gbuf, ap, create_ibss, keys, - key_count, timeout); + status = do_connect(linkid, buf, sizeof (buf), + ap, create_ibss, keys, key_count, timeout); if (status == DLADM_STATUS_OK) break; if (!set_authmode) { ap->wa_auth = DLADM_WLAN_AUTH_SHARED; ap->wa_valid |= DLADM_WLAN_ATTR_AUTH; - status = do_connect(linkid, gbuf, ap, create_ibss, keys, - key_count, timeout); + status = do_connect(linkid, buf, sizeof (buf), + ap, create_ibss, keys, key_count, timeout); if (status == DLADM_STATUS_OK) break; } } done: if ((status != DLADM_STATUS_OK) && (status != DLADM_STATUS_ISCONN)) - (void) do_disconnect(linkid, gbuf); + (void) do_disconnect(linkid, buf, sizeof (buf)); while (state.cs_list != NULL) { nodep = state.cs_list; state.cs_list = nodep->an_next; free(nodep); } - free(gbuf); free(wl_list); return (status); } @@ -622,53 +627,54 @@ done: dladm_status_t dladm_wlan_disconnect(datalink_id_t linkid) { - wldp_t *gbuf; + char buf[WLDP_BUFSIZE]; dladm_status_t status; + wl_linkstatus_t wl_status; if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) return (status); - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { - status = DLADM_STATUS_NOMEM; - goto done; - } - - if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) + != DLADM_STATUS_OK) goto done; - if (!IS_CONNECTED(gbuf)) { + if (wl_status != WL_CONNECTED) { status = DLADM_STATUS_NOTCONN; goto done; } - if ((status = do_disconnect(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_disconnect(linkid, buf, sizeof (buf))) + != DLADM_STATUS_OK) goto done; - if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) + != DLADM_STATUS_OK) goto done; - if (IS_CONNECTED(gbuf)) { + if (wl_status == WL_CONNECTED) { status = DLADM_STATUS_FAILED; goto done; } status = DLADM_STATUS_OK; done: - free(gbuf); return (status); } dladm_status_t dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) { - wldp_t *gbuf = NULL; wl_rssi_t signal; wl_bss_type_t bsstype; wl_authmode_t authmode; wl_encryption_t encryption; - wl_rates_t *ratesp; + wl_rates_t *ratesp = NULL; dladm_wlan_attr_t *wl_attrp; dladm_status_t status; + char buf[WLDP_BUFSIZE]; + wl_essid_t wls; + wl_phy_conf_t wl_phy_conf; + wl_linkstatus_t wl_status; if (attrp == NULL) return (DLADM_STATUS_BADARG); @@ -676,37 +682,33 @@ dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK) goto done; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { - status = DLADM_STATUS_NOMEM; - goto done; - } - (void) memset(attrp, 0, sizeof (*attrp)); wl_attrp = &attrp->la_wlan_attr; - if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_linkstatus(linkid, &wl_status, sizeof (wl_status))) + != DLADM_STATUS_OK) goto done; attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS; - if (!IS_CONNECTED(gbuf)) + if (wl_status != WL_CONNECTED) attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED; else attrp->la_status = DLADM_WLAN_LINK_CONNECTED; - if ((status = do_get_essid(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_essid(linkid, &wls, sizeof (wls))) + != DLADM_STATUS_OK) goto done; - (void) strlcpy(wl_attrp->wa_essid.we_bytes, - ((wl_essid_t *)(gbuf->wldp_buf))->wl_essid_essid, + (void) strlcpy(wl_attrp->wa_essid.we_bytes, wls.wl_essid_essid, DLADM_WLAN_MAX_ESSID_LEN); wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID; - if ((status = do_get_bssid(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_bssid(linkid, buf, sizeof (buf))) + != DLADM_STATUS_OK) goto done; - (void) memcpy(wl_attrp->wa_bssid.wb_bytes, gbuf->wldp_buf, - DLADM_WLAN_BSSID_LEN); + (void) memcpy(wl_attrp->wa_bssid.wb_bytes, buf, DLADM_WLAN_BSSID_LEN); wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID; @@ -716,10 +718,10 @@ dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) goto done; } - if ((status = do_get_encryption(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_encryption(linkid, &encryption, + sizeof (encryption))) != DLADM_STATUS_OK) goto done; - encryption = *(wl_encryption_t *)(gbuf->wldp_buf); wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE; switch (encryption) { @@ -737,17 +739,23 @@ dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) break; } - if ((status = do_get_signal(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_signal(linkid, &signal, sizeof (signal))) + != DLADM_STATUS_OK) goto done; - signal = *(wl_rssi_t *)(gbuf->wldp_buf); wl_attrp->wa_valid |= DLADM_WLAN_ATTR_STRENGTH; wl_attrp->wa_strength = DLADM_WLAN_SIGNAL2STRENGTH(signal); - if ((status = do_get_rate(linkid, gbuf)) != DLADM_STATUS_OK) + ratesp = malloc(WLDP_BUFSIZE); + if (ratesp == NULL) { + status = DLADM_STATUS_NOMEM; + goto done; + } + + if ((status = do_get_rate(linkid, ratesp, WLDP_BUFSIZE)) + != DLADM_STATUS_OK) goto done; - ratesp = (wl_rates_t *)(gbuf->wldp_buf); if (ratesp->wl_rates_num > 0) { uint_t i, r = 0; @@ -759,10 +767,10 @@ dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED; } - if ((status = do_get_authmode(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_authmode(linkid, &authmode, + sizeof (authmode))) != DLADM_STATUS_OK) goto done; - authmode = *(wl_authmode_t *)(gbuf->wldp_buf); wl_attrp->wa_valid |= DLADM_WLAN_ATTR_AUTH; switch (authmode) { @@ -777,10 +785,10 @@ dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) break; } - if ((status = do_get_bsstype(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_bsstype(linkid, &bsstype, + sizeof (bsstype))) != DLADM_STATUS_OK) goto done; - bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf); wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSTYPE; switch (bsstype) { @@ -798,10 +806,11 @@ dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) break; } - if ((status = do_get_mode(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_mode(linkid, &wl_phy_conf, + sizeof (wl_phy_conf))) != DLADM_STATUS_OK) goto done; - wl_attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)(gbuf->wldp_buf)); + wl_attrp->wa_mode = do_convert_mode(&wl_phy_conf); wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; if (wl_attrp->wa_mode != DLADM_WLAN_MODE_NONE) wl_attrp->wa_valid |= DLADM_WLAN_ATTR_MODE; @@ -810,7 +819,7 @@ dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp) status = DLADM_STATUS_OK; done: - free(gbuf); + free(ratesp); return (status); } @@ -1047,8 +1056,8 @@ dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus) } dladm_status_t -i_dladm_wlan_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id, size_t len, - uint_t cmd, size_t cmdlen) +i_dladm_wlan_legacy_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id, + size_t len, uint_t cmd, size_t cmdlen) { char linkname[MAXPATHLEN]; int fd, rc; @@ -1105,17 +1114,8 @@ i_dladm_wlan_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id, size_t len, return (status); } -dladm_status_t -i_dladm_wlan_get_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t id) -{ - (void) memset(gbuf, 0, MAX_BUF_LEN); - return (i_dladm_wlan_ioctl(linkid, gbuf, id, MAX_BUF_LEN, - WLAN_GET_PARAM, MAX_BUF_LEN)); -} - -dladm_status_t -i_dladm_wlan_set_ioctl(datalink_id_t linkid, uint_t id, void *buf, - uint_t buflen) +static dladm_status_t +do_cmd_ioctl(datalink_id_t linkid, void *buf, int buflen, uint_t cmd) { wldp_t *gbuf; dladm_status_t status = DLADM_STATUS_OK; @@ -1124,99 +1124,97 @@ i_dladm_wlan_set_ioctl(datalink_id_t linkid, uint_t id, void *buf, return (DLADM_STATUS_NOMEM); (void) memset(gbuf, 0, MAX_BUF_LEN); - (void) memcpy(gbuf->wldp_buf, buf, buflen); - buflen += WIFI_BUF_OFFSET; - status = i_dladm_wlan_ioctl(linkid, gbuf, id, buflen, - WLAN_SET_PARAM, buflen); - + status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, cmd, WLDP_BUFSIZE, + WLAN_COMMAND, sizeof (wldp_t)); + (void) memcpy(buf, gbuf->wldp_buf, buflen); free(gbuf); return (status); } static dladm_status_t -do_cmd_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t cmd) +do_scan(datalink_id_t linkid, void *buf, int buflen) { - (void) memset(gbuf, 0, MAX_BUF_LEN); - return (i_dladm_wlan_ioctl(linkid, gbuf, cmd, sizeof (wldp_t), - WLAN_COMMAND, sizeof (wldp_t))); + return (do_cmd_ioctl(linkid, buf, buflen, WL_SCAN)); } static dladm_status_t -do_scan(datalink_id_t linkid, wldp_t *gbuf) +do_disconnect(datalink_id_t linkid, void *buf, int buflen) { - return (do_cmd_ioctl(linkid, gbuf, WL_SCAN)); -} - -static dladm_status_t -do_disconnect(datalink_id_t linkid, wldp_t *gbuf) -{ - if (do_get_wpamode(linkid, gbuf) == 0 && - ((wl_wpa_t *)(gbuf->wldp_buf))->wpa_flag > 0) + if (do_get_wpamode(linkid, buf, buflen) == 0 && + ((wl_wpa_t *)(buf))->wpa_flag > 0) (void) wpa_instance_delete(linkid); - return (do_cmd_ioctl(linkid, gbuf, WL_DISASSOCIATE)); + return (do_cmd_ioctl(linkid, buf, buflen, WL_DISASSOCIATE)); } static dladm_status_t -do_get_esslist(datalink_id_t linkid, wldp_t *gbuf) +do_get_esslist(datalink_id_t linkid, void *buf, int buflen) { - (void) memset(gbuf, 0, MAX_BUF_LEN); - return (i_dladm_wlan_ioctl(linkid, gbuf, WL_ESS_LIST, MAX_BUF_LEN, - WLAN_GET_PARAM, sizeof (wldp_t))); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_ESS_LIST, buflen, + B_FALSE)); } static dladm_status_t -do_get_bssid(datalink_id_t linkid, wldp_t *gbuf) +do_get_bssid(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSSID)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_BSSID, buflen, + B_FALSE)); } static dladm_status_t -do_get_essid(datalink_id_t linkid, wldp_t *gbuf) +do_get_essid(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ESSID)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_ESSID, buflen, + B_FALSE)); } static dladm_status_t -do_get_bsstype(datalink_id_t linkid, wldp_t *gbuf) +do_get_bsstype(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSS_TYPE)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_BSSTYPE, buflen, + B_FALSE)); } static dladm_status_t -do_get_linkstatus(datalink_id_t linkid, wldp_t *gbuf) +do_get_linkstatus(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_LINKSTATUS)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_LINKSTATUS, buflen, + B_FALSE)); } static dladm_status_t -do_get_rate(datalink_id_t linkid, wldp_t *gbuf) +do_get_rate(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_DESIRED_RATES)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_DESIRED_RATES, + buflen, B_FALSE)); } static dladm_status_t -do_get_authmode(datalink_id_t linkid, wldp_t *gbuf) +do_get_authmode(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_AUTH_MODE)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_AUTH_MODE, buflen, + B_FALSE)); } static dladm_status_t -do_get_encryption(datalink_id_t linkid, wldp_t *gbuf) +do_get_encryption(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ENCRYPTION)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_ENCRYPTION, buflen, + B_FALSE)); } static dladm_status_t -do_get_signal(datalink_id_t linkid, wldp_t *gbuf) +do_get_signal(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RSSI)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_RSSI, buflen, + B_FALSE)); } static dladm_status_t -do_get_mode(datalink_id_t linkid, wldp_t *gbuf) +do_get_mode(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_PHY_CONFIG, + buflen, B_FALSE)); } static dladm_status_t @@ -1235,8 +1233,8 @@ do_set_bsstype(datalink_id_t linkid, dladm_wlan_bsstype_t *bsstype) ibsstype = WL_BSS_ANY; break; } - return (i_dladm_wlan_set_ioctl(linkid, WL_BSS_TYPE, &ibsstype, - sizeof (ibsstype))); + return (i_dladm_wlan_param(linkid, &ibsstype, MAC_PROP_WL_BSSTYPE, + sizeof (ibsstype), B_TRUE)); } static dladm_status_t @@ -1254,8 +1252,8 @@ do_set_authmode(datalink_id_t linkid, dladm_wlan_auth_t *auth) default: return (DLADM_STATUS_NOTSUP); } - return (i_dladm_wlan_set_ioctl(linkid, WL_AUTH_MODE, &auth_mode, - sizeof (auth_mode))); + return (i_dladm_wlan_param(linkid, &auth_mode, MAC_PROP_WL_AUTH_MODE, + sizeof (auth_mode), B_TRUE)); } static dladm_status_t @@ -1275,8 +1273,8 @@ do_set_encryption(datalink_id_t linkid, dladm_wlan_secmode_t *secmode) default: return (DLADM_STATUS_NOTSUP); } - return (i_dladm_wlan_set_ioctl(linkid, WL_ENCRYPTION, &encryption, - sizeof (encryption))); + return (i_dladm_wlan_param(linkid, &encryption, MAC_PROP_WL_ENCRYPTION, + sizeof (encryption), B_TRUE)); } static dladm_status_t @@ -1309,8 +1307,8 @@ do_set_key(datalink_id_t linkid, dladm_wlan_key_t *keys, (void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len); } - return (i_dladm_wlan_set_ioctl(linkid, WL_WEP_KEY_TAB, &wepkey_tab, - sizeof (wepkey_tab))); + return (i_dladm_wlan_param(linkid, &wepkey_tab, MAC_PROP_WL_KEY_TAB, + sizeof (wepkey_tab), B_TRUE)); } static dladm_status_t @@ -1327,8 +1325,8 @@ do_set_essid(datalink_id_t linkid, dladm_wlan_essid_t *essid) } else { return (DLADM_STATUS_BADARG); } - return (i_dladm_wlan_set_ioctl(linkid, WL_ESSID, &iessid, - sizeof (iessid))); + return (i_dladm_wlan_param(linkid, &iessid, MAC_PROP_WL_ESSID, + sizeof (iessid), B_TRUE)); } static dladm_status_t @@ -1342,8 +1340,8 @@ do_set_channel(datalink_id_t linkid, dladm_wlan_channel_t *channel) (void) memset(&phy_conf, 0xff, sizeof (phy_conf)); phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel; - return (i_dladm_wlan_set_ioctl(linkid, WL_PHY_CONFIG, &phy_conf, - sizeof (phy_conf))); + return (i_dladm_wlan_param(linkid, &phy_conf, MAC_PROP_WL_PHY_CONFIG, + sizeof (phy_conf), B_TRUE)); } static dladm_status_t @@ -1351,8 +1349,8 @@ do_set_createibss(datalink_id_t linkid, boolean_t *create_ibss) { wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss); - return (i_dladm_wlan_set_ioctl(linkid, WL_CREATE_IBSS, - &cr, sizeof (cr))); + return (i_dladm_wlan_param(linkid, &cr, MAC_PROP_WL_CREATE_IBSS, + sizeof (cr), B_TRUE)); } static void @@ -1364,15 +1362,17 @@ generate_essid(dladm_wlan_essid_t *essid) } static dladm_status_t -do_get_capability(datalink_id_t linkid, wldp_t *gbuf) +do_get_capability(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_CAPABILITY)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_CAPABILITY, + buflen, B_FALSE)); } static dladm_status_t -do_get_wpamode(datalink_id_t linkid, wldp_t *gbuf) +do_get_wpamode(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_WPA)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_WPA, buflen, + B_FALSE)); } dladm_status_t @@ -1380,17 +1380,17 @@ dladm_wlan_wpa_get_sr(datalink_id_t linkid, dladm_wlan_ess_t *sr, uint_t escnt, uint_t *estot) { int i, n; - wldp_t *gbuf; wl_wpa_ess_t *es; dladm_status_t status; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) + es = malloc(WLDP_BUFSIZE); + if (es == NULL) return (DLADM_STATUS_NOMEM); - status = i_dladm_wlan_get_ioctl(linkid, gbuf, WL_SCANRESULTS); + status = i_dladm_wlan_param(linkid, es, MAC_PROP_WL_SCANRESULTS, + WLDP_BUFSIZE, B_FALSE); if (status == DLADM_STATUS_OK) { - es = (wl_wpa_ess_t *)(gbuf->wldp_buf); n = (es->count > escnt) ? escnt : es->count; for (i = 0; i < n; i ++) { (void) memcpy(sr[i].we_bssid.wb_bytes, es->ess[i].bssid, @@ -1406,7 +1406,7 @@ dladm_wlan_wpa_get_sr(datalink_id_t linkid, dladm_wlan_ess_t *sr, *estot = n; } - free(gbuf); + free(es); return (status); } @@ -1428,7 +1428,8 @@ dladm_wlan_wpa_set_ie(datalink_id_t linkid, uint8_t *wpa_ie, uint_t wpa_ie_len) ie->wpa_ie_len = wpa_ie_len; (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len); - status = i_dladm_wlan_set_ioctl(linkid, WL_SETOPTIE, ie, len); + status = i_dladm_wlan_param(linkid, ie, MAC_PROP_WL_SETOPTIE, len, + B_TRUE); free(ie); return (status); @@ -1440,8 +1441,8 @@ dladm_wlan_wpa_set_wpa(datalink_id_t linkid, boolean_t flag) wl_wpa_t wpa; wpa.wpa_flag = flag; - return (i_dladm_wlan_set_ioctl(linkid, WL_WPA, &wpa, - sizeof (wl_wpa_t))); + return (i_dladm_wlan_param(linkid, &wpa, MAC_PROP_WL_WPA, + sizeof (wpa), B_TRUE)); } dladm_status_t @@ -1455,8 +1456,8 @@ dladm_wlan_wpa_del_key(datalink_id_t linkid, uint_t key_idx, (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes, DLADM_WLAN_BSSID_LEN); - return (i_dladm_wlan_set_ioctl(linkid, WL_DELKEY, &wk, - sizeof (wl_del_key_t))); + return (i_dladm_wlan_param(linkid, &wk, MAC_PROP_WL_DELKEY, + sizeof (wk), B_TRUE)); } dladm_status_t @@ -1501,7 +1502,8 @@ dladm_wlan_wpa_set_key(datalink_id_t linkid, dladm_wlan_cipher_t cipher, (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */ (void) memcpy(wk.ik_keydata, key, key_len); - return (i_dladm_wlan_set_ioctl(linkid, WL_KEY, &wk, sizeof (wl_key_t))); + return (i_dladm_wlan_param(linkid, &wk, MAC_PROP_WL_KEY, + sizeof (wk), B_TRUE)); } dladm_status_t @@ -1526,8 +1528,8 @@ dladm_wlan_wpa_set_mlme(datalink_id_t linkid, dladm_wlan_mlme_op_t op, (void) memcpy(mlme.im_macaddr, bssid->wb_bytes, DLADM_WLAN_BSSID_LEN); - return (i_dladm_wlan_set_ioctl(linkid, WL_MLME, &mlme, - sizeof (wl_mlme_t))); + return (i_dladm_wlan_param(linkid, &mlme, MAC_PROP_WL_MLME, + sizeof (mlme), B_TRUE)); } /* diff --git a/usr/src/lib/libdladm/common/libdlwlan_impl.h b/usr/src/lib/libdladm/common/libdlwlan_impl.h index 9611b5319b..256876f030 100644 --- a/usr/src/lib/libdladm/common/libdlwlan_impl.h +++ b/usr/src/lib/libdladm/common/libdlwlan_impl.h @@ -26,10 +26,9 @@ #ifndef _LIBDLWLAN_IMPL_H #define _LIBDLWLAN_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <inet/wifi_ioctl.h> +#include <sys/mac.h> /* * Implementation-private data structures, macros, and constants. @@ -75,12 +74,10 @@ typedef enum { DLADM_WLAN_PM_FAST } dladm_wlan_powermode_t; -extern dladm_status_t i_dladm_wlan_get_ioctl(datalink_id_t, wldp_t *, - uint_t); -extern dladm_status_t i_dladm_wlan_set_ioctl(datalink_id_t, uint_t, - void *, uint_t); -extern dladm_status_t i_dladm_wlan_ioctl(datalink_id_t, wldp_t *, uint_t, - size_t, uint_t, size_t); +extern dladm_status_t i_dladm_wlan_legacy_ioctl(datalink_id_t, wldp_t *, + uint_t, size_t, uint_t, size_t); +extern dladm_status_t i_dladm_wlan_param(datalink_id_t, void *, + mac_prop_id_t, size_t, boolean_t); extern boolean_t i_dladm_wlan_convert_chan(wl_phy_conf_t *, uint32_t *); #ifdef __cplusplus diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c index 2e78907edb..dd43d9331b 100644 --- a/usr/src/lib/libdladm/common/linkprop.c +++ b/usr/src/lib/libdladm/common/linkprop.c @@ -48,6 +48,8 @@ #include <sys/param.h> #include <inttypes.h> #include <sys/ethernet.h> +#include <net/wpa.h> +#include <sys/sysmacros.h> /* * The linkprop get() callback. @@ -98,20 +100,23 @@ typedef dladm_status_t pd_checkf_t(struct prop_desc *pd, uint_t cnt, val_desc_t *propval, datalink_media_t); -typedef struct dladm_public_prop_s { +typedef struct link_attr_s { mac_prop_id_t pp_id; size_t pp_valsize; char *pp_name; - char *pp_desc; -} dladm_public_prop_t; +} link_attr_t; -static dld_ioc_macprop_t *i_dladm_buf_alloc(size_t, datalink_id_t, const char *, - uint_t, dladm_status_t *); +static dld_ioc_macprop_t *i_dladm_buf_alloc_by_name(size_t, datalink_id_t, + const char *, uint_t, dladm_status_t *); +static dld_ioc_macprop_t *i_dladm_buf_alloc_by_id(size_t, datalink_id_t, + mac_prop_id_t, uint_t, + dladm_status_t *); static dladm_status_t i_dladm_set_prop(datalink_id_t, const char *, char **, uint_t, uint_t); static dladm_status_t i_dladm_get_prop(datalink_id_t, const char *, char **, uint_t *, dladm_prop_type_t, uint_t); -static dladm_public_prop_t *dladm_name2prop(const char *); +static link_attr_t *dladm_name2prop(const char *); +static link_attr_t *dladm_id2prop(mac_prop_id_t); static dld_ioc_macprop_t *i_dladm_get_public_prop(datalink_id_t, char *, uint_t, dladm_status_t *); static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod, @@ -128,6 +133,11 @@ static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate, static dladm_status_t i_dladm_speed_get(struct prop_desc *, datalink_id_t, char **, uint_t *, uint_t); +static dladm_status_t i_dladm_wlan_get_legacy_ioctl(datalink_id_t, void *, + uint_t, uint_t); +static dladm_status_t i_dladm_wlan_set_legacy_ioctl(datalink_id_t, void *, + uint_t, uint_t); +static dladm_status_t i_dladm_macprop(void *, boolean_t); typedef struct prop_desc { /* @@ -193,70 +203,104 @@ typedef struct prop_desc { #define MAC_PROP_BUFSIZE(v) sizeof (dld_ioc_macprop_t) + (v) - 1 +/* + * Supported link properties enumerated in the prop_table[] array are + * computed using the callback functions in that array. To compute the + * property value, multiple distinct system calls may be needed (e.g., + * for wifi speed, we need to issue system calls to get desired/supported + * rates). The link_attr[] table enumerates the interfaces to the kernel, + * and the type/size of the data passed in the user-kernel interface. + */ +static link_attr_t link_attr[] = { + { MAC_PROP_DUPLEX, sizeof (link_duplex_t), "duplex"}, + + { MAC_PROP_SPEED, sizeof (uint64_t), "speed"}, + + { MAC_PROP_STATUS, sizeof (link_state_t), "state"}, + + { MAC_PROP_AUTONEG, sizeof (uint8_t), "adv_autoneg_cap"}, + + { MAC_PROP_MTU, sizeof (uint32_t), "mtu"}, + + { MAC_PROP_FLOWCTRL, sizeof (link_flowctrl_t), "flowctrl"}, + + { MAC_PROP_ZONE, sizeof (dld_ioc_zid_t), "zone"}, + + { MAC_PROP_AUTOPUSH, sizeof (struct dlautopush), "autopush"}, + + { MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), "adv_1000fdx_cap"}, + + { MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t), "en_1000fdx_cap"}, + + { MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), "adv_1000hdx_cap"}, + + { MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t), "en_1000hdx_cap"}, + + { MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t), "adv_100fdx_cap"}, + + { MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t), "en_100fdx_cap"}, + + { MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t), "adv_100hdx_cap"}, + + { MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t), "en_100hdx_cap"}, + + { MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t), "adv_10fdx_cap"}, + + { MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t), "en_10fdx_cap"}, + + { MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t), "adv_10hdx_cap"}, + + { MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t), "en_10hdx_cap"}, -static dladm_public_prop_t dladm_prop[] = { - { MAC_PROP_DUPLEX, sizeof (link_duplex_t), - "duplex", "link duplex mode" }, + { MAC_PROP_WL_ESSID, sizeof (wl_linkstatus_t), "essid"}, - { MAC_PROP_SPEED, sizeof (uint64_t), - "speed", "link speed (bps)" }, + { MAC_PROP_WL_BSSID, sizeof (wl_bssid_t), "bssid"}, - { MAC_PROP_STATUS, sizeof (link_state_t), - "state", "link up/down" }, + { MAC_PROP_WL_BSSTYPE, sizeof (wl_bss_type_t), "bsstype"}, - { MAC_PROP_AUTONEG, sizeof (uint8_t), - "adv_autoneg_cap", "Advertised auto-negotiation" }, + { MAC_PROP_WL_LINKSTATUS, sizeof (wl_linkstatus_t), "wl_linkstatus"}, - { MAC_PROP_MTU, sizeof (uint32_t), - "mtu", "current link mtu" }, + /* wl_rates_t has variable length */ + { MAC_PROP_WL_DESIRED_RATES, sizeof (wl_rates_t), "desired_rates"}, - { MAC_PROP_FLOWCTRL, sizeof (link_flowctrl_t), - "flowctrl", "flowcontrol" }, + /* wl_rates_t has variable length */ + { MAC_PROP_WL_SUPPORTED_RATES, sizeof (wl_rates_t), "supported_rates"}, - { MAC_PROP_ZONE, sizeof (dld_ioc_zid_t), - "zone", "non-global zones" }, + { MAC_PROP_WL_AUTH_MODE, sizeof (wl_authmode_t), "authmode"}, - { MAC_PROP_AUTOPUSH, sizeof (struct dlautopush), - "autopush", "autopush modules" }, + { MAC_PROP_WL_ENCRYPTION, sizeof (wl_encryption_t), "encryption"}, - { MAC_PROP_ADV_1000FDX_CAP, sizeof (uint8_t), - "adv_1000fdx_cap", "Adv 1000 Mbps fdx" }, + { MAC_PROP_WL_RSSI, sizeof (wl_rssi_t), "signal"}, - { MAC_PROP_EN_1000FDX_CAP, sizeof (uint8_t), - "en_1000fdx_cap", "Enable 1000 Mbps fdx" }, + { MAC_PROP_WL_PHY_CONFIG, sizeof (wl_phy_conf_t), "phy_conf"}, - { MAC_PROP_ADV_1000HDX_CAP, sizeof (uint8_t), - "adv_1000hdx_cap", "Adv 1000 Mbps hdx" }, + { MAC_PROP_WL_CAPABILITY, sizeof (wl_capability_t), "capability"}, - { MAC_PROP_EN_1000HDX_CAP, sizeof (uint8_t), - "en_1000hdx_cap", "Enable 1000 Mbps hdx" }, + { MAC_PROP_WL_WPA, sizeof (wl_wpa_t), "wpa"}, - { MAC_PROP_ADV_100FDX_CAP, sizeof (uint8_t), - "adv_100fdx_cap", "Adv 100 Mbps fdx" }, + /* wl_wpa_ess_t has variable length */ + { MAC_PROP_WL_SCANRESULTS, sizeof (wl_wpa_ess_t), "scan_results"}, - { MAC_PROP_EN_100FDX_CAP, sizeof (uint8_t), - "en_100fdx_cap", "Enable 100 Mbps fdx" }, + { MAC_PROP_WL_POWER_MODE, sizeof (wl_ps_mode_t), "powermode"}, - { MAC_PROP_ADV_100HDX_CAP, sizeof (uint8_t), - "adv_100hdx_cap", "Adv 100 Mbps hdx" }, + { MAC_PROP_WL_RADIO, sizeof (dladm_wlan_radio_t), "wl_radio"}, - { MAC_PROP_EN_100HDX_CAP, sizeof (uint8_t), - "en_100hdx_cap", "Enable 100 Mbps hdx" }, + { MAC_PROP_WL_ESS_LIST, sizeof (wl_ess_list_t), "wl_ess_list"}, - { MAC_PROP_ADV_10FDX_CAP, sizeof (uint8_t), - "adv_10fdx_cap", "Adv 10 Mbps fdx" }, + { MAC_PROP_WL_KEY_TAB, sizeof (wl_wep_key_tab_t), "wl_wep_key"}, - { MAC_PROP_EN_10FDX_CAP, sizeof (uint8_t), - "en_10fdx_cap", "Enable 10 Mbps fdx" }, + { MAC_PROP_WL_CREATE_IBSS, sizeof (wl_create_ibss_t), "createibss"}, - { MAC_PROP_ADV_10HDX_CAP, sizeof (uint8_t), - "adv_10hdx_cap", "Adv 10 Mbps hdx" }, + /* wl_wpa_ie_t has variable length */ + { MAC_PROP_WL_SETOPTIE, sizeof (wl_wpa_ie_t), "set_ie"}, - { MAC_PROP_EN_10HDX_CAP, sizeof (uint8_t), - "en_10hdx_cap", "Enable 10 Mbps hdx" }, + { MAC_PROP_WL_DELKEY, sizeof (wl_del_key_t), "wpa_del_key"}, - { MAC_PROP_PRIVATE, 0, - "driver-private", "" } + { MAC_PROP_WL_KEY, sizeof (wl_key_t), "wl_key"}, + + { MAC_PROP_WL_MLME, sizeof (wl_mlme_t), "mlme"}, + + { MAC_PROP_PRIVATE, 0, "driver-private"} }; static val_desc_t link_duplex_vals[] = { @@ -414,6 +458,12 @@ static prop_desc_t prop_table[] = { #define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t)) +/* + * when retrieving private properties, we pass down a buffer with + * DLADM_PROP_BUF_CHUNK of space for the driver to return the property value. + */ +#define DLADM_PROP_BUF_CHUNK 1024 + static dladm_status_t i_dladm_set_linkprop_db(datalink_id_t, const char *, char **, uint_t); static dladm_status_t i_dladm_get_linkprop_db(datalink_id_t, const char *, @@ -1244,6 +1294,8 @@ do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, return (DLADM_STATUS_OK); } +#define WLDP_BUFSIZE (MAX_BUF_LEN - WIFI_BUF_OFFSET) + /* ARGSUSED */ static dladm_status_t do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, @@ -1251,19 +1303,16 @@ do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, { wl_rates_t *wrp; uint_t i; - wldp_t *gbuf = NULL; dladm_status_t status = DLADM_STATUS_OK; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) { - status = DLADM_STATUS_NOMEM; - goto done; - } + wrp = malloc(WLDP_BUFSIZE); + if (wrp == NULL) + return (DLADM_STATUS_NOMEM); - status = i_dladm_wlan_get_ioctl(linkid, gbuf, id); + status = i_dladm_wlan_param(linkid, wrp, id, WLDP_BUFSIZE, B_FALSE); if (status != DLADM_STATUS_OK) goto done; - wrp = (wl_rates_t *)gbuf->wldp_buf; if (wrp->wl_rates_num > *val_cnt) { status = DLADM_STATUS_TOOSMALL; goto done; @@ -1283,7 +1332,7 @@ do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid, *val_cnt = wrp->wl_rates_num; done: - free(gbuf); + free(wrp); return (status); } @@ -1296,7 +1345,7 @@ do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid, val_cnt, flags)); return (do_get_rate_common(pd, linkid, prop_val, val_cnt, - WL_DESIRED_RATES)); + MAC_PROP_WL_DESIRED_RATES)); } /* ARGSUSED */ @@ -1314,7 +1363,7 @@ do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid, case DL_WIFI: return (do_get_rate_common(pd, linkid, prop_val, val_cnt, - WL_SUPPORTED_RATES)); + MAC_PROP_WL_SUPPORTED_RATES)); default: return (DLADM_STATUS_BADARG); } @@ -1325,26 +1374,24 @@ do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates) { int i; uint_t len; - wldp_t *gbuf; wl_rates_t *wrp; dladm_status_t status = DLADM_STATUS_OK; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) + wrp = malloc(WLDP_BUFSIZE); + if (wrp == NULL) return (DLADM_STATUS_NOMEM); - (void) memset(gbuf, 0, MAX_BUF_LEN); - - wrp = (wl_rates_t *)gbuf->wldp_buf; + bzero(wrp, WLDP_BUFSIZE); for (i = 0; i < rates->wr_cnt; i++) wrp->wl_rates_rates[i] = rates->wr_rates[i]; wrp->wl_rates_num = rates->wr_cnt; len = offsetof(wl_rates_t, wl_rates_rates) + (rates->wr_cnt * sizeof (char)) + WIFI_BUF_OFFSET; - status = i_dladm_wlan_ioctl(linkid, gbuf, WL_DESIRED_RATES, len, - WLAN_SET_PARAM, len); + status = i_dladm_wlan_param(linkid, wrp, MAC_PROP_WL_DESIRED_RATES, + len, B_TRUE); - free(gbuf); + free(wrp); return (status); } @@ -1420,9 +1467,10 @@ done: } static dladm_status_t -do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf) +do_get_phyconf(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_PHY_CONFIG, + buflen, B_FALSE)); } /* ARGSUSED */ @@ -1431,17 +1479,16 @@ do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) { uint32_t channel; - wldp_t *gbuf; + char buf[WLDP_BUFSIZE]; dladm_status_t status = DLADM_STATUS_OK; + wl_phy_conf_t wl_phy_conf; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) - return (DLADM_STATUS_NOMEM); - - if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_phyconf(linkid, buf, sizeof (buf))) + != DLADM_STATUS_OK) goto done; - if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, - &channel)) { + (void) memcpy(&wl_phy_conf, buf, sizeof (wl_phy_conf)); + if (!i_dladm_wlan_convert_chan(&wl_phy_conf, &channel)) { status = DLADM_STATUS_NOTFOUND; goto done; } @@ -1450,14 +1497,14 @@ do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid, *val_cnt = 1; done: - free(gbuf); return (status); } static dladm_status_t -do_get_powermode(datalink_id_t linkid, wldp_t *gbuf) +do_get_powermode(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_POWER_MODE, + buflen, B_FALSE)); } /* ARGSUSED */ @@ -1465,19 +1512,17 @@ static dladm_status_t do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid, char **prop_val, uint_t *val_cnt, datalink_media_t media, uint_t flags) { - wl_ps_mode_t *mode; + wl_ps_mode_t mode; const char *s; - wldp_t *gbuf; + char buf[WLDP_BUFSIZE]; dladm_status_t status = DLADM_STATUS_OK; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) - return (DLADM_STATUS_NOMEM); - - if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_powermode(linkid, buf, sizeof (buf))) + != DLADM_STATUS_OK) goto done; - mode = (wl_ps_mode_t *)(gbuf->wldp_buf); - switch (mode->wl_ps_mode) { + (void) memcpy(&mode, buf, sizeof (mode)); + switch (mode.wl_ps_mode) { case WL_PM_AM: s = "off"; break; @@ -1495,7 +1540,6 @@ do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid, *val_cnt = 1; done: - free(gbuf); return (status); } @@ -1519,8 +1563,8 @@ do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm) default: return (DLADM_STATUS_NOTSUP); } - return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode, - sizeof (ps_mode))); + return (i_dladm_wlan_param(linkid, &ps_mode, MAC_PROP_WL_POWER_MODE, + sizeof (ps_mode), B_TRUE)); } /* ARGSUSED */ @@ -1540,9 +1584,10 @@ do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid, } static dladm_status_t -do_get_radio(datalink_id_t linkid, wldp_t *gbuf) +do_get_radio(datalink_id_t linkid, void *buf, int buflen) { - return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO)); + return (i_dladm_wlan_param(linkid, buf, MAC_PROP_WL_RADIO, buflen, + B_FALSE)); } /* ARGSUSED */ @@ -1552,16 +1597,14 @@ do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid, { wl_radio_t radio; const char *s; - wldp_t *gbuf; + char buf[WLDP_BUFSIZE]; dladm_status_t status = DLADM_STATUS_OK; - if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) - return (DLADM_STATUS_NOMEM); - - if ((status = do_get_radio(linkid, gbuf)) != DLADM_STATUS_OK) + if ((status = do_get_radio(linkid, buf, sizeof (buf))) + != DLADM_STATUS_OK) goto done; - radio = *(wl_radio_t *)(gbuf->wldp_buf); + (void) memcpy(&radio, buf, sizeof (radio)); switch (radio) { case B_TRUE: s = "on"; @@ -1577,7 +1620,6 @@ do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid, *val_cnt = 1; done: - free(gbuf); return (status); } @@ -1596,7 +1638,8 @@ do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio) default: return (DLADM_STATUS_NOTSUP); } - return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r))); + return (i_dladm_wlan_param(linkid, &r, MAC_PROP_WL_RADIO, + sizeof (r), B_TRUE)); } /* ARGSUSED */ @@ -1688,32 +1731,39 @@ done: return (status); } -static dladm_public_prop_t * +static link_attr_t * dladm_name2prop(const char *prop_name) { - dladm_public_prop_t *p; + link_attr_t *p; - for (p = dladm_prop; p->pp_id != MAC_PROP_PRIVATE; p++) { + for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) { if (strcmp(p->pp_name, prop_name) == 0) break; } return (p); } +static link_attr_t * +dladm_id2prop(mac_prop_id_t propid) +{ + link_attr_t *p; + + for (p = link_attr; p->pp_id != MAC_PROP_PRIVATE; p++) { + if (p->pp_id == propid) + break; + } + return (p); +} static dld_ioc_macprop_t * -i_dladm_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name, - uint_t flags, dladm_status_t *status) +i_dladm_buf_alloc_impl(size_t valsize, datalink_id_t linkid, + const char *prop_name, mac_prop_id_t propid, uint_t flags, + dladm_status_t *status) { int dsize; dld_ioc_macprop_t *dip; - dladm_public_prop_t *p; *status = DLADM_STATUS_OK; - p = dladm_name2prop(prop_name); - if (p->pp_id != MAC_PROP_PRIVATE) - valsize = p->pp_valsize; - dsize = MAC_PROP_BUFSIZE(valsize); dip = malloc(dsize); if (dip == NULL) { @@ -1725,25 +1775,48 @@ i_dladm_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name, (void) strlcpy(dip->pr_name, prop_name, sizeof (dip->pr_name)); dip->pr_version = MAC_PROP_VERSION; dip->pr_linkid = linkid; - dip->pr_num = p->pp_id; + dip->pr_num = propid; dip->pr_flags = flags; return (dip); } +static dld_ioc_macprop_t * +i_dladm_buf_alloc_by_name(size_t valsize, datalink_id_t linkid, + const char *prop_name, uint_t flags, dladm_status_t *status) +{ + link_attr_t *p; + + p = dladm_name2prop(prop_name); + valsize = MAX(p->pp_valsize, valsize); + return (i_dladm_buf_alloc_impl(valsize, linkid, prop_name, p->pp_id, + flags, status)); +} + +static dld_ioc_macprop_t * +i_dladm_buf_alloc_by_id(size_t valsize, datalink_id_t linkid, + mac_prop_id_t propid, uint_t flags, dladm_status_t *status) +{ + link_attr_t *p; + + p = dladm_id2prop(propid); + valsize = MAX(p->pp_valsize, valsize); + return (i_dladm_buf_alloc_impl(valsize, linkid, p->pp_name, propid, + flags, status)); +} + /* ARGSUSED */ static dladm_status_t i_dladm_set_public_prop(prop_desc_t *pd, datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags, datalink_media_t media) { dld_ioc_macprop_t *dip; - int fd; dladm_status_t status = DLADM_STATUS_OK; uint8_t u8; uint16_t u16; uint32_t u32; void *val; - dip = i_dladm_buf_alloc(0, linkid, pd->pd_name, 0, &status); + dip = i_dladm_buf_alloc_by_name(0, linkid, pd->pd_name, 0, &status); if (dip == NULL) return (status); @@ -1778,16 +1851,27 @@ i_dladm_set_public_prop(prop_desc_t *pd, datalink_id_t linkid, else dip->pr_valsize = 0; + status = i_dladm_macprop(dip, B_TRUE); + +done: + free(dip); + return (status); +} + +dladm_status_t +i_dladm_macprop(void *dip, boolean_t set) +{ + int fd; + dladm_status_t status = DLADM_STATUS_OK; + if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { status = dladm_errno2status(errno); - goto done; + return (status); } - if (ioctl(fd, DLDIOC_SETMACPROP, dip) < 0) + if (ioctl(fd, (set ? DLDIOC_SETMACPROP : DLDIOC_GETMACPROP), dip)) status = dladm_errno2status(errno); (void) close(fd); -done: - free(dip); return (status); } @@ -1795,24 +1879,13 @@ static dld_ioc_macprop_t * i_dladm_get_public_prop(datalink_id_t linkid, char *prop_name, uint_t flags, dladm_status_t *status) { - int fd; dld_ioc_macprop_t *dip = NULL; - *status = DLADM_STATUS_OK; - - dip = i_dladm_buf_alloc(0, linkid, prop_name, flags, status); + dip = i_dladm_buf_alloc_by_name(0, linkid, prop_name, flags, status); if (dip == NULL) return (NULL); - if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { - *status = dladm_errno2status(errno); - goto done; - } - if (ioctl(fd, DLDIOC_GETMACPROP, dip) < 0) - *status = dladm_errno2status(errno); - - (void) close(fd); -done: + *status = i_dladm_macprop(dip, B_FALSE); if (*status != DLADM_STATUS_OK) { free(dip); return (NULL); @@ -1999,11 +2072,11 @@ static dladm_status_t i_dladm_set_prop(datalink_id_t linkid, const char *prop_name, char **prop_val, uint_t val_cnt, uint_t flags) { - int fd, i, slen; + int i, slen; int bufsize = 0; dld_ioc_macprop_t *dip = NULL; uchar_t *dp; - dladm_public_prop_t *p; + link_attr_t *p; dladm_status_t status = DLADM_STATUS_OK; if ((prop_name == NULL && prop_val != NULL) || @@ -2025,25 +2098,19 @@ i_dladm_set_prop(datalink_id_t linkid, const char *prop_name, /* * getting default value. so use more buffer space. */ - bufsize += 1024; + bufsize += DLADM_PROP_BUF_CHUNK; } - dip = i_dladm_buf_alloc(bufsize + 1, linkid, prop_name, + dip = i_dladm_buf_alloc_by_name(bufsize + 1, linkid, prop_name, (prop_val != NULL ? 0 : MAC_PROP_DEFAULT), &status); if (dip == NULL) return (status); dp = (uchar_t *)dip->pr_val; slen = 0; - if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { - status = dladm_errno2status(errno); - goto done; - } + if (prop_val == NULL) { - if (ioctl(fd, DLDIOC_GETMACPROP, dip) < 0) { - status = dladm_errno2status(errno); - goto done; - } + status = i_dladm_macprop(dip, B_FALSE); } else { for (i = 0; i < val_cnt; i++) { int plen = 0; @@ -2058,13 +2125,9 @@ i_dladm_set_prop(datalink_id_t linkid, const char *prop_name, dp[slen++] = ','; dp += (plen + 1); } + status = i_dladm_macprop(dip, B_TRUE); } - if (ioctl(fd, DLDIOC_SETMACPROP, dip) < 0) - status = dladm_errno2status(errno); -done: - if (fd > 0) - (void) close(fd); free(dip); return (status); } @@ -2073,10 +2136,9 @@ static dladm_status_t i_dladm_get_prop(datalink_id_t linkid, const char *prop_name, char **prop_val, uint_t *val_cnt, dladm_prop_type_t type, uint_t dld_flags) { - int fd; - dladm_status_t status = DLADM_STATUS_OK; + dladm_status_t status = DLADM_STATUS_OK; dld_ioc_macprop_t *dip = NULL; - dladm_public_prop_t *p; + link_attr_t *p; char tmp = '\0'; if ((prop_name == NULL && prop_val != NULL) || @@ -2096,23 +2158,15 @@ i_dladm_get_prop(datalink_id_t linkid, const char *prop_name, /* * private properties: all parsing is done in the kernel. */ - dip = i_dladm_buf_alloc(1024, linkid, prop_name, dld_flags, &status); + dip = i_dladm_buf_alloc_by_name(DLADM_PROP_BUF_CHUNK, linkid, prop_name, + dld_flags, &status); if (dip == NULL) return (status); - if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) { - free(dip); - return (DLADM_STATUS_BADARG); - } - - if (ioctl(fd, DLDIOC_GETMACPROP, dip) < 0) { - status = dladm_errno2status(errno); - } else { + if ((status = i_dladm_macprop(dip, B_FALSE)) == DLADM_STATUS_OK) { (void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX); *val_cnt = 1; } - - (void) close(fd); free(dip); return (status); } @@ -2162,3 +2216,146 @@ i_dladm_getset_defval(prop_desc_t *pdp, datalink_id_t linkid, free(buf); return (status); } + +int +macprop_to_wifi(mac_prop_id_t wl_prop) +{ + switch (wl_prop) { + case MAC_PROP_WL_ESSID: + return (WL_ESSID); + case MAC_PROP_WL_BSSID: + return (WL_BSSID); + case MAC_PROP_WL_BSSTYPE: + return (WL_BSS_TYPE); + case MAC_PROP_WL_LINKSTATUS: + return (WL_LINKSTATUS); + case MAC_PROP_WL_DESIRED_RATES: + return (WL_DESIRED_RATES); + case MAC_PROP_WL_SUPPORTED_RATES: + return (WL_SUPPORTED_RATES); + case MAC_PROP_WL_AUTH_MODE: + return (WL_AUTH_MODE); + case MAC_PROP_WL_ENCRYPTION: + return (WL_ENCRYPTION); + case MAC_PROP_WL_RSSI: + return (WL_RSSI); + case MAC_PROP_WL_PHY_CONFIG: + return (WL_PHY_CONFIG); + case MAC_PROP_WL_CAPABILITY: + return (WL_CAPABILITY); + case MAC_PROP_WL_WPA: + return (WL_WPA); + case MAC_PROP_WL_SCANRESULTS: + return (WL_SCANRESULTS); + case MAC_PROP_WL_POWER_MODE: + return (WL_POWER_MODE); + case MAC_PROP_WL_RADIO: + return (WL_RADIO); + case MAC_PROP_WL_ESS_LIST: + return (WL_ESS_LIST); + case MAC_PROP_WL_KEY_TAB: + return (WL_WEP_KEY_TAB); + case MAC_PROP_WL_CREATE_IBSS: + return (WL_CREATE_IBSS); + case MAC_PROP_WL_SETOPTIE: + return (WL_SETOPTIE); + case MAC_PROP_WL_DELKEY: + return (WL_DELKEY); + case MAC_PROP_WL_KEY: + return (WL_KEY); + case MAC_PROP_WL_MLME: + return (WL_MLME); + default: + return (-1); + } +} + +dladm_status_t +i_dladm_wlan_param(datalink_id_t linkid, void *buf, mac_prop_id_t cmd, + size_t len, boolean_t set) +{ + uint32_t flags; + dladm_status_t status; + uint32_t media; + dld_ioc_macprop_t *dip; + void *dp; + + if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media, + NULL, 0)) != DLADM_STATUS_OK) { + return (status); + } + + if (media != DL_WIFI) + return (DLADM_STATUS_BADARG); + + if (!(flags & DLADM_OPT_ACTIVE)) + return (DLADM_STATUS_TEMPONLY); + + if (len == (MAX_BUF_LEN - WIFI_BUF_OFFSET)) + len = MAX_BUF_LEN - sizeof (dld_ioc_macprop_t) - 1; + + dip = i_dladm_buf_alloc_by_id(len, linkid, cmd, 0, &status); + if (dip == NULL) + return (DLADM_STATUS_NOMEM); + + dp = (uchar_t *)dip->pr_val; + if (set) + (void) memcpy(dp, buf, len); + + status = i_dladm_macprop(dip, set); + if (status == DLADM_STATUS_NOTSUP) { + if (set) { + status = i_dladm_wlan_set_legacy_ioctl(linkid, + buf, len, macprop_to_wifi(cmd)); + } else { + status = i_dladm_wlan_get_legacy_ioctl(linkid, + buf, len, macprop_to_wifi(cmd)); + } + } else if (status == DLADM_STATUS_OK) { + if (!set) + (void) memcpy(buf, dp, len); + } + + free(dip); + return (status); +} + +static dladm_status_t +i_dladm_wlan_get_legacy_ioctl(datalink_id_t linkid, void *buf, uint_t buflen, + uint_t id) +{ + wldp_t *gbuf; + dladm_status_t status; + + if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) + return (DLADM_STATUS_NOMEM); + + (void) memset(gbuf, 0, MAX_BUF_LEN); + status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, id, MAX_BUF_LEN, + WLAN_GET_PARAM, sizeof (wldp_t)); + if (status == DLADM_STATUS_OK) + (void) memcpy(buf, gbuf->wldp_buf, buflen); + + free(gbuf); + return (status); +} + +static dladm_status_t +i_dladm_wlan_set_legacy_ioctl(datalink_id_t linkid, void *buf, uint_t buflen, + uint_t id) +{ + wldp_t *gbuf; + dladm_status_t status = DLADM_STATUS_OK; + + if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) + return (DLADM_STATUS_NOMEM); + + (void) memset(gbuf, 0, MAX_BUF_LEN); + (void) memcpy(gbuf->wldp_buf, buf, buflen); + buflen += WIFI_BUF_OFFSET; + status = i_dladm_wlan_legacy_ioctl(linkid, gbuf, id, buflen, + WLAN_SET_PARAM, buflen); + + free(gbuf); + return (status); +} diff --git a/usr/src/uts/common/io/ath/ath_main.c b/usr/src/uts/common/io/ath/ath_main.c index e9a26e3c1d..034c719c5d 100644 --- a/usr/src/uts/common/io/ath/ath_main.c +++ b/usr/src/uts/common/io/ath/ath_main.c @@ -36,6 +36,7 @@ * */ + /* * Driver for the Atheros Wireless LAN controller. * @@ -218,8 +219,13 @@ static int ath_m_multicst(void *, boolean_t, const uint8_t *); static int ath_m_unicst(void *, const uint8_t *); static mblk_t *ath_m_tx(void *, mblk_t *); static void ath_m_ioctl(void *, queue_t *, mblk_t *); +static int ath_m_setprop(void *, const char *, mac_prop_id_t, + uint_t, const void *); +static int ath_m_getprop(void *, const char *, mac_prop_id_t, + uint_t, uint_t, void *); + static mac_callbacks_t ath_m_callbacks = { - MC_IOCTL, + MC_IOCTL | MC_SETPROP | MC_GETPROP, ath_m_stat, ath_m_start, ath_m_stop, @@ -229,7 +235,11 @@ static mac_callbacks_t ath_m_callbacks = { ath_m_tx, NULL, /* mc_resources; */ ath_m_ioctl, - NULL /* mc_getcapab */ + NULL, /* mc_getcapab */ + NULL, + NULL, + ath_m_setprop, + ath_m_getprop }; /* @@ -1738,6 +1748,49 @@ ath_m_multicst(void *arg, boolean_t add, const uint8_t *mca) return (0); } +/* + * callback functions for /get/set properties + */ +static int +ath_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, + uint_t wldp_length, const void *wldp_buf) +{ + ath_t *asc = arg; + int err; + + err = ieee80211_setprop(&asc->asc_isc, pr_name, wldp_pr_num, + wldp_length, wldp_buf); + + ATH_LOCK(asc); + + if (err == ENETRESET) { + if (ATH_IS_RUNNING(asc)) { + ATH_UNLOCK(asc); + (void) ath_m_start(asc); + (void) ieee80211_new_state(&asc->asc_isc, + IEEE80211_S_SCAN, -1); + ATH_LOCK(asc); + } + err = 0; + } + + ATH_UNLOCK(asc); + + return (err); +} +static int +ath_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, + uint_t pr_flags, uint_t wldp_length, void *wldp_buf) +{ + ath_t *asc = arg; + int err = 0; + + err = ieee80211_getprop(&asc->asc_isc, pr_name, wldp_pr_num, + pr_flags, wldp_length, wldp_buf); + + return (err); +} + static void ath_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) { diff --git a/usr/src/uts/common/io/iwk/iwk2.c b/usr/src/uts/common/io/iwk/iwk2.c index 0ccb805a4a..fe129e5d15 100644 --- a/usr/src/uts/common/io/iwk/iwk2.c +++ b/usr/src/uts/common/io/iwk/iwk2.c @@ -326,7 +326,11 @@ static int iwk_m_multicst(void *arg, boolean_t add, const uint8_t *m); static int iwk_m_promisc(void *arg, boolean_t on); static mblk_t *iwk_m_tx(void *arg, mblk_t *mp); static void iwk_m_ioctl(void *arg, queue_t *wq, mblk_t *mp); - +static int iwk_m_setprop(void *arg, const char *pr_name, + mac_prop_id_t wldp_pr_name, uint_t wldp_length, const void *wldp_buf); +static int iwk_m_getprop(void *arg, const char *pr_name, + mac_prop_id_t wldp_pr_name, uint_t pr_flags, uint_t wldp_length, + void *wldp_buf); static void iwk_destroy_locks(iwk_sc_t *sc); static int iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type); static void iwk_thread(iwk_sc_t *sc); @@ -410,7 +414,7 @@ _info(struct modinfo *mip) * Mac Call Back entries */ mac_callbacks_t iwk_m_callbacks = { - MC_IOCTL, + MC_IOCTL | MC_SETPROP | MC_GETPROP, iwk_m_stat, iwk_m_start, iwk_m_stop, @@ -419,7 +423,12 @@ mac_callbacks_t iwk_m_callbacks = { iwk_m_unicst, iwk_m_tx, NULL, - iwk_m_ioctl + iwk_m_ioctl, + NULL, + NULL, + NULL, + iwk_m_setprop, + iwk_m_getprop }; #ifdef DEBUG @@ -2651,6 +2660,44 @@ iwk_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) } } +/* + * callback functions for set/get properties + */ +static int +iwk_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, + uint_t pr_flags, uint_t wldp_length, void *wldp_buf) +{ + int err = 0; + iwk_sc_t *sc = (iwk_sc_t *)arg; + + err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_num, + pr_flags, wldp_length, wldp_buf); + + return (err); +} +static int +iwk_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num, + uint_t wldp_length, const void *wldp_buf) +{ + int err; + iwk_sc_t *sc = (iwk_sc_t *)arg; + ieee80211com_t *ic = &sc->sc_ic; + + err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length, + wldp_buf); + + if (err == ENETRESET) { + if (ic->ic_des_esslen) { + (void) ieee80211_new_state(ic, + IEEE80211_S_SCAN, -1); + } + + err = 0; + } + + return (err); +} + /*ARGSUSED*/ static int iwk_m_stat(void *arg, uint_t stat, uint64_t *val) diff --git a/usr/src/uts/common/io/net80211/net80211_impl.h b/usr/src/uts/common/io/net80211/net80211_impl.h index 823f0e2365..85e5fe37d4 100644 --- a/usr/src/uts/common/io/net80211/net80211_impl.h +++ b/usr/src/uts/common/io/net80211/net80211_impl.h @@ -1,5 +1,5 @@ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,8 +35,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #ifndef _SYS_NET80211_IMPL_H #define _SYS_NET80211_IMPL_H @@ -186,6 +184,7 @@ extern "C" { #define IEEE80211_MAXRSSI 127 /* Debug Flags */ +#define IEEE80211_MSG_BRUSSELS 0x80000000 /* BRUSSELS */ #define IEEE80211_MSG_DEBUG 0x40000000 /* IFF_DEBUG equivalent */ #define IEEE80211_MSG_DUMPPKTS 0x20000000 /* IFF_LINK2 equivalant */ #define IEEE80211_MSG_CRYPTO 0x10000000 /* crypto work */ diff --git a/usr/src/uts/common/io/net80211/net80211_ioctl.c b/usr/src/uts/common/io/net80211/net80211_ioctl.c index b6d515bd36..95ed7ae672 100644 --- a/usr/src/uts/common/io/net80211/net80211_ioctl.c +++ b/usr/src/uts/common/io/net80211/net80211_ioctl.c @@ -31,6 +31,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include <sys/param.h> #include <sys/types.h> #include <sys/errno.h> @@ -44,6 +45,34 @@ #include <inet/wifi_ioctl.h> #include "net80211_impl.h" +static int wl_set_essid(struct ieee80211com *, const void *); +static void wl_get_essid(struct ieee80211com *, void *); +static int wl_set_bssid(struct ieee80211com *, const void *); +static void wl_get_bssid(struct ieee80211com *, void *); +static int wl_set_bsstype(struct ieee80211com *, const void *); +static void wl_get_bsstype(struct ieee80211com *, void *); +static void wl_get_linkstatus(struct ieee80211com *, void *); +static int wl_set_desrates(struct ieee80211com *, const void *); +static void wl_get_desrates(struct ieee80211com *, void *); +static int wl_set_authmode(struct ieee80211com *, const void *); +static void wl_get_authmode(struct ieee80211com *, void *); +static int wl_set_encrypt(struct ieee80211com *, const void *); +static void wl_get_encrypt(struct ieee80211com *, void *); +static void wl_get_rssi(struct ieee80211com *, void *); +static int wl_set_phy(struct ieee80211com *, const void *); +static int wl_get_phy(struct ieee80211com *, void *); +static void wl_get_capability(struct ieee80211com *, void *); +static int wl_set_wpa(struct ieee80211com *, const void *); +static void wl_get_wpa(struct ieee80211com *, void *); +static void wl_get_scanresults(struct ieee80211com *, void *); +static void wl_get_esslist(struct ieee80211com *, void *); +static int wl_set_wepkey(struct ieee80211com *, const void *); +static int wl_set_optie(struct ieee80211com *, const void *); +static int wl_set_delkey(struct ieee80211com *, const void *); +static int wl_set_mlme(struct ieee80211com *, const void *); +static int wl_set_wpakey(struct ieee80211com *, const void *); +static void wl_get_suprates(struct ieee80211com *, void *); + static size_t wifi_strnlen(const char *s, size_t n) { @@ -105,7 +134,6 @@ wifi_cfg_essid(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *outp; wl_essid_t *iw_essid = (wl_essid_t *)inp->wldp_buf; wl_essid_t *ow_essid; - char *essid; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_essid_t))) == NULL) @@ -115,35 +143,10 @@ wifi_cfg_essid(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - essid = (char *)ic->ic_des_essid; - if (essid[0] == '\0') - essid = (char *)ic->ic_bss->in_essid; - ow_essid->wl_essid_length = wifi_strnlen((const char *)essid, - IEEE80211_NWID_LEN); - bcopy(essid, ow_essid->wl_essid_essid, - ow_essid->wl_essid_length); + wl_get_essid(ic, ow_essid); break; case WLAN_SET_PARAM: - if (iw_essid->wl_essid_length > IEEE80211_NWID_LEN) { - ieee80211_err("wifi_cfg_essid: " - "essid too long, %u, max %u\n", - iw_essid->wl_essid_length, IEEE80211_NWID_LEN); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - } - essid = iw_essid->wl_essid_essid; - essid[IEEE80211_NWID_LEN] = 0; - ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_essid: " - "set essid=%s length=%d\n", - essid, iw_essid->wl_essid_length); - - ic->ic_des_esslen = iw_essid->wl_essid_length; - if (ic->ic_des_esslen != 0) - bcopy(essid, ic->ic_des_essid, ic->ic_des_esslen); - if (ic->ic_des_esslen < IEEE80211_NWID_LEN) - ic->ic_des_essid[ic->ic_des_esslen] = 0; - err = ENETRESET; + err = wl_set_essid(ic, iw_essid); break; default: ieee80211_err("wifi_cfg_essid: unknown command %x\n", cmd); @@ -163,7 +166,6 @@ wifi_cfg_bssid(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) mblk_t *omp; wldp_t *inp = (wldp_t *)(*mp)->b_rptr; wldp_t *outp; - uint8_t *bssid; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_bssid_t))) == NULL) @@ -172,19 +174,13 @@ wifi_cfg_bssid(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - if (ic->ic_flags & IEEE80211_F_DESBSSID) - bssid = ic->ic_des_bssid; - else - bssid = ic->ic_bss->in_bssid; - bcopy(bssid, outp->wldp_buf, sizeof (wl_bssid_t)); + wl_get_bssid(ic, outp->wldp_buf); break; case WLAN_SET_PARAM: + err = wl_set_bssid(ic, inp->wldp_buf); ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_bssid: " "set bssid=%s\n", ieee80211_macaddr_sprintf(inp->wldp_buf)); - bcopy(inp->wldp_buf, ic->ic_des_bssid, sizeof (wl_bssid_t)); - ic->ic_flags |= IEEE80211_F_DESBSSID; - err = ENETRESET; break; default: ieee80211_err("wifi_cfg_bssid: unknown command %x\n", cmd); @@ -263,7 +259,6 @@ wifi_cfg_phy(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *outp; wl_phy_conf_t *iw_phy = (wl_phy_conf_t *)inp->wldp_buf; wl_phy_conf_t *ow_phy; - struct ieee80211_channel *ch = ic->ic_curchan; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_phy_conf_t))) == NULL) @@ -272,86 +267,13 @@ wifi_cfg_phy(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) ow_phy = (wl_phy_conf_t *)outp->wldp_buf; switch (cmd) { - case WLAN_GET_PARAM: { - /* get current physical (FH, DS, ERP) parameters */ - if (IEEE80211_IS_CHAN_A(ch) || IEEE80211_IS_CHAN_T(ch)) { - wl_ofdm_t *ofdm = (wl_ofdm_t *)ow_phy; - - ofdm->wl_ofdm_subtype = WL_OFDM; - ofdm->wl_ofdm_frequency = ch->ich_freq; - } else { - switch (ic->ic_phytype) { - case IEEE80211_T_FH: { - wl_fhss_t *fhss = (wl_fhss_t *)ow_phy; - - fhss->wl_fhss_subtype = WL_FHSS; - fhss->wl_fhss_channel = - ieee80211_chan2ieee(ic, ch); - break; - } - case IEEE80211_T_DS: { - wl_dsss_t *dsss = (wl_dsss_t *)ow_phy; - - dsss->wl_dsss_subtype = WL_DSSS; - dsss->wl_dsss_channel = - ieee80211_chan2ieee(ic, ch); - break; - } - case IEEE80211_T_OFDM: { - wl_erp_t *erp = (wl_erp_t *)ow_phy; - - erp->wl_erp_subtype = WL_ERP; - erp->wl_erp_channel = - ieee80211_chan2ieee(ic, ch); - break; - } - default: - ieee80211_err("wifi_cfg_phy: " - "unknown phy type, %x\n", ic->ic_phytype); - outp->wldp_result = WL_HW_ERROR; - err = EIO; - break; - } /* switch (ic->ic_phytype) */ - } + case WLAN_GET_PARAM: + err = wl_get_phy(ic, ow_phy); break; - } - - case WLAN_SET_PARAM: { - wl_dsss_t *dsss = (wl_dsss_t *)iw_phy; - int16_t ch = dsss->wl_dsss_channel; - ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_phy: " - "set channel=%d\n", ch); - if (ch == 0 || ch == (int16_t)IEEE80211_CHAN_ANY) { - ic->ic_des_chan = IEEE80211_CHAN_ANYC; - } else if ((uint_t)ch > IEEE80211_CHAN_MAX || - ieee80211_isclr(ic->ic_chan_active, ch)) { - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - } else { - ic->ic_des_chan = ic->ic_ibss_chan = - &ic->ic_sup_channels[ch]; - } - switch (ic->ic_state) { - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - err = ENETRESET; - break; - default: - /* - * If the desired channel has changed (to something - * other than any) and we're not already scanning, - * then kick the state machine. - */ - if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && - ic->ic_bss->in_chan != ic->ic_des_chan && - (ic->ic_flags & IEEE80211_F_SCAN) == 0) - err = ENETRESET; - break; - } + case WLAN_SET_PARAM: + err = wl_set_phy(ic, iw_phy); break; - } default: ieee80211_err("wifi_cfg_phy: unknown command %x\n", cmd); @@ -372,9 +294,6 @@ wifi_cfg_wepkey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *inp = (wldp_t *)(*mp)->b_rptr; wldp_t *outp; wl_wep_key_t *iw_wepkey = (wl_wep_key_t *)inp->wldp_buf; - struct ieee80211_key *k; - uint16_t i; - uint32_t klen; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) @@ -396,50 +315,7 @@ wifi_cfg_wepkey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) break; } - /* set all valid keys */ - for (i = 0; i < MAX_NWEPKEYS; i++) { - if (iw_wepkey[i].wl_wep_operation != WL_ADD) - continue; - klen = iw_wepkey[i].wl_wep_length; - if (klen > IEEE80211_KEYBUF_SIZE) { - ieee80211_err("wifi_cfg_wepkey: " - "invalid wepkey length, %u\n", klen); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - continue; /* continue to set other keys */ - } - if (klen == 0) - continue; - - /* - * Set key contents. Only WEP is supported - */ - ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_wepkey: " - "set key %u, len=%u\n", i, klen); - k = &ic->ic_nw_keys[i]; - if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, - IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, k) == 0) { - ieee80211_err("wifi_cfg_wepkey: " - "abort, create key failed. id=%u\n", i); - outp->wldp_result = WL_HW_ERROR; - err = EIO; - continue; - } - k->wk_keyix = i; - k->wk_keylen = (uint8_t)klen; - k->wk_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; - bzero(k->wk_key, IEEE80211_KEYBUF_SIZE); - bcopy(iw_wepkey[i].wl_wep_key, k->wk_key, klen); - if (ieee80211_crypto_setkey(ic, k, ic->ic_macaddr) - == 0) { - ieee80211_err("wifi_cfg_wepkey: " - "set key failed len=%u\n", klen); - outp->wldp_result = WL_HW_ERROR; - err = EIO; - } - } - if (err == 0) - err = ENETRESET; + err = wl_set_wepkey(ic, iw_wepkey); break; default: ieee80211_err("wifi_cfg_wepkey: unknown command %x\n", cmd); @@ -515,27 +391,10 @@ wifi_cfg_authmode(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - *ow_auth = ic->ic_bss->in_authmode; + wl_get_authmode(ic, ow_auth); break; case WLAN_SET_PARAM: - if (*iw_auth == ic->ic_bss->in_authmode) - break; - - ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_authmode: " - "set authmode=%u\n", *iw_auth); - switch (*iw_auth) { - case WL_OPENSYSTEM: - case WL_SHAREDKEY: - ic->ic_bss->in_authmode = *iw_auth; - err = ENETRESET; - break; - default: - ieee80211_err("wifi_cfg_authmode: " - "unknown authmode %u\n", *iw_auth); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - } + err = wl_set_authmode(ic, iw_auth); break; default: ieee80211_err("wifi_cfg_authmode: unknown command %x\n", cmd); @@ -557,7 +416,6 @@ wifi_cfg_encrypt(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *outp; wl_encryption_t *iw_encryp = (wl_encryption_t *)inp->wldp_buf; wl_encryption_t *ow_encryp; - uint32_t flags; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_encryption_t))) == NULL) @@ -567,23 +425,10 @@ wifi_cfg_encrypt(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - *ow_encryp = (ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0; - if (ic->ic_flags & IEEE80211_F_WPA) - *ow_encryp = WL_ENC_WPA; + wl_get_encrypt(ic, ow_encryp); break; case WLAN_SET_PARAM: - ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_encrypt: " - "set encryption=%u\n", *iw_encryp); - flags = ic->ic_flags; - if (*iw_encryp == WL_NOENCRYPTION) - flags &= ~IEEE80211_F_PRIVACY; - else - flags |= IEEE80211_F_PRIVACY; - - if (ic->ic_flags != flags) { - ic->ic_flags = flags; - err = ENETRESET; - } + err = wl_set_encrypt(ic, iw_encryp); break; default: ieee80211_err("wifi_cfg_encrypt: unknown command %x\n", cmd); @@ -614,47 +459,10 @@ wifi_cfg_bsstype(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - *ow_opmode = WL_BSS_BSS; - break; - case IEEE80211_M_IBSS: - *ow_opmode = WL_BSS_IBSS; - break; - default: - *ow_opmode = WL_BSS_ANY; - break; - } + wl_get_bsstype(ic, ow_opmode); break; case WLAN_SET_PARAM: - ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_bsstype: " - "set bsstype=%u\n", *iw_opmode); - switch (*iw_opmode) { - case WL_BSS_BSS: - ic->ic_flags &= ~IEEE80211_F_IBSSON; - ic->ic_opmode = IEEE80211_M_STA; - err = ENETRESET; - break; - case WL_BSS_IBSS: - if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) { - outp->wldp_result = WL_LACK_FEATURE; - err = ENOTSUP; - break; - } - - if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { - ic->ic_flags |= IEEE80211_F_IBSSON; - ic->ic_opmode = IEEE80211_M_IBSS; - err = ENETRESET; - } - break; - default: - ieee80211_err("wifi_cfg_bsstype: " - "unknown opmode %u\n", *iw_opmode); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - } + err = wl_set_bsstype(ic, iw_opmode); break; default: ieee80211_err("wifi_cfg_bsstype: unknown command %x\n", cmd); @@ -683,12 +491,7 @@ wifi_cfg_linkstatus(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - *ow_linkstat = (ic->ic_state == IEEE80211_S_RUN) ? - WL_CONNECTED : WL_NOTCONNECTED; - if ((ic->ic_flags & IEEE80211_F_WPA) && - (ieee80211_crypto_getciphertype(ic) != WIFI_SEC_WPA)) { - *ow_linkstat = WL_NOTCONNECTED; - } + wl_get_linkstatus(ic, ow_linkstat); break; case WLAN_SET_PARAM: outp->wldp_result = WL_READONLY; @@ -712,9 +515,7 @@ wifi_cfg_suprates(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) mblk_t *omp; wldp_t *outp; wl_rates_t *ow_rates; - const struct ieee80211_rateset *srs; - uint8_t srates, *drates; - int err, buflen, i, j, k, l; + int err, buflen; err = 0; /* rate value (wl_rates_rates) is of type char */ @@ -727,30 +528,7 @@ wifi_cfg_suprates(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - /* all rates supported by the device */ - ow_rates->wl_rates_num = 0; - drates = (uint8_t *)ow_rates->wl_rates_rates; - for (i = 0; i < IEEE80211_MODE_MAX; i++) { - srs = &ic->ic_sup_rates[i]; - if (srs->ir_nrates == 0) - continue; - - for (j = 0; j < srs->ir_nrates; j++) { - srates = IEEE80211_RV(srs->ir_rates[j]); - /* sort and skip duplicated rates */ - for (k = 0; k < ow_rates->wl_rates_num; k++) { - if (srates <= drates[k]) - break; - } - if (srates == drates[k]) - continue; /* duplicate, skip */ - /* sort */ - for (l = ow_rates->wl_rates_num; l > k; l--) - drates[l] = drates[l-1]; - drates[k] = srates; - ow_rates->wl_rates_num++; - } - } + (void) wl_get_suprates(ic, ow_rates); break; case WLAN_SET_PARAM: outp->wldp_result = WL_READONLY; @@ -776,11 +554,7 @@ wifi_cfg_desrates(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) mblk_t *omp; wldp_t *outp; wl_rates_t *ow_rates; - struct ieee80211_node *in = ic->ic_bss; - struct ieee80211_rateset *rs = &in->in_rates; - uint8_t drate, srate; - int err, i, j; - boolean_t found; + int err; err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_rates_t))) == NULL) @@ -788,86 +562,12 @@ wifi_cfg_desrates(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) outp = (wldp_t *)omp->b_rptr; ow_rates = (wl_rates_t *)outp->wldp_buf; - srate = rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL; switch (cmd) { case WLAN_GET_PARAM: - ow_rates->wl_rates_num = 1; - ow_rates->wl_rates_rates[0] = - (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? - srate : ic->ic_fixed_rate; + wl_get_desrates(ic, ow_rates); break; case WLAN_SET_PARAM: - drate = iw_rates->wl_rates_rates[0]; - if (ic->ic_fixed_rate == drate) - break; - - ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_desrates: " - "set desired rate=%u\n", drate); - - if (drate == 0) { /* reset */ - ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; - if (ic->ic_state == IEEE80211_S_RUN) { - IEEE80211_UNLOCK(ic); - ieee80211_new_state(ic, IEEE80211_S_ASSOC, 0); - IEEE80211_LOCK(ic); - } - break; - } - - /* - * Set desired rate. the desired rate is for data transfer - * and usually is checked and used when driver changes to - * RUN state. - * If the driver is in AUTH | ASSOC | RUN state, desired - * rate is checked against rates supported by current ESS. - * If it's supported and current state is AUTH|ASSOC, nothing - * needs to be doen by driver since the desired rate will - * be enabled when the device changes to RUN state. And - * when current state is RUN, Re-associate with the ESS to - * enable the desired rate. - */ - if (ic->ic_state != IEEE80211_S_INIT && - ic->ic_state != IEEE80211_S_SCAN) { - /* check if the rate is supported by current ESS */ - for (i = 0; i < rs->ir_nrates; i++) { - if (drate == IEEE80211_RV(rs->ir_rates[i])) - break; - } - if (i < rs->ir_nrates) { /* supported */ - ic->ic_fixed_rate = drate; - if (ic->ic_state == IEEE80211_S_RUN) { - IEEE80211_UNLOCK(ic); - ieee80211_new_state(ic, - IEEE80211_S_ASSOC, 0); - IEEE80211_LOCK(ic); - } - break; - } - } - - /* check the rate is supported by device */ - found = B_FALSE; - for (i = 0; i < IEEE80211_MODE_MAX; i++) { - rs = &ic->ic_sup_rates[i]; - for (j = 0; j < rs->ir_nrates; j++) { - if (drate == IEEE80211_RV(rs->ir_rates[j])) { - found = B_TRUE; - break; - } - } - if (found) - break; - } - if (!found) { - ieee80211_err("wifi_cfg_desrates: " - "invalid rate %d\n", drate); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - } - ic->ic_fixed_rate = drate; - if (ic->ic_state != IEEE80211_S_SCAN) - err = ENETRESET; /* restart */ + err = wl_set_desrates(ic, iw_rates); break; default: ieee80211_err("wifi_cfg_desrates: unknown command %x\n", cmd); @@ -1216,9 +916,7 @@ wifi_cfg_caps(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_caps: " - "ic_caps = %u\n", ic->ic_caps); - o_caps->caps = ic->ic_caps; + wl_get_capability(ic, o_caps); break; case WLAN_SET_PARAM: outp->wldp_result = WL_READONLY; @@ -1256,20 +954,10 @@ wifi_cfg_wpa(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) switch (cmd) { case WLAN_GET_PARAM: - ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_wpa: " - "get wpa=%u\n", wpa->wpa_flag); - o_wpa->wpa_flag = ((ic->ic_flags & IEEE80211_F_WPA)? 1 : 0); + wl_get_wpa(ic, o_wpa); break; case WLAN_SET_PARAM: - ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_wpa: " - "set wpa=%u\n", wpa->wpa_flag); - if (wpa->wpa_flag > 0) { /* enable WPA mode */ - ic->ic_flags |= IEEE80211_F_PRIVACY; - ic->ic_flags |= IEEE80211_F_WPA; - } else { - ic->ic_flags &= ~IEEE80211_F_PRIVACY; - ic->ic_flags &= ~IEEE80211_F_WPA; - } + err = wl_set_wpa(ic, wpa); break; default: ieee80211_err("wifi_cfg_wpa: unknown command %x\n", cmd); @@ -1294,9 +982,6 @@ wifi_cfg_wpakey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *outp; wldp_t *inp = (wldp_t *)(*mp)->b_rptr; wl_key_t *ik = (wl_key_t *)(inp->wldp_buf); - struct ieee80211_node *in; - struct ieee80211_key *wk; - uint16_t kid; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) @@ -1309,62 +994,7 @@ wifi_cfg_wpakey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) err = EINVAL; break; case WLAN_SET_PARAM: - ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_wpakey: " - "idx=%d\n", ik->ik_keyix); - /* NB: cipher support is verified by ieee80211_crypt_newkey */ - /* NB: this also checks ik->ik_keylen > sizeof(wk->wk_key) */ - if (ik->ik_keylen > sizeof (ik->ik_keydata)) { - ieee80211_err("wifi_cfg_wpakey: key too long\n"); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - } - kid = ik->ik_keyix; - if (kid == IEEE80211_KEYIX_NONE || kid >= IEEE80211_WEP_NKID) { - ieee80211_err("wifi_cfg_wpakey: incorrect keyix\n"); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - - } else { - wk = &ic->ic_nw_keys[kid]; - /* - * Global slots start off w/o any assigned key index. - * Force one here for consistency with WEPKEY. - */ - if (wk->wk_keyix == IEEE80211_KEYIX_NONE) - wk->wk_keyix = kid; - /* in = ic->ic_bss; */ - in = NULL; - } - - KEY_UPDATE_BEGIN(ic); - if (ieee80211_crypto_newkey(ic, ik->ik_type, - ik->ik_flags, wk)) { - wk->wk_keylen = ik->ik_keylen; - /* NB: MIC presence is implied by cipher type */ - if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) - wk->wk_keylen = IEEE80211_KEYBUF_SIZE; - wk->wk_keyrsc = ik->ik_keyrsc; - wk->wk_keytsc = 0; /* new key, reset */ - wk->wk_flags |= ik->ik_flags & - (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); - (void) memset(wk->wk_key, 0, sizeof (wk->wk_key)); - (void) memcpy(wk->wk_key, ik->ik_keydata, - ik->ik_keylen); - if (!ieee80211_crypto_setkey(ic, wk, - in != NULL ? in->in_macaddr : ik->ik_macaddr)) { - err = EIO; - outp->wldp_result = WL_HW_ERROR; - } else if ((ik->ik_flags & IEEE80211_KEY_DEFAULT)) { - ic->ic_def_txkey = kid; - ieee80211_mac_update(ic); - } - } else { - err = EIO; - outp->wldp_result = WL_HW_ERROR; - } - KEY_UPDATE_END(ic); + err = wl_set_wpakey(ic, ik); break; default: ieee80211_err("wifi_cfg_wpakey: unknown command %x\n", cmd); @@ -1389,7 +1019,6 @@ wifi_cfg_delkey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *outp; wldp_t *inp = (wldp_t *)(*mp)->b_rptr; wl_del_key_t *dk = (wl_del_key_t *)inp->wldp_buf; - int kid; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) @@ -1402,20 +1031,7 @@ wifi_cfg_delkey(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) err = EINVAL; break; case WLAN_SET_PARAM: - ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_delkey: " - "keyix=%d\n", dk->idk_keyix); - kid = dk->idk_keyix; - if (kid == IEEE80211_KEYIX_NONE || kid >= IEEE80211_WEP_NKID) { - ieee80211_err("wifi_cfg_delkey: incorrect keyix\n"); - outp->wldp_result = WL_NOTSUPPORTED; - err = EINVAL; - break; - - } else { - (void) ieee80211_crypto_delkey(ic, - &ic->ic_nw_keys[kid]); - ieee80211_mac_update(ic); - } + err = wl_set_delkey(ic, dk); break; default: ieee80211_err("wifi_cfg_delkey: unknown command %x\n", cmd); @@ -1439,7 +1055,6 @@ wifi_cfg_setoptie(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *outp; wldp_t *inp = (wldp_t *)(*mp)->b_rptr; wl_wpa_ie_t *ie_in = (wl_wpa_ie_t *)inp->wldp_buf; - char *ie; int err = 0; if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) @@ -1452,32 +1067,8 @@ wifi_cfg_setoptie(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) err = EINVAL; break; case WLAN_SET_PARAM: - ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_setoptie\n"); - /* - * NB: Doing this for ap operation could be useful (e.g. for - * WPA and/or WME) except that it typically is worthless - * without being able to intervene when processing - * association response frames--so disallow it for now. - */ - if (ic->ic_opmode != IEEE80211_M_STA) { - ieee80211_err("wifi_cfg_setoptie: opmode err\n"); - err = EINVAL; + if ((err = wl_set_optie(ic, ie_in)) == EINVAL) outp->wldp_result = WL_NOTSUPPORTED; - break; - } - if (ie_in->wpa_ie_len > IEEE80211_MAX_OPT_IE) { - ieee80211_err("wifi_cfg_setoptie: optie too long\n"); - err = EINVAL; - outp->wldp_result = WL_NOTSUPPORTED; - break; - } - - ie = ieee80211_malloc(ie_in->wpa_ie_len); - (void) memcpy(ie, ie_in->wpa_ie, ie_in->wpa_ie_len); - if (ic->ic_opt_ie != NULL) - ieee80211_free(ic->ic_opt_ie); - ic->ic_opt_ie = ie; - ic->ic_opt_ie_len = ie_in->wpa_ie_len; break; default: ieee80211_err("wifi_cfg_setoptie: unknown command %x\n", cmd); @@ -1573,9 +1164,7 @@ wifi_cfg_setmlme(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) wldp_t *outp; wldp_t *inp = (wldp_t *)(*mp)->b_rptr; wl_mlme_t *mlme = (wl_mlme_t *)inp->wldp_buf; - ieee80211_node_t *in; int err = 0; - uint32_t flags; if ((omp = wifi_getoutmsg(*mp, cmd, 0)) == NULL) return (ENOMEM); @@ -1587,60 +1176,7 @@ wifi_cfg_setmlme(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp) err = EINVAL; break; case WLAN_SET_PARAM: - ieee80211_dbg(IEEE80211_MSG_WPA, "wifi_cfg_setmlme: " - "op=%d\n", mlme->im_op); - switch (mlme->im_op) { - case IEEE80211_MLME_DISASSOC: - case IEEE80211_MLME_DEAUTH: - if (ic->ic_opmode == IEEE80211_M_STA) { - /* - * Mask ic_flags of IEEE80211_F_WPA to disable - * ieee80211_notify temporarily. - */ - flags = ic->ic_flags; - ic->ic_flags &= ~IEEE80211_F_WPA; - - IEEE80211_UNLOCK(ic); - ieee80211_new_state(ic, IEEE80211_S_INIT, - mlme->im_reason); - IEEE80211_LOCK(ic); - - ic->ic_flags = flags; - } - break; - case IEEE80211_MLME_ASSOC: - if (ic->ic_opmode != IEEE80211_M_STA) { - ieee80211_err("wifi_cfg_setmlme: opmode err\n"); - err = EINVAL; - outp->wldp_result = WL_NOTSUPPORTED; - break; - } - if (ic->ic_des_esslen != 0) { - /* - * Desired ssid specified; must match both bssid and - * ssid to distinguish ap advertising multiple ssid's. - */ - in = ieee80211_find_node_with_ssid(&ic->ic_scan, - mlme->im_macaddr, - ic->ic_des_esslen, ic->ic_des_essid); - } else { - /* - * Normal case; just match bssid. - */ - in = ieee80211_find_node(&ic->ic_scan, - mlme->im_macaddr); - } - if (in == NULL) { - ieee80211_err("wifi_cfg_setmlme: " - "no matched node\n"); - err = EINVAL; - outp->wldp_result = WL_NOTSUPPORTED; - break; - } - IEEE80211_UNLOCK(ic); - ieee80211_sta_join(ic, in); - IEEE80211_LOCK(ic); - } + err = wl_set_mlme(ic, mlme); break; default: ieee80211_err("wifi_cfg_delkey: unknown command %x\n", cmd); @@ -1842,3 +1378,1055 @@ ieee80211_ioctl(struct ieee80211com *ic, queue_t *wq, mblk_t *mp) return (err); } + +/* + * The following routines are for brussels support + */ + +/* + * MAC_PROP_WL_ESSID + */ +static int +wl_set_essid(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + char *essid; + wl_essid_t *iw_essid = (wl_essid_t *)wldp_buf; + + if (iw_essid->wl_essid_length > IEEE80211_NWID_LEN) { + ieee80211_err("wl_set_essid: " + "essid too long, %u, max %u\n", + iw_essid->wl_essid_length, IEEE80211_NWID_LEN); + + err = EINVAL; + return (err); + } + + essid = iw_essid->wl_essid_essid; + essid[IEEE80211_NWID_LEN] = 0; + + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_essid: " + "set essid=%s length=%d\n", + essid, iw_essid->wl_essid_length); + + ic->ic_des_esslen = iw_essid->wl_essid_length; + if (ic->ic_des_esslen != 0) + bcopy(essid, ic->ic_des_essid, ic->ic_des_esslen); + if (ic->ic_des_esslen < IEEE80211_NWID_LEN) + ic->ic_des_essid[ic->ic_des_esslen] = 0; + + err = ENETRESET; + + return (err); +} + +static void +wl_get_essid(struct ieee80211com *ic, void *wldp_buf) +{ + char *essid; + wl_essid_t ow_essid; + + essid = (char *)ic->ic_des_essid; + if (essid[0] == '\0') + essid = (char *)ic->ic_bss->in_essid; + + bzero(&ow_essid, sizeof (wl_essid_t)); + ow_essid.wl_essid_length = wifi_strnlen((const char *)essid, + IEEE80211_NWID_LEN); + bcopy(essid, ow_essid.wl_essid_essid, + ow_essid.wl_essid_length); + bcopy(&ow_essid, wldp_buf, sizeof (wl_essid_t)); + +} + +/* + * MAC_PROP_WL_BSSID + */ +static int +wl_set_bssid(struct ieee80211com *ic, const void* wldp_buf) +{ + + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_bssid: " + "set bssid=%s\n", + ieee80211_macaddr_sprintf(wldp_buf)); + + bcopy(wldp_buf, ic->ic_des_bssid, sizeof (wl_bssid_t)); + ic->ic_flags |= IEEE80211_F_DESBSSID; + + return (ENETRESET); +} + +static void +wl_get_bssid(struct ieee80211com *ic, void *wldp_buf) +{ + uint8_t *bssid; + + if (ic->ic_flags & IEEE80211_F_DESBSSID) + bssid = ic->ic_des_bssid; + else + bssid = ic->ic_bss->in_bssid; + bcopy(bssid, wldp_buf, sizeof (wl_bssid_t)); + +} + +/* + * MAC_PROP_WL_BSSTYP + */ +static int +wl_set_bsstype(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + wl_bss_type_t *iw_opmode = (wl_bss_type_t *)wldp_buf; + + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_bsstype: " + "set bsstype=%u\n", *iw_opmode); + + switch (*iw_opmode) { + case WL_BSS_BSS: + ic->ic_flags &= ~IEEE80211_F_IBSSON; + ic->ic_opmode = IEEE80211_M_STA; + err = ENETRESET; + break; + case WL_BSS_IBSS: + if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) { + err = ENOTSUP; + break; + } + if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { + ic->ic_flags |= IEEE80211_F_IBSSON; + ic->ic_opmode = IEEE80211_M_IBSS; + err = ENETRESET; + } + break; + default: + ieee80211_err("wl_set_bsstype: " + "unknown opmode\n"); + err = EINVAL; + break; + } + return (err); +} + +static void +wl_get_bsstype(struct ieee80211com *ic, void *wldp_buf) +{ + wl_bss_type_t ow_opmode; + + switch (ic->ic_opmode) { + case IEEE80211_M_STA: + ow_opmode = WL_BSS_BSS; + break; + case IEEE80211_M_IBSS: + ow_opmode = WL_BSS_IBSS; + break; + default: + ow_opmode = WL_BSS_ANY; + break; + } + + bcopy(&ow_opmode, wldp_buf, sizeof (wl_bss_type_t)); +} + +/* + * MAC_PROP_WL_LINKSTATUS + */ +static void +wl_get_linkstatus(struct ieee80211com *ic, void *wldp_buf) +{ + wl_linkstatus_t ow_linkstat; + + ow_linkstat = (ic->ic_state == IEEE80211_S_RUN) ? + WL_CONNECTED : WL_NOTCONNECTED; + if ((ic->ic_flags & IEEE80211_F_WPA) && + (ieee80211_crypto_getciphertype(ic) != WIFI_SEC_WPA)) { + ow_linkstat = WL_NOTCONNECTED; + } + + bcopy(&ow_linkstat, wldp_buf, sizeof (wl_linkstatus_t)); +} + +/* + * MAC_PROP_WL_DESIRED_RATESa + */ +static int +wl_set_desrates(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + int i, j; + uint8_t drate; + boolean_t isfound; + wl_rates_t *iw_rates = (wl_rates_t *)wldp_buf; + struct ieee80211_node *in = ic->ic_bss; + struct ieee80211_rateset *rs = &in->in_rates; + + drate = iw_rates->wl_rates_rates[0]; + if (ic->ic_fixed_rate == drate) + return (err); + + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_desrates: " + "set desired rate=%u\n", drate); + + if (drate == 0) { + ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE; + if (ic->ic_state == IEEE80211_S_RUN) { + IEEE80211_UNLOCK(ic); + ieee80211_new_state(ic, IEEE80211_S_ASSOC, 0); + IEEE80211_LOCK(ic); + } + return (err); + } + + /* + * Set desired rate. The desired rate is for data transfer + * and usally is checked and used when driver changes to + * RUN state. + * If the driver is in AUTH | ASSOC | RUN state, desired + * rate is checked anainst rates supported by current ESS. + * If it's supported and current state is AUTH|ASSOC, nothing + * needs to be done by driver since the desired rate will + * be enabled when the device changes to RUN state. And + * when current state is RUN, Re-associate with the ESS to + * enable the desired rate. + */ + + if (ic->ic_state != IEEE80211_S_INIT && + ic->ic_state != IEEE80211_S_SCAN) { + for (i = 0; i < rs->ir_nrates; i++) { + if (drate == IEEE80211_RV(rs->ir_rates[i])) + break; + } + /* supported */ + if (i < rs->ir_nrates) { + ic->ic_fixed_rate = drate; + if (ic->ic_state == IEEE80211_S_RUN) { + IEEE80211_UNLOCK(ic); + ieee80211_new_state(ic, + IEEE80211_S_ASSOC, 0); + IEEE80211_LOCK(ic); + } + return (err); + } + } + + /* + * In INIT or SCAN state + * check if the desired rate is supported by device + */ + isfound = B_FALSE; + for (i = 0; i < IEEE80211_MODE_MAX; i++) { + rs = &ic->ic_sup_rates[i]; + for (j = 0; j < rs->ir_nrates; j++) { + if (drate == IEEE80211_RV(rs->ir_rates[j])) { + isfound = B_TRUE; + break; + } + } + if (isfound) + break; + } + if (!isfound) { + ieee80211_err("wl_set_desrates: " + "invald rate %d\n", drate); + err = EINVAL; + return (err); + } + ic->ic_fixed_rate = drate; + if (ic->ic_state != IEEE80211_S_SCAN) + err = ENETRESET; + + return (err); +} + +static void +wl_get_desrates(struct ieee80211com *ic, void *wldp_buf) +{ + uint8_t srate; + wl_rates_t ow_rates; + struct ieee80211_node *in = ic->ic_bss; + struct ieee80211_rateset *rs = &in->in_rates; + + srate = rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL; + ow_rates.wl_rates_num = 1; + ow_rates.wl_rates_rates[0] = + (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ? + srate : ic->ic_fixed_rate; + bcopy(&ow_rates, wldp_buf, sizeof (wl_rates_t)); + +} + +/* + * MAC_PROP_AUTH_MODE + */ +static int +wl_set_authmode(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + wl_authmode_t *iw_auth = (wl_authmode_t *)wldp_buf; + + if (*iw_auth == ic->ic_bss->in_authmode) + return (err); + + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_authmode: " + "set authmode=%u\n", *iw_auth); + + switch (*iw_auth) { + case WL_OPENSYSTEM: + case WL_SHAREDKEY: + ic->ic_bss->in_authmode = *iw_auth; + err = ENETRESET; + break; + default: + ieee80211_err("wl_set_authmode: " + "unknown authmode %u\n", *iw_auth); + err = EINVAL; + break; + } + + return (err); +} + +static void +wl_get_authmode(struct ieee80211com *ic, void *wldp_buf) +{ + wl_authmode_t ow_auth; + + ow_auth = ic->ic_bss->in_authmode; + bcopy(&ow_auth, wldp_buf, sizeof (wl_authmode_t)); + +} + +/* + * MAC_PROP_WL_ENCRYPTION + */ +static int +wl_set_encrypt(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + uint32_t flags; + wl_encryption_t *iw_encryp = (wl_encryption_t *)wldp_buf; + + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_encrypt: " + "set encryption=%u\n", *iw_encryp); + + flags = ic->ic_flags; + if (*iw_encryp == WL_NOENCRYPTION) + flags &= ~IEEE80211_F_PRIVACY; + else + flags |= IEEE80211_F_PRIVACY; + + if (ic->ic_flags != flags) { + ic->ic_flags = flags; + err = ENETRESET; + } + + return (err); +} + +static void +wl_get_encrypt(struct ieee80211com *ic, void *wldp_buf) +{ + wl_encryption_t *ow_encryp; + + ow_encryp = (wl_encryption_t *)wldp_buf; + *ow_encryp = (ic->ic_flags & IEEE80211_F_PRIVACY) ? 1 : 0; + if (ic->ic_flags & IEEE80211_F_WPA) + *ow_encryp = WL_ENC_WPA; + +} + +/* + * MAC_PROP_WL_RSSI + */ +static void +wl_get_rssi(struct ieee80211com *ic, void *wldp_buf) +{ + wl_rssi_t *ow_rssi; + + ow_rssi = (wl_rssi_t *)wldp_buf; + *ow_rssi = wifi_getrssi(ic->ic_bss); + +} + +/* + * MAC_PROP_WL_PHY_CONFIG + */ + +static int +wl_set_phy(struct ieee80211com *ic, const void* wldp_buf) +{ + int err = 0; + int16_t ch; + wl_dsss_t *dsss; + wl_phy_conf_t *iw_phy = (wl_phy_conf_t *)wldp_buf; + + dsss = (wl_dsss_t *)iw_phy; + ch = dsss->wl_dsss_channel; + + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_phy: " + "set channel=%d\n", ch); + + if (ch == 0 || ch == (int16_t)IEEE80211_CHAN_ANY) { + ic->ic_des_chan = IEEE80211_CHAN_ANYC; + } else if ((uint_t)ch > IEEE80211_CHAN_MAX || + ieee80211_isclr(ic->ic_chan_active, ch)) { + err = EINVAL; + return (err); + } else { + ic->ic_des_chan = ic->ic_ibss_chan = + &ic->ic_sup_channels[ch]; + } + + switch (ic->ic_state) { + case IEEE80211_S_INIT: + case IEEE80211_S_SCAN: + err = ENETRESET; + break; + default: + /* + * If hte desired channel has changed (to something + * other than any) and we're not already scanning, + * then kick the state machine. + */ + if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && + ic->ic_bss->in_chan != ic->ic_des_chan && + (ic->ic_flags & IEEE80211_F_SCAN) == 0) + err = ENETRESET; + break; + } + + return (err); +} + +static int +wl_get_phy(struct ieee80211com *ic, void *wldp_buf) +{ + int err = 0; + wl_phy_conf_t *ow_phy; + struct ieee80211_channel *ch = ic->ic_curchan; + + ow_phy = (wl_phy_conf_t *)wldp_buf; + bzero(wldp_buf, sizeof (wl_phy_conf_t)); + + /* get current phy parameters: FH|DS|ERP */ + if (IEEE80211_IS_CHAN_A(ch) || IEEE80211_IS_CHAN_T(ch)) { + wl_ofdm_t *ofdm = (wl_ofdm_t *)ow_phy; + ofdm->wl_ofdm_subtype = WL_OFDM; + ofdm->wl_ofdm_frequency = ch->ich_freq; + } else { + switch (ic->ic_phytype) { + case IEEE80211_T_FH: { + wl_fhss_t *fhss = (wl_fhss_t *)ow_phy; + fhss->wl_fhss_subtype = WL_FHSS; + fhss->wl_fhss_channel = + ieee80211_chan2ieee(ic, ch); + break; + } + case IEEE80211_T_DS: { + wl_dsss_t *dsss = (wl_dsss_t *)ow_phy; + dsss->wl_dsss_subtype = WL_DSSS; + dsss->wl_dsss_channel = + ieee80211_chan2ieee(ic, ch); + break; + } + case IEEE80211_T_OFDM: { + wl_erp_t *erp = (wl_erp_t *)ow_phy; + erp->wl_erp_subtype = WL_ERP; + erp->wl_erp_channel = + ieee80211_chan2ieee(ic, ch); + break; + } + default: + ieee80211_err("wl_get_phy: " + "unknown phy type, %x\n", ic->ic_phytype); + err = EIO; + break; + } + } + + return (err); +} + +/* + * MAC_PROP_WL_CAPABILITY + */ +static void +wl_get_capability(struct ieee80211com *ic, void *wldp_buf) +{ + wl_capability_t ow_caps; + + ow_caps.caps = ic->ic_caps; + bcopy(&ow_caps, wldp_buf, sizeof (wl_capability_t)); + +} + +/* + * MAC_PROP_WL_WPA + */ +static int +wl_set_wpa(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + wl_wpa_t *wpa = (wl_wpa_t *)wldp_buf; + + ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_set_wpa: " + "set wpa=%u\n", wpa->wpa_flag); + + if (wpa->wpa_flag > 0) { + /* enable wpa mode */ + ic->ic_flags |= IEEE80211_F_PRIVACY; + ic->ic_flags |= IEEE80211_F_WPA; + } else { + ic->ic_flags &= ~IEEE80211_F_PRIVACY; + ic->ic_flags &= ~IEEE80211_F_WPA; + } + + return (err); +} + +static void +wl_get_wpa(struct ieee80211com *ic, void *wldp_buf) +{ + wl_wpa_t *wpa; + + wpa = (wl_wpa_t *)wldp_buf; + wpa->wpa_flag = ((ic->ic_flags & IEEE80211_F_WPA) ? 1 : 0); + + ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_get_wpa: " + "get wpa=%u\n", wpa->wpa_flag); + +} + +/* + * MAC_PROP_WL_SCANRESULTS + */ + +static void +wl_get_scanresults(struct ieee80211com *ic, void *wldp_buf) +{ + wl_wpa_ess_t *sr; + ieee80211_node_t *in; + ieee80211_node_table_t *nt; + int ap_num; + int len; + + sr = (wl_wpa_ess_t *)wldp_buf; + sr->count = 0; + ap_num = 0; + + ieee80211_dbg(IEEE80211_MSG_WPA, "wl_get_scanrelults\n"); + + nt = &ic->ic_scan; + IEEE80211_NODE_LOCK(nt); + in = list_head(&nt->nt_node); + + while (in != NULL) { + /* filter out non-wpa APs */ + if (in->in_wpa_ie == NULL) { + in = list_next(&nt->nt_node, in); + continue; + } + bcopy(in->in_bssid, sr->ess[ap_num].bssid, + IEEE80211_ADDR_LEN); + sr->ess[ap_num].ssid_len = in->in_esslen; + bcopy(in->in_essid, sr->ess[ap_num].ssid, + in->in_esslen); + sr->ess[ap_num].freq = in->in_chan->ich_freq; + + len = in->in_wpa_ie[1] + 2; + bcopy(in->in_wpa_ie, sr->ess[ap_num].wpa_ie, len); + sr->ess[ap_num].wpa_ie_len = len; + + ap_num++; + in = list_next(&nt->nt_node, in); + } + IEEE80211_NODE_UNLOCK(nt); + sr->count = ap_num; + +} + +/* + * MAC_PROP_WL_ESS_LIST + */ +static void +wl_get_esslist(struct ieee80211com *ic, void *wldp_buf) +{ + wl_ess_list_t *ess_list; + + ess_list = (wl_ess_list_t *)wldp_buf; + + ess_list->wl_ess_list_num = 0; + ieee80211_iterate_nodes(&ic->ic_scan, wifi_read_ap, ess_list); + +} + +/* + * MAC_PROP_WL_WEP_KEY + */ +static int +wl_set_wepkey(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + uint16_t i; + uint32_t klen; + struct ieee80211_key *key; + wl_wep_key_t *wepkey = (wl_wep_key_t *)wldp_buf; + + /* set all valid keys */ + for (i = 0; i < MAX_NWEPKEYS; i++) { + if (wepkey[i].wl_wep_operation != WL_ADD) + continue; + klen = wepkey[i].wl_wep_length; + if (klen > IEEE80211_KEYBUF_SIZE) { + ieee80211_err("wl_set_wepkey: " + "invalid wepkey length, %u\n", klen); + err = EINVAL; + continue; /* continue to set other keys */ + } + if (klen == 0) + continue; + + /* + * Set key contents. Only WEP is supported + */ + ieee80211_dbg(IEEE80211_MSG_CONFIG, "wl_set_wepkey: " + "set key %u, len=%u\n", i, klen); + key = &ic->ic_nw_keys[i]; + if (ieee80211_crypto_newkey(ic, IEEE80211_CIPHER_WEP, + IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV, key) == 0) { + ieee80211_err("wl_set_wepkey: " + "abort, create key failed. id=%u\n", i); + err = EIO; + continue; + } + + key->wk_keyix = i; + key->wk_keylen = (uint8_t)klen; + key->wk_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; + bzero(key->wk_key, IEEE80211_KEYBUF_SIZE); + bcopy(wepkey[i].wl_wep_key, key->wk_key, klen); + if (ieee80211_crypto_setkey(ic, key, ic->ic_macaddr) + == 0) { + ieee80211_err("wl_set_wepkey: " + "set key failed len=%u\n", klen); + err = EIO; + } + } + if (err == 0) + err = ENETRESET; + + return (err); +} + +/* + * MAC_PROP_WL_SETOPTIE + */ +static int +wl_set_optie(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + char *ie; + wl_wpa_ie_t *ie_in = (wl_wpa_ie_t *)wldp_buf; + + if (ic->ic_opmode != IEEE80211_M_STA) { + ieee80211_err("wl_set_optie: opmode err\n"); + err = EINVAL; + return (err); + } + if (ie_in->wpa_ie_len > IEEE80211_MAX_OPT_IE) { + + ieee80211_err("wl_set_optie: optie is too long\n"); + + err = EINVAL; + return (err); + } + + ie = ieee80211_malloc(ie_in->wpa_ie_len); + (void) memcpy(ie, ie_in->wpa_ie, ie_in->wpa_ie_len); + if (ic->ic_opt_ie != NULL) { + ieee80211_dbg(IEEE80211_MSG_BRUSSELS, + "wl_set_optie:ic_opt_ie!=NULL\n"); + ieee80211_free(ic->ic_opt_ie); + } + ic->ic_opt_ie = ie; + ic->ic_opt_ie_len = ie_in->wpa_ie_len; + + return (err); +} + +/* + * MAC_PROP_WL_DELKEY + */ +static int +wl_set_delkey(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + int kid; + wl_del_key_t *dk = (wl_del_key_t *)wldp_buf; + + ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_set_delkey(): " + "keyix=%d\n", dk->idk_keyix); + + kid = dk->idk_keyix; + + if (kid == IEEE80211_KEYIX_NONE || + kid >= IEEE80211_WEP_NKID) { + ieee80211_err("wl_set_delkey: incorrect keyix\n"); + err = EINVAL; + return (err); + } else { + (void) ieee80211_crypto_delkey(ic, + &ic->ic_nw_keys[kid]); + ieee80211_mac_update(ic); + } + + return (err); +} + +/* + * MAC_PROP_WL_MLME + */ + +static int +wl_set_mlme(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + uint32_t flags; + ieee80211_node_t *in; + wl_mlme_t *mlme = (wl_mlme_t *)wldp_buf; + + ieee80211_dbg(IEEE80211_MSG_WPA, "wl_set_mlme: " + "op=%d\n", mlme->im_op); + + switch (mlme->im_op) { + case IEEE80211_MLME_DISASSOC: + case IEEE80211_MLME_DEAUTH: + if (ic->ic_opmode == IEEE80211_M_STA) { + /* + * Mask ic_flags of IEEE80211_F_WPA to disable + * ieee80211_notify temporarily. + */ + flags = ic->ic_flags; + ic->ic_flags &= ~IEEE80211_F_WPA; + + IEEE80211_UNLOCK(ic); + ieee80211_new_state(ic, IEEE80211_S_INIT, + mlme->im_reason); + IEEE80211_LOCK(ic); + + ic->ic_flags = flags; + } + break; + case IEEE80211_MLME_ASSOC: + if (ic->ic_opmode != IEEE80211_M_STA) { + ieee80211_err("wifi_cfg_setmlme: opmode err\n"); + err = EINVAL; + break; + } + if (ic->ic_des_esslen != 0) { + /* + * Desired ssid specified; must match both bssid and + * ssid to distinguish ap advertising multiple ssid's. + */ + in = ieee80211_find_node_with_ssid(&ic->ic_scan, + mlme->im_macaddr, + ic->ic_des_esslen, + ic->ic_des_essid); + } else { + /* + * Normal case; just match bssid. + */ + in = ieee80211_find_node(&ic->ic_scan, + mlme->im_macaddr); + } + if (in == NULL) { + ieee80211_err("wifi_cfg_setmlme: " + "no matched node\n"); + err = EINVAL; + break; + } + IEEE80211_UNLOCK(ic); + ieee80211_sta_join(ic, in); + IEEE80211_LOCK(ic); + break; + default: + err = EINVAL; + break; + } + + return (err); +} + +/* + * MAC_PROP_WL_WPA_KEY + */ +static int +wl_set_wpakey(struct ieee80211com *ic, const void *wldp_buf) +{ + int err = 0; + uint16_t kid; + struct ieee80211_node *in; + struct ieee80211_key *wk; + wl_key_t *ik = (wl_key_t *)wldp_buf; + + ieee80211_dbg(IEEE80211_MSG_BRUSSELS, "wl_set_wpakey: " + "idx=%d\n", ik->ik_keyix); + + /* + * cipher support is verified by ieee80211_crypt_newkey + * this also checks ik->ik_keylen > sizeof(wk->wk_key) + */ + if (ik->ik_keylen > sizeof (ik->ik_keydata)) { + ieee80211_err("wl_set_wpakey: key is too long\n"); + err = EINVAL; + return (err); + } + kid = ik->ik_keyix; + if (kid == IEEE80211_KEYIX_NONE || kid >= IEEE80211_WEP_NKID) { + ieee80211_err("wl_set_wpakey: incorrect keyix\n"); + err = EINVAL; + return (err); + } else { + wk = &ic->ic_nw_keys[kid]; + /* + * Globle slots start off w/o any assigned key index. + * Force one here for consistency with WEPKEY. + */ + if (wk->wk_keyix == IEEE80211_KEYIX_NONE) + wk->wk_keyix = kid; + in = NULL; + } + + KEY_UPDATE_BEGIN(ic); + if (ieee80211_crypto_newkey(ic, ik->ik_type, + ik->ik_flags, wk)) { + wk->wk_keylen = ik->ik_keylen; + /* MIC presence is implied by cipher type */ + if (wk->wk_keylen > IEEE80211_KEYBUF_SIZE) + wk->wk_keylen = IEEE80211_KEYBUF_SIZE; + wk->wk_keyrsc = ik->ik_keyrsc; + wk->wk_keytsc = 0; + wk->wk_flags |= ik->ik_flags & + (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV); + (void) memset(wk->wk_key, 0, sizeof (wk->wk_key)); + (void) memcpy(wk->wk_key, ik->ik_keydata, + ik->ik_keylen); + if (!ieee80211_crypto_setkey(ic, wk, + in != NULL ? in->in_macaddr : ik->ik_macaddr)) { + err = EIO; + } else if ((ik->ik_flags & IEEE80211_KEY_DEFAULT)) { + ic->ic_def_txkey = kid; + ieee80211_mac_update(ic); + } + } else { + err = EIO; + } + KEY_UPDATE_END(ic); + + return (err); +} + +/* + * MAC_PROP_WL_SUP_RATE + */ +static void +wl_get_suprates(struct ieee80211com *ic, void *wldp_buf) +{ + int i, j, k, l; + uint8_t srates; + uint8_t *drates; + wl_rates_t *wl_rates; + const struct ieee80211_rateset *srs; + + wl_rates = (wl_rates_t *)wldp_buf; + + wl_rates->wl_rates_num = 0; + drates = (uint8_t *)wl_rates->wl_rates_rates; + for (i = 0; i < IEEE80211_MODE_MAX; i++) { + srs = &ic->ic_sup_rates[i]; + if (srs->ir_nrates == 0) + continue; + for (j = 0; j < srs->ir_nrates; j++) { + srates = IEEE80211_RV(srs->ir_rates[j]); + /* sort & skip duplicated rates */ + for (k = 0; k < wl_rates->wl_rates_num; k++) { + if (srates <= drates[k]) + break; + } + if (srates == drates[k]) + /* skip duplicated rates */ + continue; + /* sort */ + for (l = wl_rates->wl_rates_num; l > k; l--) + drates[l] = drates[l-1]; + drates[k] = srates; + wl_rates->wl_rates_num++; + } + } + +} + +/* + * Typically invoked by drivers in response to request for + * information or to change settings from the userland. + * + * Return value should be checked by WiFI drivers. Return 0 + * on success. Otherwise, return non-zero value to indicate + * the error. Driver should operate as below when the return + * error is: + * ENETRESET Reset wireless network and re-start to join a + * WLAN, ENETRESET is returned when a configuration + * parameter has been changed. + * When acknowledge a M_IOCTL message, this error + * is ignored + */ +/* ARGSUSED */ +int +ieee80211_setprop(void *ic_arg, const char *pr_name, mac_prop_id_t wldp_pr_num, + uint_t wldp_length, const void *wldp_buf) +{ + int err = 0; + struct ieee80211com *ic = ic_arg; + + ASSERT(ic != NULL); + IEEE80211_LOCK(ic); + + switch (wldp_pr_num) { + /* mac_prop_id */ + case MAC_PROP_WL_ESSID: + err = wl_set_essid(ic, wldp_buf); + break; + case MAC_PROP_WL_BSSID: + err = wl_set_bssid(ic, wldp_buf); + break; + case MAC_PROP_WL_PHY_CONFIG: + err = wl_set_phy(ic, wldp_buf); + break; + case MAC_PROP_WL_KEY_TAB: + err = wl_set_wepkey(ic, wldp_buf); + break; + case MAC_PROP_WL_AUTH_MODE: + err = wl_set_authmode(ic, wldp_buf); + break; + case MAC_PROP_WL_ENCRYPTION: + err = wl_set_encrypt(ic, wldp_buf); + break; + case MAC_PROP_WL_BSSTYPE: + err = wl_set_bsstype(ic, wldp_buf); + break; + case MAC_PROP_WL_DESIRED_RATES: + err = wl_set_desrates(ic, wldp_buf); + break; + case MAC_PROP_WL_WPA: + err = wl_set_wpa(ic, wldp_buf); + break; + case MAC_PROP_WL_KEY: + err = wl_set_wpakey(ic, wldp_buf); + break; + case MAC_PROP_WL_DELKEY: + err = wl_set_delkey(ic, wldp_buf); + break; + case MAC_PROP_WL_SETOPTIE: + err = wl_set_optie(ic, wldp_buf); + break; + case MAC_PROP_WL_MLME: + err = wl_set_mlme(ic, wldp_buf); + break; + case MAC_PROP_WL_LINKSTATUS: + case MAC_PROP_WL_ESS_LIST: + case MAC_PROP_WL_SUPPORTED_RATES: + case MAC_PROP_WL_RSSI: + case MAC_PROP_WL_CAPABILITY: + case MAC_PROP_WL_SCANRESULTS: + ieee80211_err("ieee80211_setprop: opmode err\n"); + err = EINVAL; + break; + default: + ieee80211_err("ieee80211_setprop: opmode not support\n"); + err = ENOTSUP; + break; + } + + IEEE80211_UNLOCK(ic); + + return (err); +} + +/* ARGSUSED */ +int +ieee80211_getprop(void *ic_arg, const char *pr_name, mac_prop_id_t wldp_pr_num, + uint_t pr_flags, uint_t wldp_length, void *wldp_buf) +{ + int err = 0; + struct ieee80211com *ic = ic_arg; + + if (wldp_length == 0) { + err = EINVAL; + return (err); + } + bzero(wldp_buf, wldp_length); + + ASSERT(ic != NULL); + IEEE80211_LOCK(ic); + + switch (wldp_pr_num) { + /* mac_prop_id */ + case MAC_PROP_WL_ESSID: + wl_get_essid(ic, wldp_buf); + break; + case MAC_PROP_WL_BSSID: + wl_get_bssid(ic, wldp_buf); + break; + case MAC_PROP_WL_PHY_CONFIG: + err = wl_get_phy(ic, wldp_buf); + break; + case MAC_PROP_WL_AUTH_MODE: + wl_get_authmode(ic, wldp_buf); + break; + case MAC_PROP_WL_ENCRYPTION: + wl_get_encrypt(ic, wldp_buf); + break; + case MAC_PROP_WL_BSSTYPE: + wl_get_bsstype(ic, wldp_buf); + break; + case MAC_PROP_WL_DESIRED_RATES: + wl_get_desrates(ic, wldp_buf); + break; + case MAC_PROP_WL_LINKSTATUS: + wl_get_linkstatus(ic, wldp_buf); + break; + case MAC_PROP_WL_ESS_LIST: + wl_get_esslist(ic, wldp_buf); + break; + case MAC_PROP_WL_SUPPORTED_RATES: + wl_get_suprates(ic, wldp_buf); + break; + case MAC_PROP_WL_RSSI: + wl_get_rssi(ic, wldp_buf); + break; + case MAC_PROP_WL_CAPABILITY: + wl_get_capability(ic, wldp_buf); + break; + case MAC_PROP_WL_WPA: + wl_get_wpa(ic, wldp_buf); + break; + case MAC_PROP_WL_SCANRESULTS: + wl_get_scanresults(ic, wldp_buf); + break; + case MAC_PROP_WL_KEY_TAB: + case MAC_PROP_WL_KEY: + case MAC_PROP_WL_DELKEY: + case MAC_PROP_WL_SETOPTIE: + case MAC_PROP_WL_MLME: + ieee80211_err("ieee80211_setprop: opmode err\n"); + err = EINVAL; + break; + default: + ieee80211_err("ieee80211_setprop: opmode not support\n"); + err = ENOTSUP; + break; + } + + IEEE80211_UNLOCK(ic); + + return (err); +} diff --git a/usr/src/uts/common/io/wpi/wpi.c b/usr/src/uts/common/io/wpi/wpi.c index 3efaf7ccad..f3e716a3be 100644 --- a/usr/src/uts/common/io/wpi/wpi.c +++ b/usr/src/uts/common/io/wpi/wpi.c @@ -269,7 +269,11 @@ static int wpi_m_multicst(void *arg, boolean_t add, const uint8_t *m); static int wpi_m_promisc(void *arg, boolean_t on); static mblk_t *wpi_m_tx(void *arg, mblk_t *mp); static void wpi_m_ioctl(void *arg, queue_t *wq, mblk_t *mp); - +static int wpi_m_setprop(void *arg, const char *pr_name, + mac_prop_id_t wldp_pr_num, uint_t wldp_length, const void *wldp_buf); +static int wpi_m_getprop(void *arg, const char *pr_name, + mac_prop_id_t wldp_pr_num, uint_t pr_flags, uint_t wldp_lenth, + void *wldp_buf); static void wpi_destroy_locks(wpi_sc_t *sc); static int wpi_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type); static void wpi_thread(wpi_sc_t *sc); @@ -358,7 +362,7 @@ _info(struct modinfo *mip) * Mac Call Back entries */ mac_callbacks_t wpi_m_callbacks = { - MC_IOCTL, + MC_IOCTL | MC_SETPROP | MC_GETPROP, wpi_m_stat, wpi_m_start, wpi_m_stop, @@ -367,7 +371,12 @@ mac_callbacks_t wpi_m_callbacks = { wpi_m_unicst, wpi_m_tx, NULL, - wpi_m_ioctl + wpi_m_ioctl, + NULL, + NULL, + NULL, + wpi_m_setprop, + wpi_m_getprop }; #ifdef DEBUG @@ -2221,6 +2230,44 @@ wpi_m_ioctl(void* arg, queue_t *wq, mblk_t *mp) } } +/* + * Callback functions for get/set properties + */ +static int +wpi_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_name, + uint_t pr_flags, uint_t wldp_length, void *wldp_buf) +{ + int err = 0; + wpi_sc_t *sc = (wpi_sc_t *)arg; + + err = ieee80211_getprop(&sc->sc_ic, pr_name, wldp_pr_name, + pr_flags, wldp_length, wldp_buf); + + return (err); +} +static int +wpi_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_name, + uint_t wldp_length, const void *wldp_buf) +{ + int err; + wpi_sc_t *sc = (wpi_sc_t *)arg; + ieee80211com_t *ic = &sc->sc_ic; + + err = ieee80211_setprop(ic, pr_name, wldp_pr_name, + wldp_length, wldp_buf); + + if (err == ENETRESET) { + if (ic->ic_des_esslen) { + (void) ieee80211_new_state(ic, + IEEE80211_S_SCAN, -1); + } + + err = 0; + } + + return (err); +} + /*ARGSUSED*/ static int wpi_m_stat(void *arg, uint_t stat, uint64_t *val) diff --git a/usr/src/uts/common/sys/mac.h b/usr/src/uts/common/sys/mac.h index bc930dfce2..ff57a7a1d4 100644 --- a/usr/src/uts/common/sys/mac.h +++ b/usr/src/uts/common/sys/mac.h @@ -131,6 +131,28 @@ typedef enum { MAC_PROP_EN_10HDX_CAP, MAC_PROP_ADV_100T4_CAP, MAC_PROP_EN_100T4_CAP, + MAC_PROP_WL_ESSID, + MAC_PROP_WL_BSSID, + MAC_PROP_WL_BSSTYPE, + MAC_PROP_WL_LINKSTATUS, + MAC_PROP_WL_DESIRED_RATES, + MAC_PROP_WL_SUPPORTED_RATES, + MAC_PROP_WL_AUTH_MODE, + MAC_PROP_WL_ENCRYPTION, + MAC_PROP_WL_RSSI, + MAC_PROP_WL_PHY_CONFIG, + MAC_PROP_WL_CAPABILITY, + MAC_PROP_WL_WPA, + MAC_PROP_WL_SCANRESULTS, + MAC_PROP_WL_POWER_MODE, + MAC_PROP_WL_RADIO, + MAC_PROP_WL_ESS_LIST, + MAC_PROP_WL_KEY_TAB, + MAC_PROP_WL_CREATE_IBSS, + MAC_PROP_WL_SETOPTIE, + MAC_PROP_WL_DELKEY, + MAC_PROP_WL_KEY, + MAC_PROP_WL_MLME, MAC_PROP_PRIVATE = -1 } mac_prop_id_t; diff --git a/usr/src/uts/common/sys/net80211.h b/usr/src/uts/common/sys/net80211.h index 39d6abdf6f..09619aaa77 100644 --- a/usr/src/uts/common/sys/net80211.h +++ b/usr/src/uts/common/sys/net80211.h @@ -38,8 +38,6 @@ #ifndef _SYS_NET80211_H #define _SYS_NET80211_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/mac.h> #include <sys/ethernet.h> #include <sys/net80211_proto.h> @@ -538,6 +536,10 @@ void ieee80211_stop_watchdog(ieee80211com_t *); void *ieee80211_malloc(size_t); void ieee80211_free(void *); +int ieee80211_setprop(void *, const char *, mac_prop_id_t, uint_t, + const void *); +int ieee80211_getprop(void *, const char *, mac_prop_id_t, uint_t, uint_t, + void *); #ifdef __cplusplus } |