summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorzf162725 <none@none>2007-04-27 09:21:03 -0700
committerzf162725 <none@none>2007-04-27 09:21:03 -0700
commita399b7655a1d835aa8606c2b29e4e777baac8635 (patch)
treeded6ac776bafd9c346919868094dcbb1f8861bef /usr/src/lib
parent2d52664353b360bce2f87239f9d1342d66b7c9cd (diff)
downloadillumos-joyent-a399b7655a1d835aa8606c2b29e4e777baac8635.tar.gz
PSARC 2006/046 Wireless WPA Supplicant
PSARC 2007/223 Wireless WPA Supplicant Addendum 6363273 Need access to WPA/TKIP functionality
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libdladm/Makefile.com2
-rw-r--r--usr/src/lib/libdladm/common/libdllink.h1
-rw-r--r--usr/src/lib/libdladm/common/libdlwlan.c674
-rw-r--r--usr/src/lib/libdladm/common/libdlwlan.h66
-rw-r--r--usr/src/lib/libdladm/common/mapfile-vers6
-rw-r--r--usr/src/lib/libdladm/common/secobj.c7
-rw-r--r--usr/src/lib/libsecdb/auth_attr.txt1
-rw-r--r--usr/src/lib/libsecdb/help/auths/Makefile1
-rw-r--r--usr/src/lib/libsecdb/help/auths/SmfWpaStates.html44
-rw-r--r--usr/src/lib/libsecdb/prof_attr.txt2
-rw-r--r--usr/src/lib/libsecdb/user_attr.txt8
11 files changed, 775 insertions, 37 deletions
diff --git a/usr/src/lib/libdladm/Makefile.com b/usr/src/lib/libdladm/Makefile.com
index a3da9a4770..6e17165bd9 100644
--- a/usr/src/lib/libdladm/Makefile.com
+++ b/usr/src/lib/libdladm/Makefile.com
@@ -35,7 +35,7 @@ include ../../Makefile.lib
include ../../Makefile.rootfs
LIBS = $(DYNLIB) $(LINTLIB)
-LDLIBS += -ldevinfo -ldlpi -lc -linetutil -lsocket
+LDLIBS += -ldevinfo -ldlpi -lc -linetutil -lsocket -lscf
SRCDIR = ../common
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
diff --git a/usr/src/lib/libdladm/common/libdllink.h b/usr/src/lib/libdladm/common/libdllink.h
index 2f5bfd145f..12327456a5 100644
--- a/usr/src/lib/libdladm/common/libdllink.h
+++ b/usr/src/lib/libdladm/common/libdllink.h
@@ -64,6 +64,7 @@ typedef struct dladm_attr {
#define DLADM_PROP_VAL_MAX 25
#define DLADM_SECOBJ_CLASS_WEP 0
+#define DLADM_SECOBJ_CLASS_WPA 1
typedef int dladm_secobj_class_t;
typedef void (dladm_walkcb_t)(void *, const char *);
diff --git a/usr/src/lib/libdladm/common/libdlwlan.c b/usr/src/lib/libdladm/common/libdlwlan.c
index d7608eede1..6693a614d5 100644
--- a/usr/src/lib/libdladm/common/libdlwlan.c
+++ b/usr/src/lib/libdladm/common/libdlwlan.c
@@ -37,9 +37,10 @@
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
+#include <libscf.h>
#include <libdlwlan.h>
#include <libdlwlan_impl.h>
-#include <inet/wifi_ioctl.h>
+#include <net/wpa.h>
typedef struct val_desc {
char *vd_name;
@@ -63,6 +64,9 @@ typedef struct prop_desc {
wl_pd_checkf_t *pd_check;
} prop_desc_t;
+static int wpa_instance_create(const char *, void *);
+static int wpa_instance_delete(const char *);
+
static int do_get_bsstype(int, wldp_t *);
static int do_get_essid(int, wldp_t *);
static int do_get_bssid(int, wldp_t *);
@@ -76,13 +80,15 @@ static int do_get_phyconf(int, wldp_t *);
static int do_get_powermode(int, wldp_t *);
static int do_get_radio(int, wldp_t *);
static int do_get_mode(int, wldp_t *);
+static int do_get_capability(int, wldp_t *);
+static int do_get_wpamode(int, wldp_t *);
static int do_set_bsstype(int, wldp_t *, dladm_wlan_bsstype_t *);
static int do_set_authmode(int, wldp_t *, dladm_wlan_auth_t *);
static int do_set_encryption(int, wldp_t *, dladm_wlan_secmode_t *);
static int do_set_essid(int, wldp_t *, dladm_wlan_essid_t *);
static int do_set_createibss(int, wldp_t *, boolean_t *);
-static int do_set_wepkey(int, wldp_t *, dladm_wlan_wepkey_t *, uint_t);
+static int do_set_key(int, wldp_t *, dladm_wlan_key_t *, uint_t);
static int do_set_rate(int, wldp_t *, dladm_wlan_rates_t *);
static int do_set_powermode(int, wldp_t *, dladm_wlan_powermode_t *);
static int do_set_radio(int, wldp_t *, dladm_wlan_radio_t *);
@@ -90,7 +96,7 @@ static int do_set_channel(int, wldp_t *, dladm_wlan_channel_t *);
static int open_link(const char *);
static int do_scan(int, wldp_t *);
-static int do_disconnect(int, wldp_t *);
+static int do_disconnect(const char *, int, wldp_t *);
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 **);
static void generate_essid(dladm_wlan_essid_t *);
@@ -110,7 +116,8 @@ static val_desc_t linkstatus_vals[] = {
static val_desc_t secmode_vals[] = {
{ "none", DLADM_WLAN_SECMODE_NONE },
- { "wep", DLADM_WLAN_SECMODE_WEP }
+ { "wep", DLADM_WLAN_SECMODE_WEP },
+ { "wpa", DLADM_WLAN_SECMODE_WPA }
};
static val_desc_t strength_vals[] = {
@@ -293,6 +300,8 @@ fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp)
attrp->wa_secmode = (wlp->wl_ess_conf_wepenabled ==
WL_ENC_WEP ? DLADM_WLAN_SECMODE_WEP : DLADM_WLAN_SECMODE_NONE);
+ if (wlp->wl_ess_conf_reserved[0] > 0)
+ attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA;
attrp->wa_valid |= DLADM_WLAN_ATTR_SECMODE;
attrp->wa_bsstype = (wlp->wl_ess_conf_bsstype == WL_BSS_BSS ?
@@ -353,6 +362,11 @@ dladm_wlan_scan(const char *link, void *arg,
goto done;
}
+ if (func == NULL) {
+ status = DLADM_STATUS_OK;
+ goto done;
+ }
+
if (do_get_esslist(fd, gbuf) < 0) {
status = DLADM_STATUS_FAILED;
goto done;
@@ -373,7 +387,7 @@ dladm_wlan_scan(const char *link, void *arg,
goto done;
}
if (IS_CONNECTED(gbuf))
- (void) do_disconnect(fd, gbuf);
+ (void) do_disconnect(link, fd, gbuf);
}
status = DLADM_STATUS_OK;
@@ -490,17 +504,20 @@ append:
return (B_TRUE);
}
+#define IEEE80211_C_WPA 0x01800000
+
static dladm_status_t
-do_connect(int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
+do_connect(const char *link, int fd, wldp_t *gbuf, 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;
dladm_wlan_bsstype_t bsstype;
dladm_wlan_essid_t essid;
- boolean_t essid_valid = B_FALSE;
+ boolean_t essid_valid = B_FALSE;
dladm_wlan_channel_t channel;
- hrtime_t start;
+ hrtime_t start;
+ wl_capability_t *caps;
if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) {
channel = attrp->wa_channel;
@@ -529,8 +546,16 @@ do_connect(int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
if (secmode == DLADM_WLAN_SECMODE_WEP) {
if (keys == NULL || key_count == 0 || key_count > MAX_NWEPKEYS)
return (DLADM_STATUS_BADARG);
- if (do_set_wepkey(fd, gbuf, keys, key_count) < 0)
+ if (do_set_key(fd, gbuf, keys, key_count) < 0)
+ goto fail;
+ } else if (secmode == DLADM_WLAN_SECMODE_WPA) {
+ if (keys == NULL || key_count == 0 || key_count > MAX_NWEPKEYS)
+ return (DLADM_STATUS_BADARG);
+ if (do_get_capability(fd, gbuf) < 0)
goto fail;
+ caps = (wl_capability_t *)(gbuf->wldp_buf);
+ if ((caps->caps & IEEE80211_C_WPA) == 0)
+ return (DLADM_STATUS_NOTSUP);
}
if (create_ibss) {
@@ -556,6 +581,13 @@ do_connect(int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
if (do_set_essid(fd, gbuf, &essid) < 0)
goto fail;
+ /*
+ * Because wpa daemon needs getting essid from driver,
+ * we need call do_set_essid() first, then call wpa_instance_create().
+ */
+ if (secmode == DLADM_WLAN_SECMODE_WPA && keys != NULL)
+ (void) wpa_instance_create(link, keys);
+
start = gethrtime();
for (;;) {
if (do_get_linkstatus(fd, gbuf) < 0)
@@ -614,7 +646,7 @@ dladm_wlan_connect(const char *link, 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(fd, gbuf, attrp,
+ status = do_connect(link, fd, gbuf, attrp,
create_ibss, keys, key_count, timeout);
goto done;
}
@@ -632,7 +664,7 @@ dladm_wlan_connect(const char *link, dladm_wlan_attr_t *attrp,
status = DLADM_STATUS_NOTFOUND;
goto done;
}
- status = do_connect(fd, gbuf, attrp, create_ibss,
+ status = do_connect(link, fd, gbuf, attrp, create_ibss,
keys, key_count, timeout);
goto done;
}
@@ -654,7 +686,7 @@ dladm_wlan_connect(const char *link, dladm_wlan_attr_t *attrp,
for (i = 0; i < state.cs_count; i++) {
dladm_wlan_attr_t *ap = wl_list[i];
- status = do_connect(fd, gbuf, ap, create_ibss, keys,
+ status = do_connect(link, fd, gbuf, ap, create_ibss, keys,
key_count, timeout);
if (status == DLADM_STATUS_OK)
break;
@@ -662,15 +694,15 @@ dladm_wlan_connect(const char *link, dladm_wlan_attr_t *attrp,
if (!set_authmode) {
ap->wa_auth = DLADM_WLAN_AUTH_SHARED;
ap->wa_valid |= DLADM_WLAN_ATTR_AUTH;
- status = do_connect(fd, gbuf, ap, create_ibss, keys,
- key_count, timeout);
+ status = do_connect(link, fd, gbuf, 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(fd, gbuf);
+ (void) do_disconnect(link, fd, gbuf);
while (state.cs_list != NULL) {
nodep = state.cs_list;
@@ -708,7 +740,7 @@ dladm_wlan_disconnect(const char *link)
goto done;
}
- if (do_disconnect(fd, gbuf) < 0) {
+ if (do_disconnect(link, fd, gbuf) < 0) {
status = DLADM_STATUS_FAILED;
goto done;
}
@@ -834,10 +866,9 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS;
if (!IS_CONNECTED(gbuf)) {
attrp->la_status = DLADM_WLAN_LINKSTATUS_DISCONNECTED;
- status = DLADM_STATUS_OK;
- goto done;
+ } else {
+ attrp->la_status = DLADM_WLAN_LINKSTATUS_CONNECTED;
}
- attrp->la_status = DLADM_WLAN_LINKSTATUS_CONNECTED;
if (do_get_essid(fd, gbuf) < 0)
goto done;
@@ -856,6 +887,12 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
wl_attrp->wa_valid |= DLADM_WLAN_ATTR_BSSID;
+ if (attrp->la_status == DLADM_WLAN_LINKSTATUS_DISCONNECTED) {
+ attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN;
+ status = DLADM_STATUS_OK;
+ goto done;
+ }
+
if (do_get_encryption(fd, gbuf) < 0)
goto done;
@@ -869,6 +906,9 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
case WL_ENC_WEP:
wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WEP;
break;
+ case WL_ENC_WPA:
+ wl_attrp->wa_secmode = DLADM_WLAN_SECMODE_WPA;
+ break;
default:
wl_attrp->wa_valid &= ~DLADM_WLAN_ATTR_SECMODE;
break;
@@ -1445,8 +1485,12 @@ do_scan(int fd, wldp_t *gbuf)
}
static int
-do_disconnect(int fd, wldp_t *gbuf)
+do_disconnect(const char *link, int fd, wldp_t *gbuf)
{
+ if (do_get_wpamode(fd, gbuf) == 0 && ((wl_wpa_t *)(gbuf->
+ wldp_buf))->wpa_flag > 0)
+ (void) wpa_instance_delete(link);
+
return (do_cmd_ioctl(fd, gbuf, WL_DISASSOCIATE));
}
@@ -1695,6 +1739,8 @@ do_set_encryption(int fd, wldp_t *gbuf, dladm_wlan_secmode_t *secmode)
case DLADM_WLAN_SECMODE_WEP:
encryption = WL_ENC_WEP;
break;
+ case DLADM_WLAN_SECMODE_WPA:
+ return (0);
default:
return (-1);
}
@@ -1703,13 +1749,13 @@ do_set_encryption(int fd, wldp_t *gbuf, dladm_wlan_secmode_t *secmode)
}
static int
-do_set_wepkey(int fd, wldp_t *gbuf, dladm_wlan_wepkey_t *keys,
+do_set_key(int fd, wldp_t *gbuf, dladm_wlan_key_t *keys,
uint_t key_count)
{
int i;
wl_wep_key_t *wkp;
wl_wep_key_tab_t wepkey_tab;
- dladm_wlan_wepkey_t *kp;
+ dladm_wlan_key_t *kp;
if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL)
return (-1);
@@ -1935,3 +1981,587 @@ generate_essid(dladm_wlan_essid_t *essid)
(void) snprintf(essid->we_bytes, DLADM_WLAN_MAX_ESSID_LEN, "%d",
random());
}
+
+static int
+do_get_capability(int fd, wldp_t *gbuf)
+{
+ return (do_get_ioctl(fd, gbuf, WL_CAPABILITY));
+}
+
+static int
+do_get_wpamode(int fd, wldp_t *gbuf)
+{
+ return (do_get_ioctl(fd, gbuf, WL_WPA));
+}
+
+static dladm_status_t
+ioctl_get(const char *link, int id, void *gbuf)
+{
+ int fd;
+
+ if ((fd = open_link(link)) < 0)
+ return (DLADM_STATUS_LINKINVAL);
+ (void) do_get_ioctl(fd, gbuf, id);
+
+ (void) close(fd);
+ return (dladm_wlan_wlresult2status(gbuf));
+}
+
+static dladm_status_t
+ioctl_set(const char *link, int id, void *buf, uint_t buflen)
+{
+ int fd;
+ wldp_t *gbuf;
+ dladm_status_t status;
+
+ if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ if ((fd = open_link(link)) < 0)
+ return (DLADM_STATUS_LINKINVAL);
+ (void) do_set_ioctl(fd, gbuf, id, buf, buflen);
+
+ (void) close(fd);
+ status = dladm_wlan_wlresult2status(gbuf);
+ free(gbuf);
+
+ return (status);
+}
+
+dladm_status_t
+dladm_wlan_wpa_get_sr(const char *link, 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)
+ return (DLADM_STATUS_NOMEM);
+
+ status = ioctl_get(link, WL_SCANRESULTS, gbuf);
+
+ 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,
+ DLADM_WLAN_BSSID_LEN);
+ sr[i].we_ssid_len = es->ess[i].ssid_len;
+ (void) memcpy(sr[i].we_ssid.we_bytes, es->ess[i].ssid,
+ es->ess[i].ssid_len);
+ sr[i].we_wpa_ie_len = es->ess[i].wpa_ie_len;
+ (void) memcpy(sr[i].we_wpa_ie, es->ess[i].wpa_ie,
+ es->ess[i].wpa_ie_len);
+ sr[i].we_freq = es->ess[i].freq;
+ }
+ *estot = n;
+ }
+
+ free(gbuf);
+ return (status);
+}
+
+dladm_status_t
+dladm_wlan_wpa_set_ie(const char *link, uint8_t *wpa_ie,
+ uint_t wpa_ie_len)
+{
+ wl_wpa_ie_t *ie;
+ uint_t len;
+ dladm_status_t status;
+
+ if (wpa_ie_len > DLADM_WLAN_MAX_WPA_IE_LEN)
+ return (DLADM_STATUS_BADARG);
+ len = sizeof (wl_wpa_ie_t) + wpa_ie_len;
+ ie = malloc(len);
+ if (ie == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ (void) memset(ie, 0, len);
+ ie->wpa_ie_len = wpa_ie_len;
+ (void) memcpy(ie->wpa_ie, wpa_ie, wpa_ie_len);
+
+ status = ioctl_set(link, WL_SETOPTIE, ie, len);
+ free(ie);
+
+ return (status);
+}
+
+dladm_status_t
+dladm_wlan_wpa_set_wpa(const char *link, boolean_t flag)
+{
+ wl_wpa_t wpa;
+
+ wpa.wpa_flag = flag;
+ return (ioctl_set(link, WL_WPA, &wpa, sizeof (wl_wpa_t)));
+}
+
+dladm_status_t
+dladm_wlan_wpa_del_key(const char *link, uint_t key_idx,
+ const dladm_wlan_bssid_t *addr)
+{
+ wl_del_key_t wk;
+
+ wk.idk_keyix = key_idx;
+ if (addr != NULL)
+ (void) memcpy((char *)wk.idk_macaddr, addr->wb_bytes,
+ DLADM_WLAN_BSSID_LEN);
+
+ return (ioctl_set(link, WL_DELKEY, &wk, sizeof (wl_del_key_t)));
+}
+
+dladm_status_t
+dladm_wlan_wpa_set_key(const char *link, dladm_wlan_cipher_t cipher,
+ const dladm_wlan_bssid_t *addr, boolean_t set_tx, uint64_t seq,
+ uint_t key_idx, uint8_t *key, uint_t key_len)
+{
+ wl_key_t wk;
+
+ (void) memset(&wk, 0, sizeof (wl_key_t));
+ switch (cipher) {
+ case DLADM_WLAN_CIPHER_WEP:
+ wk.ik_type = IEEE80211_CIPHER_WEP;
+ break;
+ case DLADM_WLAN_CIPHER_TKIP:
+ wk.ik_type = IEEE80211_CIPHER_TKIP;
+ break;
+ case DLADM_WLAN_CIPHER_AES_OCB:
+ wk.ik_type = IEEE80211_CIPHER_AES_OCB;
+ break;
+ case DLADM_WLAN_CIPHER_AES_CCM:
+ wk.ik_type = IEEE80211_CIPHER_AES_CCM;
+ break;
+ case DLADM_WLAN_CIPHER_CKIP:
+ wk.ik_type = IEEE80211_CIPHER_CKIP;
+ break;
+ case DLADM_WLAN_CIPHER_NONE:
+ wk.ik_type = IEEE80211_CIPHER_NONE;
+ break;
+ default:
+ return (DLADM_STATUS_BADARG);
+ }
+ wk.ik_flags = IEEE80211_KEY_RECV;
+ if (set_tx) {
+ wk.ik_flags |= IEEE80211_KEY_XMIT | IEEE80211_KEY_DEFAULT;
+ (void) memcpy(wk.ik_macaddr, addr->wb_bytes,
+ DLADM_WLAN_BSSID_LEN);
+ } else
+ (void) memset(wk.ik_macaddr, 0, DLADM_WLAN_BSSID_LEN);
+ wk.ik_keyix = key_idx;
+ wk.ik_keylen = key_len;
+ (void) memcpy(&wk.ik_keyrsc, &seq, 6); /* only use 48-bit of seq */
+ (void) memcpy(wk.ik_keydata, key, key_len);
+
+ return (ioctl_set(link, WL_KEY, &wk, sizeof (wl_key_t)));
+}
+
+dladm_status_t
+dladm_wlan_wpa_set_mlme(const char *link, dladm_wlan_mlme_op_t op,
+ dladm_wlan_reason_t reason, dladm_wlan_bssid_t *bssid)
+{
+ wl_mlme_t mlme;
+
+ (void) memset(&mlme, 0, sizeof (wl_mlme_t));
+ switch (op) {
+ case DLADM_WLAN_MLME_ASSOC:
+ mlme.im_op = IEEE80211_MLME_ASSOC;
+ break;
+ case DLADM_WLAN_MLME_DISASSOC:
+ mlme.im_op = IEEE80211_MLME_DISASSOC;
+ break;
+ default:
+ return (DLADM_STATUS_BADARG);
+ }
+ mlme.im_reason = reason;
+ if (bssid != NULL)
+ (void) memcpy(mlme.im_macaddr, bssid->wb_bytes,
+ DLADM_WLAN_BSSID_LEN);
+
+ return (ioctl_set(link, WL_MLME, &mlme, sizeof (wl_mlme_t)));
+}
+
+/*
+ * routines of create instance
+ */
+static scf_propertygroup_t *
+add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance,
+ const char *pg_name, const char *pg_type)
+{
+ scf_propertygroup_t *pg;
+
+ pg = scf_pg_create(handle);
+ if (pg == NULL)
+ return (NULL);
+
+ if (scf_instance_add_pg(instance, pg_name, pg_type, 0, pg) != 0) {
+ scf_pg_destroy(pg);
+ return (NULL);
+ }
+
+ return (pg);
+}
+
+static int
+add_new_property(scf_handle_t *handle, const char *prop_name,
+ scf_type_t type, const char *val, scf_transaction_t *tx)
+{
+ scf_value_t *value = NULL;
+ scf_transaction_entry_t *entry = NULL;
+
+ entry = scf_entry_create(handle);
+ if (entry == NULL)
+ goto out;
+
+ value = scf_value_create(handle);
+ if (value == NULL)
+ goto out;
+
+ if (scf_transaction_property_new(tx, entry, prop_name, type) != 0)
+ goto out;
+
+ if (scf_value_set_from_string(value, type, val) != 0)
+ goto out;
+
+ if (scf_entry_add_value(entry, value) != 0)
+ goto out;
+
+ return (DLADM_WLAN_SVC_SUCCESS);
+
+out:
+ if (value != NULL)
+ scf_value_destroy(value);
+ if (entry != NULL)
+ scf_entry_destroy(entry);
+
+ return (DLADM_WLAN_SVC_FAILURE);
+}
+
+/*
+ * DLADM_WLAN_SVC_APP_FAILURE means allocate buffer failed.
+ */
+static int
+add_pg_method(scf_handle_t *handle, scf_instance_t *instance,
+ const char *pg_name, const char *flags)
+{
+ int rv, size;
+ int status = DLADM_WLAN_SVC_FAILURE;
+ char *command = NULL;
+ scf_transaction_t *tran = NULL;
+ scf_propertygroup_t *pg;
+
+ pg = add_property_group_to_instance(handle, instance,
+ pg_name, SCF_GROUP_METHOD);
+ if (pg == NULL)
+ goto out;
+
+ tran = scf_transaction_create(handle);
+ if (tran == NULL)
+ goto out;
+
+ size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1;
+ command = malloc(size);
+ if (command == NULL) {
+ status = DLADM_WLAN_SVC_APP_FAILURE;
+ goto out;
+ }
+ (void) snprintf(command, size, "%s %s", SVC_METHOD, flags);
+
+ do {
+ if (scf_transaction_start(tran, pg) != 0)
+ goto out;
+
+ if (add_new_property(handle, SCF_PROPERTY_EXEC,
+ SCF_TYPE_ASTRING, command, tran) !=
+ DLADM_WLAN_SVC_SUCCESS) {
+ goto out;
+ }
+
+ rv = scf_transaction_commit(tran);
+ switch (rv) {
+ case 1:
+ status = DLADM_WLAN_SVC_SUCCESS;
+ goto out;
+ case 0:
+ scf_transaction_destroy_children(tran);
+ if (scf_pg_update(pg) == -1) {
+ goto out;
+ }
+ break;
+ case -1:
+ default:
+ goto out;
+ }
+ } while (rv == 0);
+
+out:
+ if (tran != NULL) {
+ scf_transaction_destroy_children(tran);
+ scf_transaction_destroy(tran);
+ }
+
+ if (pg != NULL)
+ scf_pg_destroy(pg);
+
+ if (command != NULL)
+ free(command);
+
+ return (status);
+}
+
+static int
+do_create_instance(scf_handle_t *handle, scf_service_t *svc,
+ const char *instance_name, const char *command)
+{
+ int status = DLADM_WLAN_SVC_FAILURE;
+ char *buf;
+ ssize_t max_fmri_len;
+ scf_instance_t *instance;
+
+ instance = scf_instance_create(handle);
+ if (instance == NULL)
+ goto out;
+
+ if (scf_service_add_instance(svc, instance_name, instance) != 0) {
+ if (scf_error() == SCF_ERROR_EXISTS)
+ /* Let the caller deal with the duplicate instance */
+ status = DLADM_WLAN_SVC_INSTANCE_EXISTS;
+ goto out;
+ }
+
+ if (add_pg_method(handle, instance, "start",
+ command) != DLADM_WLAN_SVC_SUCCESS) {
+ goto out;
+ }
+
+ /* enabling the instance */
+ max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
+ if ((buf = malloc(max_fmri_len + 1)) == NULL)
+ goto out;
+
+ if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) {
+ if ((smf_disable_instance(buf, 0) != 0) ||
+ (smf_enable_instance(buf, SMF_TEMPORARY) != 0)) {
+ goto out;
+ }
+ status = DLADM_WLAN_SVC_SUCCESS;
+ }
+
+out:
+ if (instance != NULL)
+ scf_instance_destroy(instance);
+ return (status);
+}
+
+static int
+create_instance(const char *instance_name, const char *command)
+{
+ int status = DLADM_WLAN_SVC_FAILURE;
+ scf_service_t *svc = NULL;
+ scf_handle_t *handle = NULL;
+
+ handle = scf_handle_create(SCF_VERSION);
+ if (handle == NULL)
+ goto out;
+
+ if (scf_handle_bind(handle) == -1)
+ goto out;
+
+ if ((svc = scf_service_create(handle)) == NULL)
+ goto out;
+
+ if (scf_handle_decode_fmri(handle, SERVICE_NAME, NULL, svc,
+ NULL, NULL, NULL, SCF_DECODE_FMRI_EXACT) != 0)
+ goto out;
+
+ status = do_create_instance(handle, svc, instance_name, command);
+
+out:
+ if (svc != NULL)
+ scf_service_destroy(svc);
+
+ if (handle != NULL) {
+ (void) scf_handle_unbind(handle);
+ scf_handle_destroy(handle);
+ }
+
+ return (status);
+}
+
+/*
+ * routines of delete instance
+ */
+#define DEFAULT_TIMEOUT 60000000
+#define INIT_WAIT_USECS 50000
+
+static void
+wait_until_disabled(scf_handle_t *handle, char *fmri)
+{
+ char *state;
+ useconds_t max;
+ useconds_t usecs;
+ uint64_t *cp = NULL;
+ scf_simple_prop_t *sp = NULL;
+
+ max = DEFAULT_TIMEOUT;
+
+ if (((sp = scf_simple_prop_get(handle, fmri, "stop",
+ SCF_PROPERTY_TIMEOUT)) != NULL) &&
+ ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0))
+ max = (*cp) * 1000000; /* convert to usecs */
+
+ if (sp != NULL)
+ scf_simple_prop_free(sp);
+
+ for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) {
+ /* incremental wait */
+ usecs *= 2;
+ usecs = (usecs > max) ? max : usecs;
+
+ (void) usleep(usecs);
+
+ /* Check state after the wait */
+ if ((state = smf_get_state(fmri)) != NULL) {
+ if (strcmp(state, "disabled") == 0)
+ return;
+ }
+ }
+}
+
+static int
+delete_instance(const char *instance_name)
+{
+ int status = DLADM_WLAN_SVC_FAILURE;
+ char *buf;
+ ssize_t max_fmri_len;
+ scf_scope_t *scope = NULL;
+ scf_service_t *svc = NULL;
+ scf_handle_t *handle = NULL;
+ scf_instance_t *instance;
+
+ handle = scf_handle_create(SCF_VERSION);
+ if (handle == NULL)
+ goto out;
+
+ if (scf_handle_bind(handle) == -1)
+ goto out;
+
+ if ((scope = scf_scope_create(handle)) == NULL)
+ goto out;
+
+ if ((svc = scf_service_create(handle)) == NULL)
+ goto out;
+
+ if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1)
+ goto out;
+
+ if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0)
+ goto out;
+
+ instance = scf_instance_create(handle);
+ if (instance == NULL)
+ goto out;
+
+ if (scf_service_get_instance(svc, instance_name, instance) != 0) {
+ scf_error_t scf_errnum = scf_error();
+
+ if (scf_errnum == SCF_ERROR_NOT_FOUND)
+ status = DLADM_WLAN_SVC_SUCCESS;
+
+ scf_instance_destroy(instance);
+ goto out;
+ }
+
+ max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
+ if ((buf = malloc(max_fmri_len + 1)) == NULL) {
+ scf_instance_destroy(instance);
+ goto out;
+ }
+
+ if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) {
+ char *state;
+
+ state = smf_get_state(buf);
+ if (state && (strcmp(state, SCF_STATE_STRING_ONLINE) == 0 ||
+ strcmp(state, SCF_STATE_STRING_DEGRADED) == 0)) {
+ if (smf_disable_instance(buf, 0) == 0) {
+ /*
+ * Wait for some time till timeout to avoid
+ * a race with scf_instance_delete() below.
+ */
+ wait_until_disabled(handle, buf);
+ }
+ }
+ }
+
+ if (scf_instance_delete(instance) != 0) {
+ scf_instance_destroy(instance);
+ goto out;
+ }
+
+ scf_instance_destroy(instance);
+
+ status = DLADM_WLAN_SVC_SUCCESS;
+
+out:
+ if (svc != NULL)
+ scf_service_destroy(svc);
+
+ if (scope != NULL)
+ scf_scope_destroy(scope);
+
+ if (handle != NULL) {
+ (void) scf_handle_unbind(handle);
+ scf_handle_destroy(handle);
+ }
+
+ return (status);
+}
+
+/*
+ * DLADM_WLAN_SVC_APP_FAILURE means allocate buffer failed.
+ */
+static int
+wpa_instance_create(const char *instance_name, void *key)
+{
+ int status = DLADM_WLAN_SVC_FAILURE;
+ char *command = NULL;
+ char *wk_name = ((dladm_wlan_key_t *)key)->wk_name;
+ int size;
+
+ size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1;
+ command = malloc(size);
+ if (command == NULL) {
+ status = DLADM_WLAN_SVC_APP_FAILURE;
+ goto out;
+ }
+ (void) snprintf(command, size, "-i %s -k %s", instance_name, wk_name);
+
+ status = create_instance(instance_name, command);
+ if (status == DLADM_WLAN_SVC_INSTANCE_EXISTS) {
+ /*
+ * Delete the existing instance and create a new instance
+ * with the supplied arguments.
+ */
+ if ((status = delete_instance(instance_name)) ==
+ DLADM_WLAN_SVC_SUCCESS) {
+ status = create_instance(instance_name, command);
+ }
+ }
+
+out:
+ if (command != NULL)
+ free(command);
+
+ return (status);
+}
+
+static int
+wpa_instance_delete(const char *instance_name)
+{
+ int status;
+
+ status = delete_instance(instance_name);
+
+ return (status);
+}
diff --git a/usr/src/lib/libdladm/common/libdlwlan.h b/usr/src/lib/libdladm/common/libdlwlan.h
index ccb2e7fc22..b1729ae658 100644
--- a/usr/src/lib/libdladm/common/libdlwlan.h
+++ b/usr/src/lib/libdladm/common/libdlwlan.h
@@ -49,6 +49,8 @@ extern "C" {
#define DLADM_WLAN_MAX_ESSID_LEN 32 /* per 802.11 spec */
#define DLADM_WLAN_BSSID_LEN 6 /* per 802.11 spec */
+#define DLADM_WLAN_WPA_KEY_LEN 32 /* per 802.11i spec */
+#define DLADM_WLAN_MAX_WPA_IE_LEN 40 /* per 802.11i spec */
#define DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT 10
#define DLADM_WLAN_CONNECT_CREATEIBSS 0x00000001
@@ -62,9 +64,38 @@ typedef struct dladm_wlan_bssid {
uint8_t wb_bytes[DLADM_WLAN_BSSID_LEN];
} dladm_wlan_bssid_t;
+typedef struct dladm_wlan_ess {
+ dladm_wlan_bssid_t we_bssid;
+ dladm_wlan_essid_t we_ssid;
+ uint_t we_ssid_len;
+ uint8_t we_wpa_ie[DLADM_WLAN_MAX_WPA_IE_LEN];
+ uint_t we_wpa_ie_len;
+ int we_freq;
+} dladm_wlan_ess_t;
+
+typedef enum {
+ DLADM_WLAN_CIPHER_WEP = 0,
+ DLADM_WLAN_CIPHER_TKIP,
+ DLADM_WLAN_CIPHER_AES_OCB,
+ DLADM_WLAN_CIPHER_AES_CCM,
+ DLADM_WLAN_CIPHER_CKIP,
+ DLADM_WLAN_CIPHER_NONE
+} dladm_wlan_cipher_t;
+
+typedef enum {
+ DLADM_WLAN_MLME_ASSOC = 1, /* associate station */
+ DLADM_WLAN_MLME_DISASSOC = 2 /* disassociate station */
+} dladm_wlan_mlme_op_t;
+
+typedef enum {
+ DLADM_WLAN_REASON_UNSPECIFIED = 1,
+ DLADM_WLAN_REASON_DISASSOC_LEAVING = 5
+} dladm_wlan_reason_t;
+
typedef enum {
DLADM_WLAN_SECMODE_NONE = 1,
- DLADM_WLAN_SECMODE_WEP
+ DLADM_WLAN_SECMODE_WEP,
+ DLADM_WLAN_SECMODE_WPA
} dladm_wlan_secmode_t;
typedef enum {
@@ -101,6 +132,13 @@ typedef enum {
typedef uint32_t dladm_wlan_speed_t;
typedef uint32_t dladm_wlan_channel_t;
+typedef enum {
+ DLADM_WLAN_SVC_SUCCESS,
+ DLADM_WLAN_SVC_FAILURE,
+ DLADM_WLAN_SVC_APP_FAILURE,
+ DLADM_WLAN_SVC_INSTANCE_EXISTS
+} dladm_wlan_svc_status_t;
+
enum {
DLADM_WLAN_ATTR_ESSID = 0x00000001,
DLADM_WLAN_ATTR_BSSID = 0x00000002,
@@ -137,15 +175,16 @@ typedef struct dladm_wlan_linkattr {
#define DLADM_WLAN_WEPKEY64_LEN 5 /* per WEP spec */
#define DLADM_WLAN_WEPKEY128_LEN 13 /* per WEP spec */
-#define DLADM_WLAN_MAX_WEPKEY_LEN 13 /* per WEP spec */
+#define DLADM_WLAN_MAX_KEY_LEN 64 /* per WEP/WPA spec */
#define DLADM_WLAN_MAX_WEPKEYS 4 /* MAX_NWEPKEYS */
-#define DLADM_WLAN_MAX_WEPKEYNAME_LEN 64
-typedef struct dladm_wlan_wepkey {
+#define DLADM_WLAN_MAX_KEYNAME_LEN 64
+typedef struct dladm_wlan_key {
uint_t wk_idx;
uint_t wk_len;
- uint8_t wk_val[DLADM_WLAN_MAX_WEPKEY_LEN];
- char wk_name[DLADM_WLAN_MAX_WEPKEYNAME_LEN];
-} dladm_wlan_wepkey_t;
+ uint8_t wk_val[DLADM_WLAN_MAX_KEY_LEN];
+ char wk_name[DLADM_WLAN_MAX_KEYNAME_LEN];
+ uint_t wk_class;
+} dladm_wlan_key_t;
extern dladm_status_t dladm_wlan_scan(const char *, void *,
boolean_t (*)(void *, dladm_wlan_attr_t *));
@@ -163,6 +202,19 @@ extern dladm_status_t dladm_wlan_walk_prop(const char *, void *,
boolean_t (*)(void *, const char *));
extern dladm_status_t dladm_wlan_get_prop(const char *, dladm_prop_type_t,
const char *, char **, uint_t *);
+/* WPA support routines */
+extern dladm_status_t dladm_wlan_wpa_get_sr(const char *,
+ dladm_wlan_ess_t *, uint_t, uint_t *);
+extern dladm_status_t dladm_wlan_wpa_set_ie(const char *, uint8_t *, uint_t);
+extern dladm_status_t dladm_wlan_wpa_set_wpa(const char *, boolean_t);
+extern dladm_status_t dladm_wlan_wpa_del_key(const char *,
+ uint_t, const dladm_wlan_bssid_t *);
+extern dladm_status_t dladm_wlan_wpa_set_key(const char *,
+ dladm_wlan_cipher_t, const dladm_wlan_bssid_t *,
+ boolean_t, uint64_t, uint_t, uint8_t *, uint_t);
+extern dladm_status_t dladm_wlan_wpa_set_mlme(const char *,
+ dladm_wlan_mlme_op_t,
+ dladm_wlan_reason_t, dladm_wlan_bssid_t *);
extern const char *dladm_wlan_essid2str(dladm_wlan_essid_t *, char *);
extern const char *dladm_wlan_bssid2str(dladm_wlan_bssid_t *, char *);
diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers
index 57c0999585..8ba960a93d 100644
--- a/usr/src/lib/libdladm/common/mapfile-vers
+++ b/usr/src/lib/libdladm/common/mapfile-vers
@@ -91,6 +91,12 @@ SUNWprivate_1.1 {
dladm_wlan_str2auth;
dladm_wlan_str2bsstype;
dladm_wlan_str2linkstatus;
+ dladm_wlan_wpa_get_sr;
+ dladm_wlan_wpa_set_ie;
+ dladm_wlan_wpa_set_wpa;
+ dladm_wlan_wpa_del_key;
+ dladm_wlan_wpa_set_key;
+ dladm_wlan_wpa_set_mlme;
local:
*;
diff --git a/usr/src/lib/libdladm/common/secobj.c b/usr/src/lib/libdladm/common/secobj.c
index 5deb1590dc..61a1cd72e5 100644
--- a/usr/src/lib/libdladm/common/secobj.c
+++ b/usr/src/lib/libdladm/common/secobj.c
@@ -51,7 +51,8 @@ typedef struct secobj_class_info {
} secobj_class_info_t;
static secobj_class_info_t secobj_class_table[] = {
- {"wep", DLD_SECOBJ_CLASS_WEP}
+ {"wep", DLD_SECOBJ_CLASS_WEP},
+ {"wpa", DLD_SECOBJ_CLASS_WPA}
};
#define NSECOBJCLASS \
@@ -154,10 +155,12 @@ dladm_set_secobj(const char *obj_name, dladm_secobj_class_t class,
return (dladm_errno2status(errno));
if (i_dladm_ioctl(fd, DLDIOCSECOBJSET, &secobj_set,
- sizeof (secobj_set)) < 0)
+ sizeof (secobj_set)) < 0) {
status = dladm_errno2status(errno);
+ }
(void) close(fd);
+
if (status != DLADM_STATUS_OK)
return (status);
diff --git a/usr/src/lib/libsecdb/auth_attr.txt b/usr/src/lib/libsecdb/auth_attr.txt
index 46521fbc2d..ec95de975d 100644
--- a/usr/src/lib/libsecdb/auth_attr.txt
+++ b/usr/src/lib/libsecdb/auth_attr.txt
@@ -98,6 +98,7 @@ solaris.smf.manage.rpc.bind:::Manage RPC Program number mapper::help=SmfRPCBind.
solaris.smf.manage.sendmail:::Manage Sendmail Service States::help=SmfSendmailStates.html
solaris.smf.manage.ssh:::Manage Secure Shell Service States::help=SmfSshStates.html
solaris.smf.manage.system-log:::Manage Syslog Service States::help=SmfSyslogStates.html
+solaris.smf.manage.wpa:::Manage WPA Service States::help=SmfWpaStates.html
solaris.smf.value.:::Change Values of SMF Service Properties::help=SmfValueHeader.html
solaris.smf.value.nwam:::Change Values of SMF Network Auto-Magic Properties::help=SmfValueNWAM.html
solaris.smf.value.routing:::Change Values of SMF Routing Properties::help=SmfValueRouting.html
diff --git a/usr/src/lib/libsecdb/help/auths/Makefile b/usr/src/lib/libsecdb/help/auths/Makefile
index a6b50e871d..45e7c359c3 100644
--- a/usr/src/lib/libsecdb/help/auths/Makefile
+++ b/usr/src/lib/libsecdb/help/auths/Makefile
@@ -84,6 +84,7 @@ HTMLENTS = \
SmfValueHeader.html \
SmfValueNWAM.html \
SmfValueRouting.html \
+ SmfWpaStates.html \
NetworkHeader.html \
WifiConfig.html \
WifiWep.html \
diff --git a/usr/src/lib/libsecdb/help/auths/SmfWpaStates.html b/usr/src/lib/libsecdb/help/auths/SmfWpaStates.html
new file mode 100644
index 0000000000..00792d10cf
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/SmfWpaStates.html
@@ -0,0 +1,44 @@
+<HTML>
+
+<!--
+ Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+-->
+<!-- SCCS keyword
+#pragma ident "%Z%%M% %I% %E% SMI"
+-->
+
+<HEAD>
+<!--
+META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"
+-->
+</HEAD>
+<BODY>
+When Manage WPA Service States is in the Authorizations
+Include column, it grants the authorization to enable, disable or
+refresh the wpa daemon.
+<p>
+If Manage WPA Service States is grayed, then you are not
+entitled to Add or Remove this authorization.
+<BR>&nbsp;
+</BODY>
+</HTML>
diff --git a/usr/src/lib/libsecdb/prof_attr.txt b/usr/src/lib/libsecdb/prof_attr.txt
index fc9e312077..90fe709baf 100644
--- a/usr/src/lib/libsecdb/prof_attr.txt
+++ b/usr/src/lib/libsecdb/prof_attr.txt
@@ -49,7 +49,7 @@ Mail Management:::Manage sendmail & queues:auths=solaris.smf.manage.sendmail;hel
Maintenance and Repair:::Maintain and repair a system:auths=solaris.smf.manage.system-log;help=RtMaintAndRepair.html
Media Backup:::Backup files and file systems:help=RtMediaBkup.html
Media Restore:::Restore files and file systems from backups:help=RtMediaRestore.html
-Network Management:::Manage the host and network configuration:auths=solaris.smf.manage.name-service-cache,solaris.smf.manage.bind,solaris.smf.value.routing,solaris.smf.manage.routing,solaris.smf.value.nwam,solaris.smf.manage.nwam;profiles=Network Wifi Management;help=RtNetMngmnt.html
+Network Management:::Manage the host and network configuration:auths=solaris.smf.manage.name-service-cache,solaris.smf.manage.bind,solaris.smf.value.routing,solaris.smf.manage.routing,solaris.smf.value.nwam,solaris.smf.manage.nwam,solaris.smf.manage.wpa;profiles=Network Wifi Management;help=RtNetMngmnt.html
Network Security:::Manage network and host security:auths=solaris.smf.manage.ssh;profiles=Network Wifi Security,Network Link Security;help=RtNetSecure.html
Network Wifi Management:::Manage wifi network configuration:auths=solaris.network.wifi.config;help=RtNetWifiMngmnt.html
Network Wifi Security:::Manage wifi network security:auths=solaris.network.wifi.wep;help=RtNetWifiSecure.html
diff --git a/usr/src/lib/libsecdb/user_attr.txt b/usr/src/lib/libsecdb/user_attr.txt
index de173ce94f..70a20356f3 100644
--- a/usr/src/lib/libsecdb/user_attr.txt
+++ b/usr/src/lib/libsecdb/user_attr.txt
@@ -1,13 +1,12 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -31,3 +30,4 @@
root::::auths=solaris.*,solaris.grant;profiles=All;lock_after_retries=no
lp::::profiles=Printer Management
adm::::profiles=Log Management
+dladm::::auths=solaris.smf.manage.wpa,solaris.smf.modify