summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdladm
diff options
context:
space:
mode:
authoryz147064 <none@none>2008-01-23 18:09:15 -0800
committeryz147064 <none@none>2008-01-23 18:09:15 -0800
commitd62bc4badc1c1f1549c961cfb8b420e650e1272b (patch)
tree9f466859e9cfb73da13b64261432aba4683f19ad /usr/src/lib/libdladm
parentd38257c4392a9dd690c2f7f2383236c1fc80e509 (diff)
downloadillumos-joyent-d62bc4badc1c1f1549c961cfb8b420e650e1272b.tar.gz
PSARC/2006/499 Clearview Nemo unification and vanity naming
PSARC/2007/527 Addendum for Clearview Vanity Naming and Nemo Unification PSARC/2008/002 Clearview UV Updates 6310766 vlan statistics get reset at unplumb time 6320515 dladm commands with "-R" option should not take effect immediately 6433732 Simplify the GLDv3 control path by making its processing asynchronous 6445912 dladm show-link fails to show a specific link in the debug version 6452413 dladm show-link doesn't show VLAN links for GLDv2 drivers 6504433 libwladm's use of wladm_wlresult2status() needs an overhaul 6504507 dladm set-linkprop failure message is unclear 6534289 DR should work with aggregations 6535719 dladm_aggr_port_attr_db_t`lp_devname should be MAXNAMELEN, not MAXNAMELEN + 1 6539634 GLDv3 should DL_ERROR_ACK a DL_UDQOS_REQ with DL_OUTSTATE when the stream is DL_UNATTACHED 6540246 libdladm should not guess zoneid from DLDIOCZIDGET ioctl errno 6544195 dladm show-dev assumes GLDv3 stats.. incompatible with GLDv2 6563295 dladm show-linkprop -P does not work properly for unavailable links 6577618 integrate network vanity naming and nemo unification 6600446 links assigned to a local zone are still aggregatable by global zone 6607572 "boot net - install" can trigger assertion failure in dld_str_attach() 6613956 "svccfg import -" does not work as bfu expects 6637596 invalid assertion in ip_soft_ring_assignment() 6642350 kernel DLPI processing routines are long overdue 6643338 GLDv3 PPA hack VLAN ID checks don't always work 6647203 bfu: smf_delete_manifest() does not work for non-global zones 6649885 DL_IB GLDv3 mactype plugin must fill in its mtr_nativetype 6650395 libuuid should be lint-clean and linted nightly --HG-- rename : usr/src/cmd/dladm/aggregation.conf => deleted_files/usr/src/cmd/dladm/aggregation.conf rename : usr/src/cmd/dladm/linkprop.conf => deleted_files/usr/src/cmd/dladm/linkprop.conf rename : usr/src/lib/libinetcfg/common/inetcfg_nic.c => deleted_files/usr/src/lib/libinetcfg/common/inetcfg_nic.c rename : usr/src/lib/libinetcfg/common/inetcfg_nic.h => deleted_files/usr/src/lib/libinetcfg/common/inetcfg_nic.h
Diffstat (limited to 'usr/src/lib/libdladm')
-rw-r--r--usr/src/lib/libdladm/Makefile8
-rw-r--r--usr/src/lib/libdladm/Makefile.com6
-rw-r--r--usr/src/lib/libdladm/common/libdladm.c194
-rw-r--r--usr/src/lib/libdladm/common/libdladm.h60
-rw-r--r--usr/src/lib/libdladm/common/libdladm_impl.h33
-rw-r--r--usr/src/lib/libdladm/common/libdlaggr.c1923
-rw-r--r--usr/src/lib/libdladm/common/libdlaggr.h54
-rw-r--r--usr/src/lib/libdladm/common/libdllink.c915
-rw-r--r--usr/src/lib/libdladm/common/libdllink.h88
-rw-r--r--usr/src/lib/libdladm/common/libdlmgmt.c676
-rw-r--r--usr/src/lib/libdladm/common/libdlmgmt.h199
-rw-r--r--usr/src/lib/libdladm/common/libdlvlan.c345
-rw-r--r--usr/src/lib/libdladm/common/libdlvlan.h60
-rw-r--r--usr/src/lib/libdladm/common/libdlvnic.c364
-rw-r--r--usr/src/lib/libdladm/common/libdlvnic.h28
-rw-r--r--usr/src/lib/libdladm/common/libdlwlan.c1358
-rw-r--r--usr/src/lib/libdladm/common/libdlwlan.h46
-rw-r--r--usr/src/lib/libdladm/common/libdlwlan_impl.h15
-rw-r--r--usr/src/lib/libdladm/common/linkprop.c1773
-rw-r--r--usr/src/lib/libdladm/common/llib-ldladm4
-rw-r--r--usr/src/lib/libdladm/common/mapfile-vers52
-rw-r--r--usr/src/lib/libdladm/common/secobj.c16
22 files changed, 4712 insertions, 3505 deletions
diff --git a/usr/src/lib/libdladm/Makefile b/usr/src/lib/libdladm/Makefile
index ceae6a3ad5..630a7e2e19 100644
--- a/usr/src/lib/libdladm/Makefile
+++ b/usr/src/lib/libdladm/Makefile
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,7 +28,8 @@
include $(SRC)/lib/Makefile.lib
HDRS = libdladm.h libdladm_impl.h libdllink.h libdlaggr.h \
- libdlwlan.h libdlwlan_impl.h libdlvnic.h
+ libdlwlan.h libdlwlan_impl.h libdlvnic.h libdlvlan.h \
+ libdlmgmt.h
HDRDIR = common
SUBDIRS = $(MACH)
@@ -37,7 +38,8 @@ $(BUILD64)SUBDIRS += $(MACH64)
POFILE = libdladm.po
MSGFILES = common/libdladm.c common/linkprop.c common/secobj.c \
common/libdllink.c common/libdlaggr.c \
- common/libdlwlan.c common/libdlvnic.c
+ common/libdlwlan.c common/libdlvnic.c \
+ common/libdlvlan.c common/libdlmgmt.c
XGETFLAGS = -a -x libdladm.xcl
all := TARGET = all
diff --git a/usr/src/lib/libdladm/Makefile.com b/usr/src/lib/libdladm/Makefile.com
index cbb912d3ed..4caeb08465 100644
--- a/usr/src/lib/libdladm/Makefile.com
+++ b/usr/src/lib/libdladm/Makefile.com
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -28,7 +28,7 @@
LIBRARY = libdladm.a
VERS = .1
OBJECTS = libdladm.o secobj.o linkprop.o libdllink.o libdlaggr.o \
- libdlwlan.o libdlvnic.o
+ libdlwlan.o libdlvnic.o libdlmgmt.o libdlvlan.o
include ../../Makefile.lib
@@ -36,7 +36,7 @@ include ../../Makefile.lib
include ../../Makefile.rootfs
LIBS = $(DYNLIB) $(LINTLIB)
-LDLIBS += -ldevinfo -ldlpi -lc -linetutil -lsocket -lscf
+LDLIBS += -ldevinfo -lc -linetutil -lsocket -lscf -lrcm -lnvpair
SRCDIR = ../common
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c
index ea440f76e3..58f15038bc 100644
--- a/usr/src/lib/libdladm/common/libdladm.c
+++ b/usr/src/lib/libdladm/common/libdladm.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,13 +28,14 @@
#include <unistd.h>
#include <stropts.h>
#include <errno.h>
+#include <ctype.h>
#include <fcntl.h>
#include <strings.h>
#include <dirent.h>
#include <sys/stat.h>
-#include <libdladm.h>
#include <libdladm_impl.h>
#include <libintl.h>
+#include <libdlpi.h>
static char dladm_rootdir[MAXPATHLEN] = "/";
@@ -127,24 +128,23 @@ dladm_status2str(dladm_status_t status, char *buf)
case DLADM_STATUS_KEYINVAL:
s = "invalid key";
break;
- case DLADM_STATUS_INVALIDID:
- s = "invalid VNIC id";
- break;
case DLADM_STATUS_INVALIDMACADDRLEN:
s = "invalid MAC address length";
break;
case DLADM_STATUS_INVALIDMACADDRTYPE:
s = "invalid MAC address type";
break;
- case DLADM_STATUS_AUTOIDNOTEMP:
- s = "automatic VNIC ID assigment not supported with"
- "persistant operations";
+ case DLADM_STATUS_LINKBUSY:
+ s = "link busy";
+ break;
+ case DLADM_STATUS_VIDINVAL:
+ s = "invalid VLAN identifier";
break;
- case DLADM_STATUS_AUTOIDNOAVAILABLEID:
- s = "no available VNIC ID for automatic assignment";
+ case DLADM_STATUS_TRYAGAIN:
+ s = "try again later";
break;
- case DLADM_STATUS_BUSY:
- s = "device busy";
+ case DLADM_STATUS_NONOTIF:
+ s = "link notification is not supported";
break;
default:
s = "<unknown error>";
@@ -175,12 +175,16 @@ dladm_errno2status(int err)
return (DLADM_STATUS_NOMEM);
case ENOTSUP:
return (DLADM_STATUS_NOTSUP);
+ case ENETDOWN:
+ return (DLADM_STATUS_NONOTIF);
case EACCES:
return (DLADM_STATUS_DENIED);
case EIO:
return (DLADM_STATUS_IOERR);
case EBUSY:
- return (DLADM_STATUS_BUSY);
+ return (DLADM_STATUS_LINKBUSY);
+ case EAGAIN:
+ return (DLADM_STATUS_TRYAGAIN);
default:
return (DLADM_STATUS_FAILED);
}
@@ -190,15 +194,15 @@ dladm_errno2status(int err)
* These are the uid and gid of the user 'dladm'.
* The directory /etc/dladm and all files under it are owned by this user.
*/
-#define DLADM_DB_OWNER 15
-#define DLADM_DB_GROUP 3
-#define LOCK_DB_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
+#define DLADM_DB_OWNER 15
+#define DLADM_DB_GROUP 3
+#define LOCK_DB_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
static int
i_dladm_lock_db(const char *lock_file, short type)
{
int lock_fd;
- struct flock lock;
+ struct flock lock;
if ((lock_fd = open(lock_file, O_RDWR | O_CREAT | O_TRUNC,
LOCK_DB_PERMS)) < 0)
@@ -238,6 +242,135 @@ i_dladm_unlock_db(const char *lock_file, int fd)
(void) unlink(lock_file);
}
+/*
+ * Given a link class, returns its class string.
+ */
+const char *
+dladm_class2str(datalink_class_t class, char *buf)
+{
+ const char *s;
+
+ switch (class) {
+ case DATALINK_CLASS_PHYS:
+ s = "phys";
+ break;
+ case DATALINK_CLASS_VLAN:
+ s = "vlan";
+ break;
+ case DATALINK_CLASS_AGGR:
+ s = "aggr";
+ break;
+ case DATALINK_CLASS_VNIC:
+ s = "vnic";
+ break;
+ default:
+ s = "unknown";
+ break;
+ }
+
+ (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
+ return (buf);
+}
+
+/*
+ * Given a physical link media type, returns its media type string.
+ */
+const char *
+dladm_media2str(uint32_t media, char *buf)
+{
+ const char *s;
+
+ switch (media) {
+ case DL_ETHER:
+ s = "Ethernet";
+ break;
+ case DL_WIFI:
+ s = "WiFi";
+ break;
+ case DL_IB:
+ s = "Infiniband";
+ break;
+ case DL_IPV4:
+ s = "IPv4Tunnel";
+ break;
+ case DL_IPV6:
+ s = "IPv6Tunnel";
+ break;
+ case DL_CSMACD:
+ s = "CSMA/CD";
+ break;
+ case DL_TPB:
+ s = "TokenBus";
+ break;
+ case DL_TPR:
+ s = "TokenRing";
+ break;
+ case DL_METRO:
+ s = "MetroNet";
+ break;
+ case DL_HDLC:
+ s = "HDLC";
+ break;
+ case DL_CHAR:
+ s = "SyncCharacter";
+ break;
+ case DL_CTCA:
+ s = "CTCA";
+ break;
+ case DL_FDDI:
+ s = "FDDI";
+ break;
+ case DL_FC:
+ s = "FiberChannel";
+ break;
+ case DL_ATM:
+ s = "ATM";
+ break;
+ case DL_IPATM:
+ s = "ATM(ClassicIP)";
+ break;
+ case DL_X25:
+ s = "X.25";
+ break;
+ case DL_IPX25:
+ s = "X.25(ClassicIP)";
+ break;
+ case DL_ISDN:
+ s = "ISDN";
+ break;
+ case DL_HIPPI:
+ s = "HIPPI";
+ break;
+ case DL_100VG:
+ s = "100BaseVGEthernet";
+ break;
+ case DL_100VGTPR:
+ s = "100BaseVGTokenRing";
+ break;
+ case DL_ETH_CSMA:
+ s = "IEEE802.3";
+ break;
+ case DL_100BT:
+ s = "100BaseT";
+ break;
+ case DL_FRAME:
+ s = "FrameRelay";
+ break;
+ case DL_MPFRAME:
+ s = "MPFrameRelay";
+ break;
+ case DL_ASYNC:
+ s = "AsyncCharacter";
+ break;
+ default:
+ s = "--";
+ break;
+ }
+
+ (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
+ return (buf);
+}
+
dladm_status_t
i_dladm_rw_db(const char *db_file, mode_t db_perms,
dladm_status_t (*process_db)(void *, FILE *, FILE *),
@@ -350,3 +483,30 @@ dladm_set_rootdir(const char *rootdir)
(void) closedir(dp);
return (DLADM_STATUS_OK);
}
+
+boolean_t
+dladm_valid_linkname(const char *link)
+{
+ size_t len = strlen(link);
+ const char *cp;
+
+ if (len + 1 >= MAXLINKNAMELEN)
+ return (B_FALSE);
+
+ /*
+ * The link name cannot start with a digit and must end with a digit.
+ */
+ if ((isdigit(link[0]) != 0) || (isdigit(link[len - 1]) == 0))
+ return (B_FALSE);
+
+ /*
+ * The legal characters in a link name are:
+ * alphanumeric (a-z, A-Z, 0-9), and the underscore ('_').
+ */
+ for (cp = link; *cp != '\0'; cp++) {
+ if ((isalnum(*cp) == 0) && (*cp != '_'))
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h
index 8ed30b4ebf..a7077f5900 100644
--- a/usr/src/lib/libdladm/common/libdladm.h
+++ b/usr/src/lib/libdladm/common/libdladm.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,6 +28,9 @@
#pragma ident "%Z%%M% %I% %E% SMI"
+#include <sys/dls.h>
+#include <sys/dlpi.h>
+
/*
* This file includes structures, macros and common routines shared by all
* data-link administration, and routines which do not directly administrate
@@ -38,10 +41,36 @@
extern "C" {
#endif
+#define LINKID_STR_WIDTH 10
#define DLADM_STRSIZE 256
-#define DLADM_OPT_TEMP 0x00000001
-#define DLADM_OPT_CREATE 0x00000002
-#define DLADM_OPT_PERSIST 0x00000004
+
+/*
+ * option flags taken by the libdladm functions
+ *
+ * - DLADM_OPT_ACTIVE:
+ * The function requests to bringup some configuration that only take
+ * effect on active system (not persistent).
+ *
+ * - DLADM_OPT_PERSIST:
+ * The function requests to persist some configuration.
+ *
+ * - DLADM_OPT_CREATE:
+ * Today, only used by dladm_set_secobj() - requests to create a secobj.
+ *
+ * - DLADM_OPT_FORCE:
+ * The function requests to execute a specific operation forcefully.
+ *
+ * - DLADM_OPT_PREFIX:
+ * The function requests to generate a link name using the specified prefix.
+ */
+#define DLADM_OPT_ACTIVE 0x00000001
+#define DLADM_OPT_PERSIST 0x00000002
+#define DLADM_OPT_CREATE 0x00000004
+#define DLADM_OPT_FORCE 0x00000008
+#define DLADM_OPT_PREFIX 0x00000010
+
+#define DLADM_WALK_TERMINATE 0
+#define DLADM_WALK_CONTINUE -1
typedef enum {
DLADM_STATUS_OK = 0,
@@ -66,23 +95,28 @@ typedef enum {
DLADM_STATUS_REPOSITORYINVAL,
DLADM_STATUS_MACADDRINVAL,
DLADM_STATUS_KEYINVAL,
- DLADM_STATUS_INVALIDID,
DLADM_STATUS_INVALIDMACADDRLEN,
DLADM_STATUS_INVALIDMACADDRTYPE,
- DLADM_STATUS_AUTOIDNOTEMP,
- DLADM_STATUS_AUTOIDNOAVAILABLEID,
- DLADM_STATUS_BUSY
+ DLADM_STATUS_LINKBUSY,
+ DLADM_STATUS_VIDINVAL,
+ DLADM_STATUS_NONOTIF,
+ DLADM_STATUS_TRYAGAIN
} dladm_status_t;
typedef enum {
- DLADM_PROP_VAL_CURRENT = 1,
- DLADM_PROP_VAL_DEFAULT,
- DLADM_PROP_VAL_MODIFIABLE,
- DLADM_PROP_VAL_PERSISTENT
-} dladm_prop_type_t;
+ DLADM_TYPE_STR,
+ DLADM_TYPE_BOOLEAN,
+ DLADM_TYPE_UINT64
+} dladm_datatype_t;
+
+typedef int dladm_conf_t;
+#define DLADM_INVALID_CONF 0
extern const char *dladm_status2str(dladm_status_t, char *);
extern dladm_status_t dladm_set_rootdir(const char *);
+extern const char *dladm_class2str(datalink_class_t, char *);
+extern const char *dladm_media2str(uint32_t, char *);
+extern boolean_t dladm_valid_linkname(const char *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdladm/common/libdladm_impl.h b/usr/src/lib/libdladm/common/libdladm_impl.h
index c949219a5b..f71495e5d9 100644
--- a/usr/src/lib/libdladm/common/libdladm_impl.h
+++ b/usr/src/lib/libdladm/common/libdladm_impl.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,12 +38,41 @@ extern "C" {
#define MAXLINELEN 1024
#define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
+typedef struct val_desc {
+ char *vd_name;
+ uintptr_t vd_val;
+} val_desc_t;
+
+#define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t))
+
extern int i_dladm_ioctl(int, int, void *, int);
extern dladm_status_t dladm_errno2status(int);
-extern dladm_status_t i_dladm_rw_db(const char *, mode_t,
+extern dladm_status_t i_dladm_rw_db(const char *, mode_t,
dladm_status_t (*)(void *, FILE *, FILE *),
void *, boolean_t);
+/*
+ * Link attributes persisted by dlmgmtd.
+ */
+/*
+ * Set for VLANs only
+ */
+#define FVLANID "vid" /* uint64_t */
+#define FLINKOVER "linkover" /* uint64_t */
+
+/*
+ * Set for AGGRs only
+ */
+#define FKEY "key" /* uint64_t */
+#define FNPORTS "nports" /* uint64_t */
+#define FPORTS "portnames" /* string */
+#define FPOLICY "policy" /* uint64_t */
+#define FFIXMACADDR "fix_macaddr" /* boolean_t */
+#define FMACADDR "macaddr" /* string */
+#define FFORCE "force" /* boolean_t */
+#define FLACPMODE "lacp_mode" /* uint64_t */
+#define FLACPTIMER "lacp_timer" /* uint64_t */
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libdladm/common/libdlaggr.c b/usr/src/lib/libdladm/common/libdlaggr.c
index 0c622fc8a2..75291d0d1d 100644
--- a/usr/src/lib/libdladm/common/libdlaggr.c
+++ b/usr/src/lib/libdladm/common/libdlaggr.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -34,10 +34,13 @@
#include <stropts.h>
#include <stdlib.h>
#include <errno.h>
+#include <assert.h>
#include <strings.h>
#include <libintl.h>
#include <net/if_types.h>
#include <net/if_dl.h>
+#include <libdllink.h>
+#include <libdlvlan.h>
#include <libdlaggr.h>
#include <libdladm_impl.h>
@@ -46,78 +49,39 @@
*
* This library is used by administration tools such as dladm(1M) to
* configure link aggregations.
- *
- * Link aggregation configuration information is saved in a text
- * file of the following format:
- *
- * <db-file> ::= <groups>*
- * <group> ::= <key> <sep> <policy> <sep> <nports> <sep> <ports> <sep>
- * <mac> <sep> <lacp-mode> <sep> <lacp-timer>
- * <sep> ::= ' ' | '\t'
- * <key> ::= <number>
- * <nports> ::= <number>
- * <ports> ::= <port> <m-port>*
- * <m-port> ::= ',' <port>
- * <port> ::= <devname>
- * <devname> ::= <string>
- * <port-num> ::= <number>
- * <policy> ::= <pol-level> <m-pol>*
- * <m-pol> ::= ',' <pol-level>
- * <pol-level> ::= 'L2' | 'L3' | 'L4'
- * <mac> ::= 'auto' | <mac-addr>
- * <mac-addr> ::= <hex> ':' <hex> ':' <hex> ':' <hex> ':' <hex> ':' <hex>
- * <lacp-mode> ::= 'off' | 'active' | 'passive'
- * <lacp-timer> ::= 'short' | 'long'
*/
-#define DLADM_AGGR_DEV "/devices/pseudo/aggr@0:" AGGR_DEVNAME_CTL
-#define DLADM_AGGR_DB "/etc/dladm/aggregation.conf"
-#define DLADM_AGGR_DB_TMP "/etc/dladm/aggregation.conf.new"
-#define DLADM_AGGR_DB_LOCK "/tmp/aggregation.conf.lock"
-
-#define DLADM_AGGR_DB_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
-#define DLADM_AGGR_DB_OWNER 15 /* "dladm" UID */
-#define DLADM_AGGR_DB_GROUP 3 /* "sys" GID */
-
-/*
- * The largest configurable aggregation key. Because by default the key is
- * used as the DLPI device PPA and default VLAN PPA's are calculated as
- * ((1000 * vid) + PPA), the largest key can't be > 999.
- */
-#define DLADM_AGGR_MAX_KEY 999
-
-#define BLANK_LINE(s) ((s[0] == '\0') || (s[0] == '#') || (s[0] == '\n'))
+#define DLADM_AGGR_DEV "/devices/pseudo/aggr@0:" AGGR_DEVNAME_CTL
/* Limits on buffer size for LAIOC_INFO request */
#define MIN_INFO_SIZE (4*1024)
#define MAX_INFO_SIZE (128*1024)
-#define MAXPATHLEN 1024
-
static uchar_t zero_mac[] = {0, 0, 0, 0, 0, 0};
+#define VALID_PORT_MAC(mac) \
+ (((mac) != NULL) && (bcmp(zero_mac, (mac), ETHERADDRL) != 0) && \
+ (!(mac)[0] & 0x01))
-/* configuration database entry */
-typedef struct dladm_aggr_grp_attr_db {
- uint32_t lt_key;
- uint32_t lt_policy;
- uint32_t lt_nports;
- dladm_aggr_port_attr_db_t *lt_ports;
- boolean_t lt_mac_fixed;
- uchar_t lt_mac[ETHERADDRL];
- aggr_lacp_mode_t lt_lacp_mode;
- aggr_lacp_timer_t lt_lacp_timer;
-} dladm_aggr_grp_attr_db_t;
-
-typedef struct dladm_aggr_up {
- uint32_t lu_key;
- boolean_t lu_found;
- int lu_fd;
-} dladm_aggr_up_t;
-
-typedef struct dladm_aggr_down {
- uint32_t ld_key;
- boolean_t ld_found;
-} dladm_aggr_down_t;
+#define PORT_DELIMITER '.'
+
+#define WRITE_PORT(portstr, portid, size) { \
+ char pstr[LINKID_STR_WIDTH + 2]; \
+ (void) snprintf(pstr, LINKID_STR_WIDTH + 2, "%d%c", \
+ (portid), PORT_DELIMITER); \
+ (void) strlcat((portstr), pstr, (size)); \
+}
+
+#define READ_PORT(portstr, portid, status) { \
+ errno = 0; \
+ (status) = DLADM_STATUS_OK; \
+ (portid) = (int)strtol((portstr), &(portstr), 10); \
+ if (errno != 0 || *(portstr) != PORT_DELIMITER) { \
+ (status) = DLADM_STATUS_REPOSITORYINVAL; \
+ } else { \
+ /* Skip the delimiter. */ \
+ (portstr)++; \
+ } \
+}
typedef struct dladm_aggr_modify_attr {
uint32_t ld_policy;
@@ -175,106 +139,93 @@ static dladm_aggr_port_state_t port_states[] = {
#define NPORT_STATES \
(sizeof (port_states) / sizeof (dladm_aggr_port_state_t))
-typedef struct delete_db_state {
- uint32_t ds_key;
- boolean_t ds_found;
-} delete_db_state_t;
+static int
+i_dladm_aggr_strioctl(int cmd, void *ptr, int ilen)
+{
+ int err, fd;
-typedef struct modify_db_state {
- uint32_t us_key;
- uint32_t us_mask;
- dladm_aggr_modify_attr_t *us_attr_new;
- dladm_aggr_modify_attr_t *us_attr_old;
- boolean_t us_found;
-} modify_db_state_t;
+ if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0)
+ return (-1);
-typedef struct add_db_state {
- dladm_aggr_grp_attr_db_t *as_attr;
- boolean_t as_found;
-} add_db_state_t;
+ err = i_dladm_ioctl(fd, cmd, ptr, ilen);
+ (void) close(fd);
-static int i_dladm_aggr_fput_grp(FILE *, dladm_aggr_grp_attr_db_t *);
+ return (err);
+}
/*
- * Open and lock the aggregation configuration file lock. The lock is
- * acquired as a reader (F_RDLCK) or writer (F_WRLCK).
+ * Caller must free attr.lg_ports. The ptr pointer is advanced while convert
+ * the laioc_info_t to the dladm_aggr_grp_attr_t structure.
*/
static int
-i_dladm_aggr_lock_db(short type)
+i_dladm_aggr_iocp2grpattr(void **ptr, dladm_aggr_grp_attr_t *attrp)
{
- int lock_fd;
- struct flock lock;
- int errno_save;
+ laioc_info_group_t *grp;
+ laioc_info_port_t *port;
+ int i;
+ void *where = (*ptr);
- if ((lock_fd = open(DLADM_AGGR_DB_LOCK, O_RDWR | O_CREAT | O_TRUNC,
- DLADM_AGGR_DB_PERMS)) < 0)
- return (-1);
+ grp = (laioc_info_group_t *)where;
- lock.l_type = type;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
+ attrp->lg_linkid = grp->lg_linkid;
+ attrp->lg_key = grp->lg_key;
+ attrp->lg_nports = grp->lg_nports;
+ attrp->lg_policy = grp->lg_policy;
+ attrp->lg_lacp_mode = grp->lg_lacp_mode;
+ attrp->lg_lacp_timer = grp->lg_lacp_timer;
+ attrp->lg_force = grp->lg_force;
- if (fcntl(lock_fd, F_SETLKW, &lock) < 0) {
- errno_save = errno;
- (void) close(lock_fd);
- (void) unlink(DLADM_AGGR_DB_LOCK);
- errno = errno_save;
- return (-1);
+ bcopy(grp->lg_mac, attrp->lg_mac, ETHERADDRL);
+ attrp->lg_mac_fixed = grp->lg_mac_fixed;
+
+ if ((attrp->lg_ports = malloc(grp->lg_nports *
+ sizeof (dladm_aggr_port_attr_t))) == NULL) {
+ errno = ENOMEM;
+ goto fail;
}
- return (lock_fd);
-}
-/*
- * Unlock and close the specified file.
- */
-static void
-i_dladm_aggr_unlock_db(int fd)
-{
- struct flock lock;
+ where = (grp + 1);
- if (fd < 0)
- return;
+ /*
+ * Go through each port that is part of the group.
+ */
+ for (i = 0; i < grp->lg_nports; i++) {
+ port = (laioc_info_port_t *)where;
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
+ attrp->lg_ports[i].lp_linkid = port->lp_linkid;
+ bcopy(port->lp_mac, attrp->lg_ports[i].lp_mac, ETHERADDRL);
+ attrp->lg_ports[i].lp_state = port->lp_state;
+ attrp->lg_ports[i].lp_lacp_state = port->lp_lacp_state;
- (void) fcntl(fd, F_SETLKW, &lock);
- (void) close(fd);
- (void) unlink(DLADM_AGGR_DB_LOCK);
+ where = (port + 1);
+ }
+ *ptr = where;
+ return (0);
+fail:
+ return (-1);
}
/*
- * Walk through the groups defined on the system and for each group <grp>,
- * invoke <fn>(<arg>, <grp>);
- * Terminate the walk if at any time <fn> returns non-NULL value
+ * Get active configuration of a specific aggregation.
+ * Caller must free attrp->la_ports.
*/
-int
-dladm_aggr_walk(int (*fn)(void *, dladm_aggr_grp_attr_t *), void *arg)
+static dladm_status_t
+i_dladm_aggr_info_active(datalink_id_t linkid, dladm_aggr_grp_attr_t *attrp)
{
laioc_info_t *ioc;
- laioc_info_group_t *grp;
- laioc_info_port_t *port;
- dladm_aggr_grp_attr_t attr;
- int rc, i, j, bufsize, fd;
- char *where;
-
- if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) == -1)
- return (-1);
+ int rc, bufsize;
+ void *where;
+ dladm_status_t status = DLADM_STATUS_OK;
bufsize = MIN_INFO_SIZE;
ioc = (laioc_info_t *)calloc(1, bufsize);
- if (ioc == NULL) {
- (void) close(fd);
- errno = ENOMEM;
- return (-1);
- }
+ if (ioc == NULL)
+ return (DLADM_STATUS_NOMEM);
-tryagain:
- rc = i_dladm_ioctl(fd, LAIOC_INFO, ioc, bufsize);
+ ioc->li_group_linkid = linkid;
+tryagain:
+ rc = i_dladm_aggr_strioctl(LAIOC_INFO, ioc, bufsize);
if (rc != 0) {
if (errno == ENOSPC) {
/*
@@ -290,6 +241,7 @@ tryagain:
}
}
}
+ status = dladm_errno2status(errno);
goto bail;
}
@@ -297,257 +249,329 @@ tryagain:
* Go through each group returned by the aggregation driver.
*/
where = (char *)(ioc + 1);
- for (i = 0; i < ioc->li_ngroups; i++) {
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- grp = (laioc_info_group_t *)where;
-
- attr.lg_key = grp->lg_key;
- attr.lg_nports = grp->lg_nports;
- attr.lg_policy = grp->lg_policy;
- attr.lg_lacp_mode = grp->lg_lacp_mode;
- attr.lg_lacp_timer = grp->lg_lacp_timer;
-
- bcopy(grp->lg_mac, attr.lg_mac, ETHERADDRL);
- attr.lg_mac_fixed = grp->lg_mac_fixed;
-
- attr.lg_ports = malloc(grp->lg_nports *
- sizeof (dladm_aggr_port_attr_t));
- if (attr.lg_ports == NULL) {
- errno = ENOMEM;
- goto bail;
- }
-
- where = (char *)(grp + 1);
-
- /*
- * Go through each port that is part of the group.
- */
- for (j = 0; j < grp->lg_nports; j++) {
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- port = (laioc_info_port_t *)where;
-
- bcopy(port->lp_devname, attr.lg_ports[j].lp_devname,
- MAXNAMELEN + 1);
- bcopy(port->lp_mac, attr.lg_ports[j].lp_mac,
- ETHERADDRL);
- attr.lg_ports[j].lp_state = port->lp_state;
- attr.lg_ports[j].lp_lacp_state = port->lp_lacp_state;
-
- where = (char *)(port + 1);
- }
-
- rc = fn(arg, &attr);
- free(attr.lg_ports);
- if (rc != 0)
- goto bail;
+ if (i_dladm_aggr_iocp2grpattr(&where, attrp) != 0) {
+ status = dladm_errno2status(errno);
+ goto bail;
}
bail:
free(ioc);
- (void) close(fd);
- return (rc);
+ return (status);
}
/*
- * Parse one line of the link aggregation DB, and return the corresponding
- * group. Memory for the ports associated with the aggregation may be
- * allocated. It is the responsibility of the caller to free the lt_ports
- * aggregation group attribute.
- *
- * Returns -1 on parsing failure, or 0 on success.
+ * Get configuration information of a specific aggregation.
+ * Caller must free attrp->la_ports.
*/
-static int
-i_dladm_aggr_parse_db(char *line, dladm_aggr_grp_attr_db_t *attr)
+static dladm_status_t
+i_dladm_aggr_info_persist(datalink_id_t linkid, dladm_aggr_grp_attr_t *attrp)
{
- char *token;
- int i;
- int value;
- char *endp = NULL;
- char *lasts = NULL;
-
- bzero(attr, sizeof (*attr));
+ dladm_conf_t conf;
+ uint32_t nports, i;
+ char *portstr, *next;
+ dladm_status_t status;
+ uint64_t u64;
+ int size;
+ char macstr[ETHERADDRL * 3];
- /* key */
- if ((token = strtok_r(line, " \t", &lasts)) == NULL)
- goto failed;
+ attrp->lg_linkid = linkid;
+ if ((status = dladm_read_conf(linkid, &conf)) != DLADM_STATUS_OK)
+ return (status);
- errno = 0;
- value = (int)strtol(token, &endp, 10);
- if (errno != 0 || *endp != '\0')
- goto failed;
+ status = dladm_get_conf_field(conf, FKEY, &u64, sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ attrp->lg_key = (uint16_t)u64;
- attr->lt_key = value;
+ status = dladm_get_conf_field(conf, FPOLICY, &u64, sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ attrp->lg_policy = (uint32_t)u64;
- /* policy */
- if ((token = strtok_r(NULL, " \t", &lasts)) == NULL ||
- !dladm_aggr_str2policy(token, &attr->lt_policy))
- goto failed;
+ status = dladm_get_conf_field(conf, FFIXMACADDR, &attrp->lg_mac_fixed,
+ sizeof (boolean_t));
+ if (status != DLADM_STATUS_OK)
+ goto done;
- /* number of ports */
- if ((token = strtok_r(NULL, " \t", &lasts)) == NULL)
- return (-1);
+ if (attrp->lg_mac_fixed) {
+ boolean_t fixed;
- errno = 0;
- value = (int)strtol(token, &endp, 10);
- if (errno != 0 || *endp != '\0')
- goto failed;
+ if ((status = dladm_get_conf_field(conf, FMACADDR, macstr,
+ sizeof (macstr))) != DLADM_STATUS_OK) {
+ goto done;
+ }
+ if (!dladm_aggr_str2macaddr(macstr, &fixed, attrp->lg_mac)) {
+ status = DLADM_STATUS_REPOSITORYINVAL;
+ goto done;
+ }
+ }
- attr->lt_nports = value;
+ status = dladm_get_conf_field(conf, FFORCE, &attrp->lg_force,
+ sizeof (boolean_t));
+ if (status != DLADM_STATUS_OK)
+ goto done;
- /* ports */
- if ((attr->lt_ports = malloc(attr->lt_nports *
- sizeof (dladm_aggr_port_attr_db_t))) == NULL)
- goto failed;
+ status = dladm_get_conf_field(conf, FLACPMODE, &u64, sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ attrp->lg_lacp_mode = (aggr_lacp_mode_t)u64;
- for (i = 0; i < attr->lt_nports; i++) {
- char *where, *devname;
+ status = dladm_get_conf_field(conf, FLACPTIMER, &u64, sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ attrp->lg_lacp_timer = (aggr_lacp_timer_t)u64;
- /* port */
- if ((token = strtok_r(NULL, ", \t\n", &lasts)) == NULL)
- goto failed;
+ status = dladm_get_conf_field(conf, FNPORTS, &u64, sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ nports = (uint32_t)u64;
+ attrp->lg_nports = nports;
- /*
- * device name: In a previous version of this file, a port
- * number could be specified using <devname>/<portnum>.
- * This syntax is unecessary and obsolete.
- */
- if ((devname = strtok_r(token, "/", &where)) == NULL)
- goto failed;
- if (strlcpy(attr->lt_ports[i].lp_devname, devname,
- MAXNAMELEN) >= MAXNAMELEN)
- goto failed;
+ size = nports * (LINKID_STR_WIDTH + 1) + 1;
+ if ((portstr = calloc(1, size)) == NULL) {
+ status = DLADM_STATUS_NOMEM;
+ goto done;
}
- /* unicast MAC address */
- if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
- !dladm_aggr_str2macaddr(token, &attr->lt_mac_fixed,
- attr->lt_mac))
- goto failed;
+ status = dladm_get_conf_field(conf, FPORTS, portstr, size);
+ if (status != DLADM_STATUS_OK) {
+ free(portstr);
+ goto done;
+ }
- /* LACP mode */
- if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
- !dladm_aggr_str2lacpmode(token, &attr->lt_lacp_mode))
- attr->lt_lacp_mode = AGGR_LACP_OFF;
+ if ((attrp->lg_ports = malloc(nports *
+ sizeof (dladm_aggr_port_attr_t))) == NULL) {
+ free(portstr);
+ status = DLADM_STATUS_NOMEM;
+ goto done;
+ }
- /* LACP timer */
- if ((token = strtok_r(NULL, " \t\n", &lasts)) == NULL ||
- !dladm_aggr_str2lacptimer(token, &attr->lt_lacp_timer))
- attr->lt_lacp_timer = AGGR_LACP_TIMER_SHORT;
+ for (next = portstr, i = 0; i < nports; i++) {
+ READ_PORT(next, attrp->lg_ports[i].lp_linkid, status);
+ if (status != DLADM_STATUS_OK) {
+ free(portstr);
+ free(attrp->lg_ports);
+ goto done;
+ }
+ }
+ free(portstr);
- return (0);
+done:
+ dladm_destroy_conf(conf);
+ return (status);
+}
-failed:
- free(attr->lt_ports);
- attr->lt_ports = NULL;
- return (-1);
+dladm_status_t
+dladm_aggr_info(datalink_id_t linkid, dladm_aggr_grp_attr_t *attrp,
+ uint32_t flags)
+{
+ assert(flags == DLADM_OPT_ACTIVE || flags == DLADM_OPT_PERSIST);
+ if (flags == DLADM_OPT_ACTIVE)
+ return (i_dladm_aggr_info_active(linkid, attrp));
+ else
+ return (i_dladm_aggr_info_persist(linkid, attrp));
}
/*
- * Walk through the groups defined in the DB and for each group <grp>,
- * invoke <fn>(<arg>, <grp>);
+ * Add or remove one or more ports to/from an existing link aggregation.
*/
static dladm_status_t
-i_dladm_aggr_walk_db(dladm_status_t (*fn)(void *, dladm_aggr_grp_attr_db_t *),
- void *arg, const char *root)
+i_dladm_aggr_add_rmv(datalink_id_t linkid, uint32_t nports,
+ dladm_aggr_port_attr_db_t *ports, uint32_t flags, int cmd)
{
- FILE *fp;
- char line[MAXLINELEN];
- dladm_aggr_grp_attr_db_t attr;
- char *db_file;
- char db_file_buf[MAXPATHLEN];
- int lock_fd;
+ char *orig_portstr = NULL, *portstr = NULL;
+ laioc_add_rem_t *iocp;
+ laioc_port_t *ioc_ports;
+ uint32_t orig_nports, result_nports, len, i, j;
+ dladm_conf_t conf;
+ datalink_class_t class;
dladm_status_t status = DLADM_STATUS_OK;
+ int size;
+ uint64_t u64;
+ uint32_t media;
- if (root == NULL) {
- db_file = DLADM_AGGR_DB;
- } else {
- (void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
- DLADM_AGGR_DB);
- db_file = db_file_buf;
- }
-
- lock_fd = i_dladm_aggr_lock_db(F_RDLCK);
+ if (nports == 0)
+ return (DLADM_STATUS_BADARG);
- if ((fp = fopen(db_file, "r")) == NULL) {
- status = dladm_errno2status(errno);
- i_dladm_aggr_unlock_db(lock_fd);
- return (status);
+ /*
+ * Sanity check - aggregations can only be created over Ethernet
+ * physical links.
+ */
+ for (i = 0; i < nports; i++) {
+ if ((dladm_datalink_id2info(ports[i].lp_linkid, NULL,
+ &class, &media, NULL, 0) != DLADM_STATUS_OK) ||
+ (class != DATALINK_CLASS_PHYS) || (media != DL_ETHER)) {
+ return (DLADM_STATUS_BADARG);
+ }
}
- bzero(&attr, sizeof (attr));
+ /*
+ * First, update the persistent configuration if requested. We only
+ * need to update the FPORTS and FNPORTS fields of this aggregation.
+ * Note that FPORTS is a list of port linkids separated by
+ * PORT_DELIMITER ('.').
+ */
+ if (flags & DLADM_OPT_PERSIST) {
+ status = dladm_read_conf(linkid, &conf);
+ if (status != DLADM_STATUS_OK)
+ return (status);
- while (fgets(line, MAXLINELEN, fp) != NULL) {
- /* skip comments */
- if (BLANK_LINE(line))
- continue;
+ /*
+ * Get the original configuration of FNPORTS and FPORTS.
+ */
+ status = dladm_get_conf_field(conf, FNPORTS, &u64,
+ sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto destroyconf;
+ orig_nports = (uint32_t)u64;
- if (i_dladm_aggr_parse_db(line, &attr) != 0) {
- status = DLADM_STATUS_REPOSITORYINVAL;
- goto done;
+ /*
+ * At least one port needs to be in the aggregation.
+ */
+ if ((cmd == LAIOC_REMOVE) && (orig_nports <= nports)) {
+ status = DLADM_STATUS_BADARG;
+ goto destroyconf;
}
- if ((status = fn(arg, &attr)) != DLADM_STATUS_OK)
- goto done;
+ size = orig_nports * (LINKID_STR_WIDTH + 1) + 1;
+ if ((orig_portstr = calloc(1, size)) == NULL) {
+ status = dladm_errno2status(errno);
+ goto destroyconf;
+ }
- free(attr.lt_ports);
- attr.lt_ports = NULL;
- }
+ status = dladm_get_conf_field(conf, FPORTS, orig_portstr, size);
+ if (status != DLADM_STATUS_OK)
+ goto destroyconf;
-done:
- free(attr.lt_ports);
- (void) fclose(fp);
- i_dladm_aggr_unlock_db(lock_fd);
- return (status);
-}
+ result_nports = (cmd == LAIOC_ADD) ? orig_nports + nports :
+ orig_nports;
-/*
- * Send an add or remove command to the link aggregation driver.
- */
-static dladm_status_t
-i_dladm_aggr_add_rem_sys(dladm_aggr_grp_attr_db_t *attr, int cmd)
-{
- int i, rc, fd, len;
- laioc_add_rem_t *iocp;
- laioc_port_t *ports;
- dladm_status_t status = DLADM_STATUS_OK;
+ size = result_nports * (LINKID_STR_WIDTH + 1) + 1;
+ if ((portstr = calloc(1, size)) == NULL) {
+ status = dladm_errno2status(errno);
+ goto destroyconf;
+ }
- len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
- iocp = malloc(len);
- if (iocp == NULL) {
- status = DLADM_STATUS_NOMEM;
- goto done;
- }
+ /*
+ * get the new configuration and set to result_nports and
+ * portstr.
+ */
+ if (cmd == LAIOC_ADD) {
+ (void) strlcpy(portstr, orig_portstr, size);
+ for (i = 0; i < nports; i++)
+ WRITE_PORT(portstr, ports[i].lp_linkid, size);
+ } else {
+ char *next;
+ datalink_id_t portid;
+ uint32_t remove = 0;
+
+ for (next = orig_portstr, j = 0; j < orig_nports; j++) {
+ /*
+ * Read the portids from the old configuration
+ * one by one.
+ */
+ READ_PORT(next, portid, status);
+ if (status != DLADM_STATUS_OK) {
+ free(portstr);
+ goto destroyconf;
+ }
+
+ /*
+ * See whether this port is in the removal
+ * list. If not, copy to the new config.
+ */
+ for (i = 0; i < nports; i++) {
+ if (ports[i].lp_linkid == portid)
+ break;
+ }
+ if (i == nports) {
+ WRITE_PORT(portstr, portid, size);
+ } else {
+ remove++;
+ }
+ }
+ if (remove != nports) {
+ status = DLADM_STATUS_LINKINVAL;
+ free(portstr);
+ goto destroyconf;
+ }
+ result_nports -= nports;
+ }
+
+ u64 = result_nports;
+ if ((status = dladm_set_conf_field(conf, FNPORTS,
+ DLADM_TYPE_UINT64, &u64)) != DLADM_STATUS_OK) {
+ free(portstr);
+ goto destroyconf;
+ }
- iocp->la_key = attr->lt_key;
- iocp->la_nports = attr->lt_nports;
- ports = (laioc_port_t *)(iocp + 1);
+ status = dladm_set_conf_field(conf, FPORTS, DLADM_TYPE_STR,
+ portstr);
+ free(portstr);
+ if (status != DLADM_STATUS_OK)
+ goto destroyconf;
- for (i = 0; i < attr->lt_nports; i++) {
- if (strlcpy(ports[i].lp_devname,
- attr->lt_ports[i].lp_devname,
- MAXNAMELEN) >= MAXNAMELEN) {
- status = DLADM_STATUS_BADARG;
- goto done;
+ /*
+ * Write the new configuration to the persistent repository.
+ */
+ status = dladm_write_conf(conf);
+
+destroyconf:
+ dladm_destroy_conf(conf);
+ if (status != DLADM_STATUS_OK) {
+ free(orig_portstr);
+ return (status);
}
}
- if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0) {
- status = dladm_errno2status(errno);
+ /*
+ * If the caller only requested to update the persistent
+ * configuration, we are done.
+ */
+ if (!(flags & DLADM_OPT_ACTIVE))
goto done;
- }
- rc = i_dladm_ioctl(fd, cmd, iocp, len);
- if (rc < 0) {
- if (errno == EINVAL)
- status = DLADM_STATUS_LINKINVAL;
- else
- status = dladm_errno2status(errno);
+ /*
+ * Update the active configuration.
+ */
+ len = sizeof (*iocp) + nports * sizeof (laioc_port_t);
+ if ((iocp = malloc(len)) == NULL) {
+ status = DLADM_STATUS_NOMEM;
+ goto done;
}
- (void) close(fd);
+ iocp->la_linkid = linkid;
+ iocp->la_nports = nports;
+ if (cmd == LAIOC_ADD)
+ iocp->la_force = (flags & DLADM_OPT_FORCE);
+
+ ioc_ports = (laioc_port_t *)(iocp + 1);
+ for (i = 0; i < nports; i++)
+ ioc_ports[i].lp_linkid = ports[i].lp_linkid;
+
+ if (i_dladm_aggr_strioctl(cmd, iocp, len) < 0)
+ status = dladm_errno2status(errno);
done:
free(iocp);
+
+ /*
+ * If the active configuration update fails, restore the old
+ * persistent configuration if we've changed that.
+ */
+ if ((status != DLADM_STATUS_OK) && (flags & DLADM_OPT_PERSIST)) {
+ if (dladm_read_conf(linkid, &conf) == DLADM_STATUS_OK) {
+ u64 = orig_nports;
+ if ((dladm_set_conf_field(conf, FNPORTS,
+ DLADM_TYPE_UINT64, &u64) == DLADM_STATUS_OK) &&
+ (dladm_set_conf_field(conf, FPORTS, DLADM_TYPE_STR,
+ orig_portstr) == DLADM_STATUS_OK)) {
+ (void) dladm_write_conf(conf);
+ }
+ (void) dladm_destroy_conf(conf);
+ }
+ }
+ free(orig_portstr);
return (status);
}
@@ -555,14 +579,12 @@ done:
* Send a modify command to the link aggregation driver.
*/
static dladm_status_t
-i_dladm_aggr_modify_sys(uint32_t key, uint32_t mask,
+i_dladm_aggr_modify_sys(datalink_id_t linkid, uint32_t mask,
dladm_aggr_modify_attr_t *attr)
{
- int rc, fd;
laioc_modify_t ioc;
- dladm_status_t status = DLADM_STATUS_OK;
- ioc.lu_key = key;
+ ioc.lu_linkid = linkid;
ioc.lu_modify_mask = 0;
if (mask & DLADM_AGGR_MODIFY_POLICY)
@@ -580,68 +602,60 @@ i_dladm_aggr_modify_sys(uint32_t key, uint32_t mask,
ioc.lu_lacp_mode = attr->ld_lacp_mode;
ioc.lu_lacp_timer = attr->ld_lacp_timer;
- if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0)
- return (dladm_errno2status(errno));
-
- rc = i_dladm_ioctl(fd, LAIOC_MODIFY, &ioc, sizeof (ioc));
- if (rc < 0) {
+ if (i_dladm_aggr_strioctl(LAIOC_MODIFY, &ioc, sizeof (ioc)) < 0) {
if (errno == EINVAL)
- status = DLADM_STATUS_MACADDRINVAL;
+ return (DLADM_STATUS_MACADDRINVAL);
else
- status = dladm_errno2status(errno);
+ return (dladm_errno2status(errno));
+ } else {
+ return (DLADM_STATUS_OK);
}
-
- (void) close(fd);
- return (status);
}
/*
* Send a create command to the link aggregation driver.
*/
static dladm_status_t
-i_dladm_aggr_create_sys(int fd, dladm_aggr_grp_attr_db_t *attr)
+i_dladm_aggr_create_sys(datalink_id_t linkid, uint16_t key, uint32_t nports,
+ dladm_aggr_port_attr_db_t *ports, uint32_t policy,
+ boolean_t mac_addr_fixed, const uchar_t *mac_addr,
+ aggr_lacp_mode_t lacp_mode, aggr_lacp_timer_t lacp_timer, boolean_t force)
{
int i, rc, len;
- laioc_create_t *iocp;
- laioc_port_t *ports;
+ laioc_create_t *iocp = NULL;
+ laioc_port_t *ioc_ports;
dladm_status_t status = DLADM_STATUS_OK;
- len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
+ len = sizeof (*iocp) + nports * sizeof (laioc_port_t);
iocp = malloc(len);
if (iocp == NULL)
return (DLADM_STATUS_NOMEM);
- iocp->lc_key = attr->lt_key;
- iocp->lc_nports = attr->lt_nports;
- iocp->lc_policy = attr->lt_policy;
- iocp->lc_lacp_mode = attr->lt_lacp_mode;
- iocp->lc_lacp_timer = attr->lt_lacp_timer;
-
- ports = (laioc_port_t *)(iocp + 1);
+ iocp->lc_key = key;
+ iocp->lc_linkid = linkid;
+ iocp->lc_nports = nports;
+ iocp->lc_policy = policy;
+ iocp->lc_lacp_mode = lacp_mode;
+ iocp->lc_lacp_timer = lacp_timer;
+ ioc_ports = (laioc_port_t *)(iocp + 1);
+ iocp->lc_force = force;
- for (i = 0; i < attr->lt_nports; i++) {
- if (strlcpy(ports[i].lp_devname,
- attr->lt_ports[i].lp_devname,
- MAXNAMELEN) >= MAXNAMELEN) {
- free(iocp);
- return (DLADM_STATUS_BADARG);
- }
- }
+ for (i = 0; i < nports; i++)
+ ioc_ports[i].lp_linkid = ports[i].lp_linkid;
- if (attr->lt_mac_fixed &&
- ((bcmp(zero_mac, attr->lt_mac, ETHERADDRL) == 0) ||
- (attr->lt_mac[0] & 0x01))) {
- free(iocp);
- return (DLADM_STATUS_MACADDRINVAL);
+ if (mac_addr_fixed && !VALID_PORT_MAC(mac_addr)) {
+ status = DLADM_STATUS_MACADDRINVAL;
+ goto done;
}
- bcopy(attr->lt_mac, iocp->lc_mac, ETHERADDRL);
- iocp->lc_mac_fixed = attr->lt_mac_fixed;
+ bcopy(mac_addr, iocp->lc_mac, ETHERADDRL);
+ iocp->lc_mac_fixed = mac_addr_fixed;
- rc = i_dladm_ioctl(fd, LAIOC_CREATE, iocp, len);
+ rc = i_dladm_aggr_strioctl(LAIOC_CREATE, iocp, len);
if (rc < 0)
- status = DLADM_STATUS_LINKINVAL;
+ status = dladm_errno2status(errno);
+done:
free(iocp);
return (status);
}
@@ -649,518 +663,109 @@ i_dladm_aggr_create_sys(int fd, dladm_aggr_grp_attr_db_t *attr)
/*
* Invoked to bring up a link aggregation group.
*/
-static dladm_status_t
-i_dladm_aggr_up(void *arg, dladm_aggr_grp_attr_db_t *attr)
-{
- dladm_aggr_up_t *up = (dladm_aggr_up_t *)arg;
- dladm_status_t status;
-
- if (up->lu_key != 0 && up->lu_key != attr->lt_key)
- return (DLADM_STATUS_OK);
-
- up->lu_found = B_TRUE;
-
- status = i_dladm_aggr_create_sys(up->lu_fd, attr);
- if (status != DLADM_STATUS_OK && up->lu_key != 0)
- return (status);
-
- return (DLADM_STATUS_OK);
-}
-
-/*
- * Bring up a link aggregation group or all of them if the key is zero.
- * If key is 0, walk may terminate early if any of the links fail
- */
-dladm_status_t
-dladm_aggr_up(uint32_t key, const char *root)
+static int
+i_dladm_aggr_up(datalink_id_t linkid, void *arg)
{
- dladm_aggr_up_t up;
+ dladm_status_t *statusp = (dladm_status_t *)arg;
+ dladm_aggr_grp_attr_t attr;
+ dladm_aggr_port_attr_db_t *ports = NULL;
+ uint16_t key = 0;
+ int i, j;
dladm_status_t status;
- if ((up.lu_fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0)
- return (dladm_errno2status(errno));
-
- up.lu_key = key;
- up.lu_found = B_FALSE;
-
- status = i_dladm_aggr_walk_db(i_dladm_aggr_up, &up, root);
+ status = dladm_aggr_info(linkid, &attr, DLADM_OPT_PERSIST);
if (status != DLADM_STATUS_OK) {
- (void) close(up.lu_fd);
- return (status);
+ *statusp = status;
+ return (DLADM_WALK_CONTINUE);
}
- (void) close(up.lu_fd);
-
- /*
- * only return error if user specified key and key was
- * not found
- */
- if (!up.lu_found && key != 0)
- return (DLADM_STATUS_NOTFOUND);
-
- return (DLADM_STATUS_OK);
-}
-/*
- * Send a delete command to the link aggregation driver.
- */
-static int
-i_dladm_aggr_delete_sys(int fd, dladm_aggr_grp_attr_t *attr)
-{
- laioc_delete_t ioc;
-
- ioc.ld_key = attr->lg_key;
-
- return (i_dladm_ioctl(fd, LAIOC_DELETE, &ioc, sizeof (ioc)));
-}
-
-/*
- * Invoked to bring down a link aggregation group.
- */
-static int
-i_dladm_aggr_down(void *arg, dladm_aggr_grp_attr_t *attr)
-{
- dladm_aggr_down_t *down = (dladm_aggr_down_t *)arg;
- int fd, errno_save;
-
- if (down->ld_key != 0 && down->ld_key != attr->lg_key)
- return (0);
- down->ld_found = B_TRUE;
-
- if ((fd = open(DLADM_AGGR_DEV, O_RDWR)) < 0)
- return (-1);
+ if (attr.lg_key <= AGGR_MAX_KEY)
+ key = attr.lg_key;
- if (i_dladm_aggr_delete_sys(fd, attr) < 0 && down->ld_key != 0) {
- errno_save = errno;
- (void) close(fd);
- errno = errno_save;
- return (-1);
+ ports = malloc(attr.lg_nports * sizeof (dladm_aggr_port_attr_db_t));
+ if (ports == NULL) {
+ status = DLADM_STATUS_NOMEM;
+ goto done;
}
- (void) close(fd);
- return (0);
-}
-
-/*
- * Bring down a link aggregation group or all of them if the key is zero.
- * If key is 0, walk may terminate early if any of the links fail
- */
-dladm_status_t
-dladm_aggr_down(uint32_t key)
-{
- dladm_aggr_down_t down;
-
- down.ld_key = key;
- down.ld_found = B_FALSE;
-
- if (dladm_aggr_walk(i_dladm_aggr_down, &down) < 0)
- return (dladm_errno2status(errno));
-
/*
- * only return error if user specified key and key was
- * not found
+ * Validate (and purge) each physical link associated with this
+ * aggregation, if the specific hardware has been removed during
+ * the system shutdown.
*/
- if (!down.ld_found && key != 0)
- return (DLADM_STATUS_NOTFOUND);
+ for (i = 0, j = 0; i < attr.lg_nports; i++) {
+ datalink_id_t portid = attr.lg_ports[i].lp_linkid;
+ uint32_t flags;
+ dladm_status_t s;
- return (DLADM_STATUS_OK);
-}
-
-/*
- * For each group <grp> found in the DB, invokes <fn>(<grp>, <arg>).
- *
- * The following values can be returned by <fn>():
- *
- * -1: an error occured. This will cause the walk to be terminated,
- * and the original DB file to be preserved.
- *
- * 0: success and write. The walker will write the contents of
- * the attribute passed as argument to <fn>(), and continue walking
- * the entries found in the DB.
- *
- * 1: skip. The walker should not write the contents of the current
- * group attributes to the new DB, but should continue walking
- * the entries found in the DB.
- */
-static dladm_status_t
-i_dladm_aggr_walk_rw_db(int (*fn)(void *, dladm_aggr_grp_attr_db_t *),
- void *arg, const char *root)
-{
- FILE *fp, *nfp;
- int nfd, fn_rc, lock_fd;
- char line[MAXLINELEN];
- dladm_aggr_grp_attr_db_t attr;
- char *db_file, *tmp_db_file;
- char db_file_buf[MAXPATHLEN];
- char tmp_db_file_buf[MAXPATHLEN];
- dladm_status_t status;
-
- if (root == NULL) {
- db_file = DLADM_AGGR_DB;
- tmp_db_file = DLADM_AGGR_DB_TMP;
- } else {
- (void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
- DLADM_AGGR_DB);
- (void) snprintf(tmp_db_file_buf, MAXPATHLEN, "%s%s", root,
- DLADM_AGGR_DB_TMP);
- db_file = db_file_buf;
- tmp_db_file = tmp_db_file_buf;
- }
-
- if ((lock_fd = i_dladm_aggr_lock_db(F_WRLCK)) < 0)
- return (dladm_errno2status(errno));
-
- if ((fp = fopen(db_file, "r")) == NULL) {
- status = dladm_errno2status(errno);
- i_dladm_aggr_unlock_db(lock_fd);
- return (status);
- }
-
- if ((nfd = open(tmp_db_file, O_WRONLY|O_CREAT|O_TRUNC,
- DLADM_AGGR_DB_PERMS)) == -1) {
- status = dladm_errno2status(errno);
- (void) fclose(fp);
- i_dladm_aggr_unlock_db(lock_fd);
- return (status);
- }
-
- if ((nfp = fdopen(nfd, "w")) == NULL) {
- status = dladm_errno2status(errno);
- (void) close(nfd);
- (void) fclose(fp);
- (void) unlink(tmp_db_file);
- i_dladm_aggr_unlock_db(lock_fd);
- return (status);
- }
-
- attr.lt_ports = NULL;
-
- while (fgets(line, MAXLINELEN, fp) != NULL) {
-
- /* skip comments */
- if (BLANK_LINE(line)) {
- if (fputs(line, nfp) == EOF) {
- status = dladm_errno2status(errno);
- goto failed;
- }
+ s = dladm_datalink_id2info(portid, &flags, NULL, NULL, NULL, 0);
+ if (s != DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE))
continue;
- }
-
- if (i_dladm_aggr_parse_db(line, &attr) != 0) {
- status = DLADM_STATUS_REPOSITORYINVAL;
- goto failed;
- }
-
- fn_rc = fn(arg, &attr);
-
- switch (fn_rc) {
- case -1:
- /* failure, stop walking */
- status = dladm_errno2status(errno);
- goto failed;
- case 0:
- /*
- * Success, write group attributes, which could
- * have been modified by fn().
- */
- if (i_dladm_aggr_fput_grp(nfp, &attr) != 0) {
- status = dladm_errno2status(errno);
- goto failed;
- }
- break;
- case 1:
- /* skip current group */
- break;
- }
-
- free(attr.lt_ports);
- attr.lt_ports = NULL;
- }
-
- if (getuid() == 0 || geteuid() == 0) {
- if (fchmod(nfd, DLADM_AGGR_DB_PERMS) == -1) {
- status = dladm_errno2status(errno);
- goto failed;
- }
-
- if (fchown(nfd, DLADM_AGGR_DB_OWNER,
- DLADM_AGGR_DB_GROUP) == -1) {
- status = dladm_errno2status(errno);
- goto failed;
- }
- }
-
- if (fflush(nfp) == EOF) {
- status = dladm_errno2status(errno);
- goto failed;
- }
-
- (void) fclose(fp);
- (void) fclose(nfp);
-
- if (rename(tmp_db_file, db_file) == -1) {
- status = dladm_errno2status(errno);
- (void) unlink(tmp_db_file);
- i_dladm_aggr_unlock_db(lock_fd);
- return (status);
- }
- i_dladm_aggr_unlock_db(lock_fd);
- return (DLADM_STATUS_OK);
-
-failed:
- free(attr.lt_ports);
- (void) fclose(fp);
- (void) fclose(nfp);
- (void) unlink(tmp_db_file);
- i_dladm_aggr_unlock_db(lock_fd);
-
- return (status);
-}
-
-/*
- * Remove an entry from the DB.
- */
-static int
-i_dladm_aggr_del_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
-{
- delete_db_state_t *state = arg;
-
- if (grp->lt_key != state->ds_key)
- return (0);
-
- state->ds_found = B_TRUE;
-
- /* don't save matching group */
- return (1);
-}
-
-static dladm_status_t
-i_dladm_aggr_del_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
-{
- delete_db_state_t state;
- dladm_status_t status;
-
- state.ds_key = attr->lt_key;
- state.ds_found = B_FALSE;
-
- status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_del_db_fn, &state, root);
- if (status != DLADM_STATUS_OK)
- return (status);
-
- if (!state.ds_found)
- return (DLADM_STATUS_NOTFOUND);
-
- return (DLADM_STATUS_OK);
-}
-
-/*
- * Modify the properties of an existing group in the DB.
- */
-static int
-i_dladm_aggr_modify_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
-{
- modify_db_state_t *state = arg;
- dladm_aggr_modify_attr_t *new_attr = state->us_attr_new;
- dladm_aggr_modify_attr_t *old_attr = state->us_attr_old;
-
- if (grp->lt_key != state->us_key)
- return (0);
-
- state->us_found = B_TRUE;
-
- if (state->us_mask & DLADM_AGGR_MODIFY_POLICY) {
- if (old_attr != NULL)
- old_attr->ld_policy = grp->lt_policy;
- grp->lt_policy = new_attr->ld_policy;
+ ports[j++].lp_linkid = portid;
}
- if (state->us_mask & DLADM_AGGR_MODIFY_MAC) {
- if (old_attr != NULL) {
- old_attr->ld_mac_fixed = grp->lt_mac_fixed;
- bcopy(grp->lt_mac, old_attr->ld_mac, ETHERADDRL);
- }
- grp->lt_mac_fixed = new_attr->ld_mac_fixed;
- bcopy(new_attr->ld_mac, grp->lt_mac, ETHERADDRL);
+ if (j == 0) {
+ /*
+ * All of the physical links are removed.
+ */
+ status = DLADM_STATUS_BADARG;
+ goto done;
}
- if (state->us_mask & DLADM_AGGR_MODIFY_LACP_MODE) {
- if (old_attr != NULL)
- old_attr->ld_lacp_mode = grp->lt_lacp_mode;
- grp->lt_lacp_mode = new_attr->ld_lacp_mode;
+ /*
+ * Create active aggregation.
+ */
+ if ((status = i_dladm_aggr_create_sys(linkid,
+ key, j, ports, attr.lg_policy, attr.lg_mac_fixed,
+ (const uchar_t *)attr.lg_mac, attr.lg_lacp_mode,
+ attr.lg_lacp_timer, attr.lg_force)) != DLADM_STATUS_OK) {
+ goto done;
}
- if (state->us_mask & DLADM_AGGR_MODIFY_LACP_TIMER) {
- if (old_attr != NULL)
- old_attr->ld_lacp_timer = grp->lt_lacp_timer;
- grp->lt_lacp_timer = new_attr->ld_lacp_timer;
+ if ((status = dladm_up_datalink_id(linkid)) != DLADM_STATUS_OK) {
+ laioc_delete_t ioc;
+ ioc.ld_linkid = linkid;
+ (void) i_dladm_aggr_strioctl(LAIOC_DELETE, &ioc, sizeof (ioc));
+ goto done;
}
- /* save modified group */
- return (0);
-}
-
-static dladm_status_t
-i_dladm_aggr_modify_db(uint32_t key, uint32_t mask,
- dladm_aggr_modify_attr_t *new, dladm_aggr_modify_attr_t *old,
- const char *root)
-{
- modify_db_state_t state;
- dladm_status_t status;
-
- state.us_key = key;
- state.us_mask = mask;
- state.us_attr_new = new;
- state.us_attr_old = old;
- state.us_found = B_FALSE;
-
- if ((status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_modify_db_fn,
- &state, root)) != DLADM_STATUS_OK) {
- return (status);
- }
+ /*
+ * Reset the active linkprop of this specific link.
+ */
+ (void) dladm_init_linkprop(linkid);
- if (!state.us_found)
- return (DLADM_STATUS_NOTFOUND);
+done:
+ free(attr.lg_ports);
+ free(ports);
- return (DLADM_STATUS_OK);
+ *statusp = status;
+ return (DLADM_WALK_CONTINUE);
}
/*
- * Add ports to an existing group in the DB.
+ * Bring up one aggregation, or all persistent aggregations. In the latter
+ * case, the walk may terminate early if bringup of an aggregation fails.
*/
-static int
-i_dladm_aggr_add_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
-{
- add_db_state_t *state = arg;
- dladm_aggr_grp_attr_db_t *attr = state->as_attr;
- void *ports;
- int i, j;
-
- if (grp->lt_key != attr->lt_key)
- return (0);
-
- state->as_found = B_TRUE;
-
- /* are any of the ports to be added already members of the group? */
- for (i = 0; i < grp->lt_nports; i++) {
- for (j = 0; j < attr->lt_nports; j++) {
- if (strcmp(grp->lt_ports[i].lp_devname,
- attr->lt_ports[j].lp_devname) == 0) {
- errno = EEXIST;
- return (-1);
- }
- }
- }
-
- /* add groups specified by attr to grp */
- ports = realloc(grp->lt_ports, (grp->lt_nports +
- attr->lt_nports) * sizeof (dladm_aggr_port_attr_db_t));
- if (ports == NULL)
- return (-1);
- grp->lt_ports = ports;
-
- for (i = 0; i < attr->lt_nports; i++) {
- if (strlcpy(grp->lt_ports[grp->lt_nports + i].lp_devname,
- attr->lt_ports[i].lp_devname, MAXNAMELEN + 1) >=
- MAXNAMELEN + 1)
- return (-1);
- }
-
- grp->lt_nports += attr->lt_nports;
-
- /* save modified group */
- return (0);
-}
-
-static dladm_status_t
-i_dladm_aggr_add_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
+dladm_status_t
+dladm_aggr_up(datalink_id_t linkid)
{
- add_db_state_t state;
dladm_status_t status;
- state.as_attr = attr;
- state.as_found = B_FALSE;
-
- status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_add_db_fn, &state, root);
- if (status != DLADM_STATUS_OK)
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(i_dladm_aggr_up, &status,
+ DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_PERSIST);
+ return (DLADM_STATUS_OK);
+ } else {
+ (void) i_dladm_aggr_up(linkid, &status);
return (status);
-
- if (!state.as_found)
- return (DLADM_STATUS_NOTFOUND);
-
- return (DLADM_STATUS_OK);
-}
-
-/*
- * Remove ports from an existing group in the DB.
- */
-
-typedef struct remove_db_state {
- dladm_aggr_grp_attr_db_t *rs_attr;
- boolean_t rs_found;
-} remove_db_state_t;
-
-static int
-i_dladm_aggr_remove_db_fn(void *arg, dladm_aggr_grp_attr_db_t *grp)
-{
- remove_db_state_t *state = (remove_db_state_t *)arg;
- dladm_aggr_grp_attr_db_t *attr = state->rs_attr;
- int i, j, k, nremoved;
- boolean_t match;
-
- if (grp->lt_key != attr->lt_key)
- return (0);
-
- state->rs_found = B_TRUE;
-
- /* remove the ports specified by attr from the group */
- nremoved = 0;
- k = 0;
- for (i = 0; i < grp->lt_nports; i++) {
- match = B_FALSE;
- for (j = 0; j < attr->lt_nports && !match; j++) {
- match = (strcmp(grp->lt_ports[i].lp_devname,
- attr->lt_ports[j].lp_devname) == 0);
- }
- if (match)
- nremoved++;
- else
- grp->lt_ports[k++] = grp->lt_ports[i];
- }
-
- if (nremoved != attr->lt_nports) {
- errno = ENOENT;
- return (-1);
}
-
- grp->lt_nports -= nremoved;
-
- /* save modified group */
- return (0);
-}
-
-static dladm_status_t
-i_dladm_aggr_remove_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
-{
- remove_db_state_t state;
- dladm_status_t status;
-
- state.rs_attr = attr;
- state.rs_found = B_FALSE;
-
- status = i_dladm_aggr_walk_rw_db(i_dladm_aggr_remove_db_fn,
- &state, root);
- if (status != DLADM_STATUS_OK)
- return (status);
-
- if (!state.rs_found)
- return (DLADM_STATUS_NOTFOUND);
-
- return (DLADM_STATUS_OK);
}
/*
* Given a policy string, return a policy mask. Returns B_TRUE on
- * success, or B_FALSE if an error occured during parsing.
+ * success, or B_FALSE if an error occurred during parsing.
*/
boolean_t
dladm_aggr_str2policy(const char *str, uint32_t *policy)
@@ -1199,6 +804,9 @@ dladm_aggr_policy2str(uint32_t policy, char *str)
int i, npolicies = 0;
policy_t *pol;
+ if (str == NULL)
+ return (NULL);
+
str[0] = '\0';
for (i = 0; i < NPOLICIES; i++) {
@@ -1206,8 +814,8 @@ dladm_aggr_policy2str(uint32_t policy, char *str)
if ((policy & pol->policy) != 0) {
npolicies++;
if (npolicies > 1)
- (void) strcat(str, ",");
- (void) strcat(str, pol->pol_name);
+ (void) strlcat(str, ",", DLADM_STRSIZE);
+ (void) strlcat(str, pol->pol_name, DLADM_STRSIZE);
}
}
@@ -1257,7 +865,7 @@ dladm_aggr_str2macaddr(const char *str, boolean_t *mac_fixed, uchar_t *mac_addr)
* Returns a string containing a printable representation of a MAC address.
*/
const char *
-dladm_aggr_macaddr2str(unsigned char *mac, char *buf)
+dladm_aggr_macaddr2str(const unsigned char *mac, char *buf)
{
static char unknown_mac[] = {0, 0, 0, 0, 0, 0};
@@ -1265,9 +873,11 @@ dladm_aggr_macaddr2str(unsigned char *mac, char *buf)
return (NULL);
if (bcmp(unknown_mac, mac, ETHERADDRL) == 0)
- return (gettext("<unknown>"));
+ (void) strlcpy(buf, "unknown", DLADM_STRSIZE);
else
return (_link_ntoa(mac, buf, ETHERADDRL, IFT_OTHER));
+
+ return (buf);
}
/*
@@ -1302,6 +912,9 @@ dladm_aggr_lacpmode2str(aggr_lacp_mode_t mode_id, char *buf)
int i;
dladm_aggr_lacpmode_t *mode;
+ if (buf == NULL)
+ return (NULL);
+
for (i = 0; i < NLACP_MODES; i++) {
mode = &lacp_modes[i];
if (mode->mode_id == mode_id) {
@@ -1347,6 +960,9 @@ dladm_aggr_lacptimer2str(aggr_lacp_timer_t timer_id, char *buf)
int i;
dladm_aggr_lacptimer_t *timer;
+ if (buf == NULL)
+ return (NULL);
+
for (i = 0; i < NLACP_TIMERS; i++) {
timer = &lacp_timers[i];
if (timer->lt_id == timer_id) {
@@ -1364,7 +980,10 @@ const char *
dladm_aggr_portstate2str(aggr_port_state_t state_id, char *buf)
{
int i;
- dladm_aggr_port_state_t *state;
+ dladm_aggr_port_state_t *state;
+
+ if (buf == NULL)
+ return (NULL);
for (i = 0; i < NPORT_STATES; i++) {
state = &port_states[i];
@@ -1379,123 +998,94 @@ dladm_aggr_portstate2str(aggr_port_state_t state_id, char *buf)
return (buf);
}
-#define FPRINTF_ERR(fcall) if ((fcall) < 0) return (-1);
-
-/*
- * Write the attribute of a group to the specified file. Returns 0 on
- * success, -1 on failure.
- */
-static int
-i_dladm_aggr_fput_grp(FILE *fp, dladm_aggr_grp_attr_db_t *attr)
+static dladm_status_t
+dladm_aggr_persist_aggr_conf(const char *link, datalink_id_t linkid,
+ uint16_t key, uint32_t nports, dladm_aggr_port_attr_db_t *ports,
+ uint32_t policy, boolean_t mac_addr_fixed, const uchar_t *mac_addr,
+ aggr_lacp_mode_t lacp_mode, aggr_lacp_timer_t lacp_timer,
+ boolean_t force)
{
- int i;
- char addr_str[ETHERADDRL * 3];
- char buf[DLADM_STRSIZE];
-
- /* key, policy */
- FPRINTF_ERR(fprintf(fp, "%d\t%s\t", attr->lt_key,
- dladm_aggr_policy2str(attr->lt_policy, buf)));
-
- /* number of ports, ports */
- FPRINTF_ERR(fprintf(fp, "%d\t", attr->lt_nports));
- for (i = 0; i < attr->lt_nports; i++) {
- if (i > 0)
- FPRINTF_ERR(fprintf(fp, ","));
- FPRINTF_ERR(fprintf(fp, "%s", attr->lt_ports[i].lp_devname));
- }
- FPRINTF_ERR(fprintf(fp, "\t"));
+ dladm_conf_t conf = DLADM_INVALID_CONF;
+ char *portstr = NULL;
+ char macstr[ETHERADDRL * 3];
+ dladm_status_t status;
+ int i, size;
+ uint64_t u64;
- /* MAC address */
- if (!attr->lt_mac_fixed) {
- FPRINTF_ERR(fprintf(fp, "auto"));
- } else {
- FPRINTF_ERR(fprintf(fp, "%s",
- dladm_aggr_macaddr2str(attr->lt_mac, addr_str)));
+ if ((status = dladm_create_conf(link, linkid, DATALINK_CLASS_AGGR,
+ DL_ETHER, &conf)) != DLADM_STATUS_OK) {
+ return (status);
}
- FPRINTF_ERR(fprintf(fp, "\t"));
-
- FPRINTF_ERR(fprintf(fp, "%s\t",
- dladm_aggr_lacpmode2str(attr->lt_lacp_mode, buf)));
-
- FPRINTF_ERR(fprintf(fp, "%s\n",
- dladm_aggr_lacptimer2str(attr->lt_lacp_timer, buf)));
- return (0);
-}
+ u64 = key;
+ status = dladm_set_conf_field(conf, FKEY, DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
-static dladm_status_t
-i_dladm_aggr_create_db(dladm_aggr_grp_attr_db_t *attr, const char *root)
-{
- FILE *fp;
- char line[MAXLINELEN];
- uint32_t key;
- int lock_fd;
- char *db_file;
- char db_file_buf[MAXPATHLEN];
- char *endp = NULL;
- dladm_status_t status;
+ u64 = nports;
+ status = dladm_set_conf_field(conf, FNPORTS, DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
- if (root == NULL) {
- db_file = DLADM_AGGR_DB;
- } else {
- (void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
- DLADM_AGGR_DB);
- db_file = db_file_buf;
+ size = nports * (LINKID_STR_WIDTH + 1) + 1;
+ if ((portstr = calloc(1, size)) == NULL) {
+ status = DLADM_STATUS_NOMEM;
+ goto done;
}
- if ((lock_fd = i_dladm_aggr_lock_db(F_WRLCK)) < 0)
- return (dladm_errno2status(errno));
+ for (i = 0; i < nports; i++)
+ WRITE_PORT(portstr, ports[i].lp_linkid, size);
+ status = dladm_set_conf_field(conf, FPORTS, DLADM_TYPE_STR, portstr);
+ free(portstr);
- if ((fp = fopen(db_file, "r+")) == NULL &&
- (fp = fopen(db_file, "w")) == NULL) {
- status = dladm_errno2status(errno);
- i_dladm_aggr_unlock_db(lock_fd);
- return (status);
- }
-
- /* look for existing group with same key */
- while (fgets(line, MAXLINELEN, fp) != NULL) {
- char *holder, *lasts;
+ if (status != DLADM_STATUS_OK)
+ goto done;
- /* skip comments */
- if (BLANK_LINE(line))
- continue;
+ u64 = policy;
+ status = dladm_set_conf_field(conf, FPOLICY, DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
- /* ignore corrupted lines */
- holder = strtok_r(line, " \t", &lasts);
- if (holder == NULL)
- continue;
+ status = dladm_set_conf_field(conf, FFIXMACADDR, DLADM_TYPE_BOOLEAN,
+ &mac_addr_fixed);
+ if (status != DLADM_STATUS_OK)
+ goto done;
- /* port number */
- errno = 0;
- key = (int)strtol(holder, &endp, 10);
- if (errno != 0 || *endp != '\0') {
- status = DLADM_STATUS_REPOSITORYINVAL;
+ if (mac_addr_fixed) {
+ if (!VALID_PORT_MAC(mac_addr)) {
+ status = DLADM_STATUS_MACADDRINVAL;
goto done;
}
- if (key == attr->lt_key) {
- /* group with key already exists */
- status = DLADM_STATUS_EXIST;
+ (void) dladm_aggr_macaddr2str(mac_addr, macstr);
+ status = dladm_set_conf_field(conf, FMACADDR, DLADM_TYPE_STR,
+ macstr);
+ if (status != DLADM_STATUS_OK)
goto done;
- }
}
- /*
- * If we get here, we've verified that no existing group with
- * the same key already exists. It's now time to add the
- * new group to the DB.
- */
- if (i_dladm_aggr_fput_grp(fp, attr) != 0) {
- status = dladm_errno2status(errno);
+ status = dladm_set_conf_field(conf, FFORCE, DLADM_TYPE_BOOLEAN, &force);
+ if (status != DLADM_STATUS_OK)
goto done;
- }
- status = DLADM_STATUS_OK;
+ u64 = lacp_mode;
+ status = dladm_set_conf_field(conf, FLACPMODE, DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ u64 = lacp_timer;
+ status = dladm_set_conf_field(conf, FLACPTIMER, DLADM_TYPE_UINT64,
+ &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ /*
+ * Commit the link aggregation configuration.
+ */
+ status = dladm_write_conf(conf);
done:
- (void) fclose(fp);
- i_dladm_aggr_unlock_db(lock_fd);
+ dladm_destroy_conf(conf);
return (status);
}
@@ -1504,60 +1094,168 @@ done:
* file and bring it up.
*/
dladm_status_t
-dladm_aggr_create(uint32_t key, uint32_t nports,
+dladm_aggr_create(const char *name, uint16_t key, uint32_t nports,
dladm_aggr_port_attr_db_t *ports, uint32_t policy, boolean_t mac_addr_fixed,
- uchar_t *mac_addr, aggr_lacp_mode_t lacp_mode, aggr_lacp_timer_t lacp_timer,
- boolean_t tempop, const char *root)
+ const uchar_t *mac_addr, aggr_lacp_mode_t lacp_mode,
+ aggr_lacp_timer_t lacp_timer, uint32_t flags)
{
- dladm_aggr_grp_attr_db_t attr;
+ datalink_id_t linkid = DATALINK_INVALID_LINKID;
+ uint32_t media;
+ uint32_t i;
+ datalink_class_t class;
dladm_status_t status;
+ boolean_t force = (flags & DLADM_OPT_FORCE) ? B_TRUE : B_FALSE;
- if (key == 0 || key > DLADM_AGGR_MAX_KEY)
+ if (key != 0 && key > AGGR_MAX_KEY)
return (DLADM_STATUS_KEYINVAL);
- attr.lt_key = key;
- attr.lt_nports = nports;
- attr.lt_ports = ports;
- attr.lt_policy = policy;
- attr.lt_mac_fixed = mac_addr_fixed;
- if (attr.lt_mac_fixed)
- bcopy(mac_addr, attr.lt_mac, ETHERADDRL);
- else
- bzero(attr.lt_mac, ETHERADDRL);
- attr.lt_lacp_mode = lacp_mode;
- attr.lt_lacp_timer = lacp_timer;
+ if (nports == 0)
+ return (DLADM_STATUS_BADARG);
- /* add the link aggregation group to the DB */
- if (!tempop) {
- status = i_dladm_aggr_create_db(&attr, root);
+ for (i = 0; i < nports; i++) {
+ if ((dladm_datalink_id2info(ports[i].lp_linkid, NULL,
+ &class, &media, NULL, 0) != DLADM_STATUS_OK) ||
+ (class != DATALINK_CLASS_PHYS) && (media != DL_ETHER)) {
+ return (DLADM_STATUS_BADARG);
+ }
+ }
+
+ flags &= (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
+ if ((status = dladm_create_datalink_id(name, DATALINK_CLASS_AGGR,
+ DL_ETHER, flags, &linkid)) != DLADM_STATUS_OK) {
+ goto fail;
+ }
+
+ if ((flags & DLADM_OPT_PERSIST) &&
+ (status = dladm_aggr_persist_aggr_conf(name, linkid, key, nports,
+ ports, policy, mac_addr_fixed, mac_addr, lacp_mode, lacp_timer,
+ force)) != DLADM_STATUS_OK) {
+ goto fail;
+ }
+
+ if (!(flags & DLADM_OPT_ACTIVE))
+ return (DLADM_STATUS_OK);
+
+ status = i_dladm_aggr_create_sys(linkid, key, nports, ports, policy,
+ mac_addr_fixed, mac_addr, lacp_mode, lacp_timer, force);
+
+ if (status != DLADM_STATUS_OK) {
+ if (flags & DLADM_OPT_PERSIST)
+ (void) dladm_remove_conf(linkid);
+ goto fail;
+ }
+
+ return (DLADM_STATUS_OK);
+
+fail:
+ if (linkid != DATALINK_INVALID_LINKID)
+ (void) dladm_destroy_datalink_id(linkid, flags);
+
+ return (status);
+}
+
+static dladm_status_t
+i_dladm_aggr_get_aggr_attr(dladm_conf_t conf, uint32_t mask,
+ dladm_aggr_modify_attr_t *attrp)
+{
+ dladm_status_t status = DLADM_STATUS_OK;
+ char macstr[ETHERADDRL * 3];
+ uint64_t u64;
+
+ if (mask & DLADM_AGGR_MODIFY_POLICY) {
+ status = dladm_get_conf_field(conf, FPOLICY, &u64,
+ sizeof (u64));
if (status != DLADM_STATUS_OK)
return (status);
- } else {
- dladm_aggr_up_t up;
+ attrp->ld_policy = (uint32_t)u64;
+ }
- up.lu_key = key;
- up.lu_found = B_FALSE;
- up.lu_fd = open(DLADM_AGGR_DEV, O_RDWR);
- if (up.lu_fd < 0)
- return (dladm_errno2status(errno));
+ if (mask & DLADM_AGGR_MODIFY_MAC) {
+ status = dladm_get_conf_field(conf, FFIXMACADDR,
+ &attrp->ld_mac_fixed, sizeof (boolean_t));
+ if (status != DLADM_STATUS_OK)
+ return (status);
- status = i_dladm_aggr_up((void *)&up, &attr);
- (void) close(up.lu_fd);
- return (status);
+ if (attrp->ld_mac_fixed) {
+ boolean_t fixed;
+
+ status = dladm_get_conf_field(conf, FMACADDR,
+ macstr, sizeof (macstr));
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (!dladm_aggr_str2macaddr(macstr, &fixed,
+ attrp->ld_mac)) {
+ return (DLADM_STATUS_REPOSITORYINVAL);
+ }
+ }
}
- /* bring up the link aggregation group */
- status = dladm_aggr_up(key, root);
- /*
- * If the operation fails because the aggregation already exists,
- * then only update the persistent configuration repository and
- * return success.
- */
- if (status == DLADM_STATUS_EXIST)
- status = DLADM_STATUS_OK;
+ if (mask & DLADM_AGGR_MODIFY_LACP_MODE) {
+ status = dladm_get_conf_field(conf, FLACPMODE, &u64,
+ sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ attrp->ld_lacp_mode = (aggr_lacp_mode_t)u64;
+ }
+
+ if (mask & DLADM_AGGR_MODIFY_LACP_TIMER) {
+ status = dladm_get_conf_field(conf, FLACPTIMER, &u64,
+ sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ attrp->ld_lacp_timer = (aggr_lacp_timer_t)u64;
+ }
+
+ return (status);
+}
+
+static dladm_status_t
+i_dladm_aggr_set_aggr_attr(dladm_conf_t conf, uint32_t mask,
+ dladm_aggr_modify_attr_t *attrp)
+{
+ dladm_status_t status = DLADM_STATUS_OK;
+ char macstr[ETHERADDRL * 3];
+ uint64_t u64;
+
+ if (mask & DLADM_AGGR_MODIFY_POLICY) {
+ u64 = attrp->ld_policy;
+ status = dladm_set_conf_field(conf, FPOLICY, DLADM_TYPE_UINT64,
+ &u64);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ }
+
+ if (mask & DLADM_AGGR_MODIFY_MAC) {
+ status = dladm_set_conf_field(conf, FFIXMACADDR,
+ DLADM_TYPE_BOOLEAN, &attrp->ld_mac_fixed);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (attrp->ld_mac_fixed) {
+ (void) dladm_aggr_macaddr2str(attrp->ld_mac, macstr);
+ status = dladm_set_conf_field(conf, FMACADDR,
+ DLADM_TYPE_STR, macstr);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ }
+ }
+
+ if (mask & DLADM_AGGR_MODIFY_LACP_MODE) {
+ u64 = attrp->ld_lacp_mode;
+ status = dladm_set_conf_field(conf, FLACPMODE,
+ DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ }
- if (status != DLADM_STATUS_OK && !tempop)
- (void) i_dladm_aggr_del_db(&attr, root);
+ if (mask & DLADM_AGGR_MODIFY_LACP_TIMER) {
+ u64 = attrp->ld_lacp_timer;
+ status = dladm_set_conf_field(conf, FLACPTIMER,
+ DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ }
return (status);
}
@@ -1567,146 +1265,211 @@ dladm_aggr_create(uint32_t key, uint32_t nports,
* the configuration file and pass the changes to the kernel.
*/
dladm_status_t
-dladm_aggr_modify(uint32_t key, uint32_t modify_mask, uint32_t policy,
- boolean_t mac_fixed, uchar_t *mac_addr, aggr_lacp_mode_t lacp_mode,
- aggr_lacp_timer_t lacp_timer, boolean_t tempop, const char *root)
+dladm_aggr_modify(datalink_id_t linkid, uint32_t modify_mask, uint32_t policy,
+ boolean_t mac_fixed, const uchar_t *mac_addr, aggr_lacp_mode_t lacp_mode,
+ aggr_lacp_timer_t lacp_timer, uint32_t flags)
{
dladm_aggr_modify_attr_t new_attr, old_attr;
+ dladm_conf_t conf;
dladm_status_t status;
- if (key == 0)
- return (DLADM_STATUS_KEYINVAL);
+ new_attr.ld_policy = policy;
+ new_attr.ld_mac_fixed = mac_fixed;
+ new_attr.ld_lacp_mode = lacp_mode;
+ new_attr.ld_lacp_timer = lacp_timer;
+ bcopy(mac_addr, new_attr.ld_mac, ETHERADDRL);
- if (modify_mask & DLADM_AGGR_MODIFY_POLICY)
- new_attr.ld_policy = policy;
+ if (flags & DLADM_OPT_PERSIST) {
+ status = dladm_read_conf(linkid, &conf);
+ if (status != DLADM_STATUS_OK)
+ return (status);
- if (modify_mask & DLADM_AGGR_MODIFY_MAC) {
- new_attr.ld_mac_fixed = mac_fixed;
- bcopy(mac_addr, new_attr.ld_mac, ETHERADDRL);
- }
+ if ((status = i_dladm_aggr_get_aggr_attr(conf, modify_mask,
+ &old_attr)) != DLADM_STATUS_OK) {
+ goto done;
+ }
- if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE)
- new_attr.ld_lacp_mode = lacp_mode;
+ if ((status = i_dladm_aggr_set_aggr_attr(conf, modify_mask,
+ &new_attr)) != DLADM_STATUS_OK) {
+ goto done;
+ }
- if (modify_mask & DLADM_AGGR_MODIFY_LACP_TIMER)
- new_attr.ld_lacp_timer = lacp_timer;
+ status = dladm_write_conf(conf);
- /* update the DB */
- if (!tempop && ((status = i_dladm_aggr_modify_db(key, modify_mask,
- &new_attr, &old_attr, root)) != DLADM_STATUS_OK)) {
- return (status);
+done:
+ dladm_destroy_conf(conf);
+ if (status != DLADM_STATUS_OK)
+ return (status);
}
- status = i_dladm_aggr_modify_sys(key, modify_mask, &new_attr);
- if (status != DLADM_STATUS_OK && !tempop) {
- (void) i_dladm_aggr_modify_db(key, modify_mask, &old_attr,
- NULL, root);
+ if (!(flags & DLADM_OPT_ACTIVE))
+ return (DLADM_STATUS_OK);
+
+ status = i_dladm_aggr_modify_sys(linkid, modify_mask, &new_attr);
+ if ((status != DLADM_STATUS_OK) && (flags & DLADM_OPT_PERSIST)) {
+ if (dladm_read_conf(linkid, &conf) == DLADM_STATUS_OK) {
+ if (i_dladm_aggr_set_aggr_attr(conf, modify_mask,
+ &old_attr) == DLADM_STATUS_OK) {
+ (void) dladm_write_conf(conf);
+ }
+ dladm_destroy_conf(conf);
+ }
}
return (status);
}
+typedef struct aggr_held_arg_s {
+ datalink_id_t aggrid;
+ boolean_t isheld;
+} aggr_held_arg_t;
+
+static int
+i_dladm_aggr_is_held(datalink_id_t linkid, void *arg)
+{
+ aggr_held_arg_t *aggr_held_arg = arg;
+ dladm_vlan_attr_t dva;
+
+ if (dladm_vlan_info(linkid, &dva, DLADM_OPT_PERSIST) != DLADM_STATUS_OK)
+ return (DLADM_WALK_CONTINUE);
+
+ if (dva.dv_linkid == aggr_held_arg->aggrid) {
+ /*
+ * This VLAN is created over the given aggregation.
+ */
+ aggr_held_arg->isheld = B_TRUE;
+ return (DLADM_WALK_TERMINATE);
+ }
+ return (DLADM_WALK_CONTINUE);
+}
+
/*
- * Delete a previously created link aggregation group.
+ * Delete a previously created link aggregation group. Either the name "aggr"
+ * or the "key" is specified.
*/
dladm_status_t
-dladm_aggr_delete(uint32_t key, boolean_t tempop, const char *root)
+dladm_aggr_delete(datalink_id_t linkid, uint32_t flags)
{
- dladm_aggr_grp_attr_db_t db_attr;
+ laioc_delete_t ioc;
+ datalink_class_t class;
dladm_status_t status;
- if (key == 0)
- return (DLADM_STATUS_KEYINVAL);
-
- if (tempop) {
- dladm_aggr_down_t down;
- dladm_aggr_grp_attr_t sys_attr;
+ if ((dladm_datalink_id2info(linkid, NULL, &class, NULL, NULL, 0) !=
+ DLADM_STATUS_OK) || (class != DATALINK_CLASS_AGGR)) {
+ return (DLADM_STATUS_BADARG);
+ }
- down.ld_key = key;
- down.ld_found = B_FALSE;
- sys_attr.lg_key = key;
- if (i_dladm_aggr_down((void *)&down, &sys_attr) < 0)
- return (dladm_errno2status(errno));
- else
- return (DLADM_STATUS_OK);
- } else {
- status = dladm_aggr_down(key);
+ if (flags & DLADM_OPT_ACTIVE) {
+ ioc.ld_linkid = linkid;
+ if ((i_dladm_aggr_strioctl(LAIOC_DELETE, &ioc,
+ sizeof (ioc)) < 0) &&
+ ((errno != ENOENT) || !(flags & DLADM_OPT_PERSIST))) {
+ status = dladm_errno2status(errno);
+ return (status);
+ }
/*
- * Only continue to delete the configuration repository
- * either if we successfully delete the active aggregation
- * or if the aggregation is not found.
+ * Delete ACTIVE linkprop first.
*/
- if (status != DLADM_STATUS_OK &&
- status != DLADM_STATUS_NOTFOUND) {
- return (status);
- }
+ (void) dladm_set_linkprop(linkid, NULL, NULL, 0,
+ DLADM_OPT_ACTIVE);
+ (void) dladm_destroy_datalink_id(linkid, DLADM_OPT_ACTIVE);
}
- if (tempop)
- return (DLADM_STATUS_OK);
+ /*
+ * If we reach here, it means that the active aggregation has already
+ * been deleted, and there is no active VLANs holding this aggregation.
+ * Now we see whether there is any persistent VLANs holding this
+ * aggregation. If so, we fail the operation.
+ */
+ if (flags & DLADM_OPT_PERSIST) {
+ aggr_held_arg_t arg;
+
+ arg.aggrid = linkid;
+ arg.isheld = B_FALSE;
+
+ (void) dladm_walk_datalink_id(i_dladm_aggr_is_held,
+ &arg, DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_PERSIST);
+ if (arg.isheld)
+ return (DLADM_STATUS_LINKBUSY);
+
+ (void) dladm_destroy_datalink_id(linkid, DLADM_OPT_PERSIST);
+ (void) dladm_remove_conf(linkid);
+ }
- db_attr.lt_key = key;
- return (i_dladm_aggr_del_db(&db_attr, root));
+ return (DLADM_STATUS_OK);
}
/*
* Add one or more ports to an existing link aggregation.
*/
dladm_status_t
-dladm_aggr_add(uint32_t key, uint32_t nports, dladm_aggr_port_attr_db_t *ports,
- boolean_t tempop, const char *root)
+dladm_aggr_add(datalink_id_t linkid, uint32_t nports,
+ dladm_aggr_port_attr_db_t *ports, uint32_t flags)
{
- dladm_aggr_grp_attr_db_t attr;
- dladm_status_t status;
-
- if (key == 0)
- return (DLADM_STATUS_KEYINVAL);
-
- bzero(&attr, sizeof (attr));
- attr.lt_key = key;
- attr.lt_nports = nports;
- attr.lt_ports = ports;
-
- if (!tempop &&
- ((status = i_dladm_aggr_add_db(&attr, root)) != DLADM_STATUS_OK)) {
- return (status);
- }
-
- status = i_dladm_aggr_add_rem_sys(&attr, LAIOC_ADD);
- if (status != DLADM_STATUS_OK && !tempop)
- (void) i_dladm_aggr_remove_db(&attr, root);
-
- return (status);
+ return (i_dladm_aggr_add_rmv(linkid, nports, ports, flags, LAIOC_ADD));
}
/*
* Remove one or more ports from an existing link aggregation.
*/
dladm_status_t
-dladm_aggr_remove(uint32_t key, uint32_t nports,
- dladm_aggr_port_attr_db_t *ports, boolean_t tempop, const char *root)
+dladm_aggr_remove(datalink_id_t linkid, uint32_t nports,
+ dladm_aggr_port_attr_db_t *ports, uint32_t flags)
+{
+ return (i_dladm_aggr_add_rmv(linkid, nports, ports, flags,
+ LAIOC_REMOVE));
+}
+
+typedef struct i_walk_key_state_s {
+ uint16_t key;
+ datalink_id_t linkid;
+ boolean_t found;
+} i_walk_key_state_t;
+
+static int
+i_dladm_walk_key2linkid(datalink_id_t linkid, void *arg)
{
- dladm_aggr_grp_attr_db_t attr;
+ dladm_conf_t conf;
+ uint16_t key;
dladm_status_t status;
+ i_walk_key_state_t *statep = (i_walk_key_state_t *)arg;
+ uint64_t u64;
- if (key == 0)
- return (DLADM_STATUS_KEYINVAL);
+ if (dladm_read_conf(linkid, &conf) != 0)
+ return (DLADM_WALK_CONTINUE);
- bzero(&attr, sizeof (attr));
- attr.lt_key = key;
- attr.lt_nports = nports;
- attr.lt_ports = ports;
+ status = dladm_get_conf_field(conf, FKEY, &u64, sizeof (u64));
+ key = (uint16_t)u64;
+ dladm_destroy_conf(conf);
- if (!tempop &&
- ((status = i_dladm_aggr_remove_db(&attr, root)) !=
- DLADM_STATUS_OK)) {
- return (status);
+ if ((status == DLADM_STATUS_OK) && (key == statep->key)) {
+ statep->found = B_TRUE;
+ statep->linkid = linkid;
+ return (DLADM_WALK_TERMINATE);
}
- status = i_dladm_aggr_add_rem_sys(&attr, LAIOC_REMOVE);
- if (status != DLADM_STATUS_OK && !tempop)
- (void) i_dladm_aggr_add_db(&attr, root);
+ return (DLADM_WALK_CONTINUE);
+}
- return (status);
+dladm_status_t
+dladm_key2linkid(uint16_t key, datalink_id_t *linkidp, uint32_t flags)
+{
+ i_walk_key_state_t state;
+
+ if (key > AGGR_MAX_KEY)
+ return (DLADM_STATUS_NOTFOUND);
+
+ state.found = B_FALSE;
+ state.key = key;
+
+ (void) dladm_walk_datalink_id(i_dladm_walk_key2linkid, &state,
+ DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags);
+ if (state.found == B_TRUE) {
+ *linkidp = state.linkid;
+ return (DLADM_STATUS_OK);
+ } else {
+ return (DLADM_STATUS_NOTFOUND);
+ }
}
diff --git a/usr/src/lib/libdladm/common/libdlaggr.h b/usr/src/lib/libdladm/common/libdlaggr.h
index 40b8c72eeb..1b5df523c4 100644
--- a/usr/src/lib/libdladm/common/libdlaggr.h
+++ b/usr/src/lib/libdladm/common/libdlaggr.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,67 +44,65 @@ extern "C" {
/*
* Modification flags sent with the LAIOC_MODIFY ioctl
*/
-#define DLADM_AGGR_MODIFY_POLICY 0x01
-#define DLADM_AGGR_MODIFY_MAC 0x02
-#define DLADM_AGGR_MODIFY_LACP_MODE 0x04
-#define DLADM_AGGR_MODIFY_LACP_TIMER 0x08
+#define DLADM_AGGR_MODIFY_POLICY 0x01
+#define DLADM_AGGR_MODIFY_MAC 0x02
+#define DLADM_AGGR_MODIFY_LACP_MODE 0x04
+#define DLADM_AGGR_MODIFY_LACP_TIMER 0x08
typedef struct dladm_aggr_port_attr_db {
- char lp_devname[MAXNAMELEN + 1];
+ datalink_id_t lp_linkid;
} dladm_aggr_port_attr_db_t;
typedef struct dladm_aggr_port_attr {
- char lp_devname[MAXNAMELEN + 1];
+ datalink_id_t lp_linkid;
uchar_t lp_mac[ETHERADDRL];
aggr_port_state_t lp_state;
aggr_lacp_state_t lp_lacp_state;
} dladm_aggr_port_attr_t;
typedef struct dladm_aggr_grp_attr {
+ datalink_id_t lg_linkid;
uint32_t lg_key;
uint32_t lg_nports;
dladm_aggr_port_attr_t *lg_ports;
uint32_t lg_policy;
uchar_t lg_mac[ETHERADDRL];
boolean_t lg_mac_fixed;
+ boolean_t lg_force;
aggr_lacp_mode_t lg_lacp_mode;
aggr_lacp_timer_t lg_lacp_timer;
} dladm_aggr_grp_attr_t;
-extern dladm_status_t dladm_aggr_create(uint32_t, uint32_t,
+extern dladm_status_t dladm_aggr_create(const char *, uint16_t, uint32_t,
dladm_aggr_port_attr_db_t *, uint32_t, boolean_t,
- uchar_t *, aggr_lacp_mode_t, aggr_lacp_timer_t,
- boolean_t, const char *);
-extern dladm_status_t dladm_aggr_delete(uint32_t, boolean_t, const char *);
-extern dladm_status_t dladm_aggr_add(uint32_t, uint32_t,
- dladm_aggr_port_attr_db_t *, boolean_t,
- const char *);
-extern dladm_status_t dladm_aggr_remove(uint32_t, uint32_t,
- dladm_aggr_port_attr_db_t *, boolean_t,
- const char *);
-extern dladm_status_t dladm_aggr_modify(uint32_t, uint32_t, uint32_t,
- boolean_t, uchar_t *, aggr_lacp_mode_t,
- aggr_lacp_timer_t, boolean_t, const char *);
-extern dladm_status_t dladm_aggr_up(uint32_t, const char *);
-extern dladm_status_t dladm_aggr_down(uint32_t);
+ const uchar_t *, aggr_lacp_mode_t,
+ aggr_lacp_timer_t, uint32_t);
+extern dladm_status_t dladm_aggr_delete(datalink_id_t, uint32_t);
+extern dladm_status_t dladm_aggr_add(datalink_id_t, uint32_t,
+ dladm_aggr_port_attr_db_t *, uint32_t);
+extern dladm_status_t dladm_aggr_remove(datalink_id_t, uint32_t,
+ dladm_aggr_port_attr_db_t *, uint32_t);
+extern dladm_status_t dladm_aggr_modify(datalink_id_t, uint32_t, uint32_t,
+ boolean_t, const uchar_t *, aggr_lacp_mode_t,
+ aggr_lacp_timer_t, uint32_t);
+extern dladm_status_t dladm_aggr_up(datalink_id_t);
+extern dladm_status_t dladm_aggr_info(datalink_id_t, dladm_aggr_grp_attr_t *,
+ uint32_t);
extern boolean_t dladm_aggr_str2policy(const char *, uint32_t *);
extern char *dladm_aggr_policy2str(uint32_t, char *);
extern boolean_t dladm_aggr_str2macaddr(const char *, boolean_t *,
uchar_t *);
-extern const char *dladm_aggr_macaddr2str(unsigned char *, char *);
-
+extern const char *dladm_aggr_macaddr2str(const unsigned char *, char *);
extern boolean_t dladm_aggr_str2lacpmode(const char *,
aggr_lacp_mode_t *);
extern const char *dladm_aggr_lacpmode2str(aggr_lacp_mode_t, char *);
extern boolean_t dladm_aggr_str2lacptimer(const char *,
aggr_lacp_timer_t *);
extern const char *dladm_aggr_lacptimer2str(aggr_lacp_timer_t, char *);
-
extern const char *dladm_aggr_portstate2str(aggr_port_state_t, char *);
-
-extern int dladm_aggr_walk(int (*)(void *,
- dladm_aggr_grp_attr_t *), void *);
+extern dladm_status_t dladm_key2linkid(uint16_t, datalink_id_t *,
+ uint32_t);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdladm/common/libdllink.c b/usr/src/lib/libdladm/common/libdllink.c
index 45f4641588..bd046acda9 100644
--- a/usr/src/lib/libdladm/common/libdllink.c
+++ b/usr/src/lib/libdladm/common/libdllink.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,213 +29,85 @@
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
+#include <assert.h>
+#include <ctype.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/dld.h>
+#include <sys/vlan.h>
+#include <librcm.h>
#include <libdlpi.h>
#include <libdevinfo.h>
+#include <libdlaggr.h>
+#include <libdlvlan.h>
#include <libdllink.h>
+#include <libdlmgmt.h>
#include <libdladm_impl.h>
-typedef struct dladm_dev {
- char dd_name[IFNAMSIZ];
- struct dladm_dev *dd_next;
-} dladm_dev_t;
-
-typedef struct dladm_walk {
- dladm_dev_t *dw_dev_list;
-} dladm_walk_t;
-
/*
* Return the attributes of the specified datalink from the DLD driver.
*/
-static int
-i_dladm_info(int fd, const char *name, dladm_attr_t *dap)
+static dladm_status_t
+i_dladm_info(int fd, const datalink_id_t linkid, dladm_attr_t *dap)
{
dld_ioc_attr_t dia;
- if (strlen(name) >= IFNAMSIZ) {
- errno = EINVAL;
- return (-1);
- }
-
- (void) strlcpy(dia.dia_name, name, IFNAMSIZ);
+ dia.dia_linkid = linkid;
- if (i_dladm_ioctl(fd, DLDIOCATTR, &dia, sizeof (dia)) < 0)
- return (-1);
+ if (i_dladm_ioctl(fd, DLDIOC_ATTR, &dia, sizeof (dia)) < 0)
+ return (dladm_errno2status(errno));
- (void) strlcpy(dap->da_dev, dia.dia_dev, MAXNAMELEN);
dap->da_max_sdu = dia.dia_max_sdu;
- dap->da_vid = dia.dia_vid;
- return (0);
+ return (DLADM_STATUS_OK);
}
-/*
- * Adds a datalink to the array corresponding to arg.
- */
-static void
-i_dladm_nt_net_add(void *arg, char *name)
-{
- dladm_walk_t *dwp = arg;
- dladm_dev_t *ddp = dwp->dw_dev_list;
- dladm_dev_t **lastp = &dwp->dw_dev_list;
-
- while (ddp) {
- /*
- * Skip duplicates.
- */
- if (strcmp(ddp->dd_name, name) == 0)
- return;
-
- lastp = &ddp->dd_next;
- ddp = ddp->dd_next;
- }
-
- if ((ddp = malloc(sizeof (*ddp))) == NULL)
- return;
-
- (void) strlcpy(ddp->dd_name, name, IFNAMSIZ);
- ddp->dd_next = NULL;
- *lastp = ddp;
-}
-
-/*
- * Walker callback invoked for each DDI_NT_NET node.
- */
-static int
-i_dladm_nt_net_walk(di_node_t node, di_minor_t minor, void *arg)
-{
- char linkname[DLPI_LINKNAME_MAX];
- dlpi_handle_t dh;
-
- if (dlpi_makelink(linkname, di_minor_name(minor),
- di_instance(node)) != DLPI_SUCCESS)
- return (DI_WALK_CONTINUE);
-
- if (dlpi_open(linkname, &dh, 0) == DLPI_SUCCESS) {
- i_dladm_nt_net_add(arg, linkname);
- dlpi_close(dh);
- }
- return (DI_WALK_CONTINUE);
-}
-
-/*
- * Hold a data-link.
- */
-static int
-i_dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
-{
- int fd;
- dld_hold_vlan_t dhv;
-
- if (strlen(name) >= IFNAMSIZ) {
- errno = EINVAL;
- return (-1);
- }
+struct i_dladm_walk_arg {
+ dladm_walkcb_t *fn;
+ void *arg;
+};
- if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
- return (-1);
-
- bzero(&dhv, sizeof (dld_hold_vlan_t));
- (void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
- dhv.dhv_zid = zoneid;
- dhv.dhv_docheck = docheck;
-
- if (i_dladm_ioctl(fd, DLDIOCHOLDVLAN, &dhv, sizeof (dhv)) < 0) {
- int olderrno = errno;
-
- (void) close(fd);
- errno = olderrno;
- return (-1);
- }
-
- (void) close(fd);
- return (0);
-}
-
-/*
- * Release a data-link.
- */
static int
-i_dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+i_dladm_walk(datalink_id_t linkid, void *arg)
{
- int fd;
- dld_hold_vlan_t dhv;
-
- if (strlen(name) >= IFNAMSIZ) {
- errno = EINVAL;
- return (-1);
- }
-
- if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
- return (-1);
-
- bzero(&dhv, sizeof (dld_hold_vlan_t));
- (void) strlcpy(dhv.dhv_name, name, IFNAMSIZ);
- dhv.dhv_zid = zoneid;
- dhv.dhv_docheck = docheck;
+ struct i_dladm_walk_arg *walk_arg = arg;
+ char link[MAXLINKNAMELEN];
- if (i_dladm_ioctl(fd, DLDIOCRELEVLAN, &dhv, sizeof (dhv)) < 0) {
- int olderrno = errno;
-
- (void) close(fd);
- errno = olderrno;
- return (-1);
+ if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, link,
+ sizeof (link)) == DLADM_STATUS_OK) {
+ return (walk_arg->fn(link, walk_arg->arg));
}
- (void) close(fd);
- return (0);
+ return (DLADM_WALK_CONTINUE);
}
/*
- * Invoke the specified callback function for each active DDI_NT_NET
- * node.
+ * Walk all datalinks.
*/
-int
-dladm_walk(void (*fn)(void *, const char *), void *arg)
+dladm_status_t
+dladm_walk(dladm_walkcb_t *fn, void *arg, datalink_class_t class,
+ datalink_media_t dmedia, uint32_t flags)
{
- di_node_t root;
- dladm_walk_t dw;
- dladm_dev_t *ddp, *last_ddp;
-
- if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) {
- errno = EFAULT;
- return (-1);
- }
- dw.dw_dev_list = NULL;
-
- (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &dw,
- i_dladm_nt_net_walk);
-
- di_fini(root);
+ struct i_dladm_walk_arg walk_arg;
- ddp = dw.dw_dev_list;
- while (ddp) {
- fn(arg, ddp->dd_name);
- last_ddp = ddp;
- ddp = ddp->dd_next;
- free(last_ddp);
- }
-
- return (0);
+ walk_arg.fn = fn;
+ walk_arg.arg = arg;
+ return (dladm_walk_datalink_id(i_dladm_walk, &walk_arg,
+ class, dmedia, flags));
}
/*
- * MAC Administration Library.
- *
- * This library is used by administration tools such as dladm(1M) to
+ * These routines are used by administration tools such as dladm(1M) to
* iterate through the list of MAC interfaces
- *
*/
typedef struct dladm_mac_dev {
char dm_name[MAXNAMELEN];
- struct dladm_mac_dev *dm_next;
+ struct dladm_mac_dev *dm_next;
} dladm_mac_dev_t;
typedef struct macadm_walk {
- dladm_mac_dev_t *dmd_dev_list;
+ dladm_mac_dev_t *dmd_dev_list;
} dladm_mac_walk_t;
/*
@@ -259,6 +131,12 @@ i_dladm_mac_walk(di_node_t node, di_minor_t minor, void *arg)
if (strcmp("aggr", di_driver_name(node)) == 0)
return (DI_WALK_CONTINUE);
+ /*
+ * Skip softmacs.
+ */
+ if (strcmp("softmac", di_driver_name(node)) == 0)
+ return (DI_WALK_CONTINUE);
+
while (dmdp) {
/*
* Skip duplicates.
@@ -281,17 +159,18 @@ i_dladm_mac_walk(di_node_t node, di_minor_t minor, void *arg)
}
/*
- * Invoke the specified callback for each DDI_NT_MAC node.
+ * Invoke the specified callback for each DDI_NT_NET node.
*/
-int
-dladm_mac_walk(void (*fn)(void *, const char *), void *arg)
+dladm_status_t
+dladm_mac_walk(int (*fn)(const char *, void *arg), void *arg)
{
di_node_t root;
dladm_mac_walk_t dmw;
dladm_mac_dev_t *dmdp, *next;
+ boolean_t done = B_FALSE;
if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
- return (-1);
+ return (dladm_errno2status(errno));
dmw.dmd_dev_list = NULL;
@@ -303,33 +182,32 @@ dladm_mac_walk(void (*fn)(void *, const char *), void *arg)
dmdp = dmw.dmd_dev_list;
for (dmdp = dmw.dmd_dev_list; dmdp != NULL; dmdp = next) {
next = dmdp->dm_next;
- (*fn)(arg, dmdp->dm_name);
+ if (!done &&
+ ((*fn)(dmdp->dm_name, arg) == DLADM_WALK_TERMINATE)) {
+ done = B_TRUE;
+ }
free(dmdp);
}
- return (0);
+ return (DLADM_STATUS_OK);
}
/*
- * Returns the current attributes of the specified datalink.
+ * Get the current attributes of the specified datalink.
*/
-int
-dladm_info(const char *name, dladm_attr_t *dap)
+dladm_status_t
+dladm_info(datalink_id_t linkid, dladm_attr_t *dap)
{
int fd;
+ dladm_status_t status;
if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
- return (-1);
-
- if (i_dladm_info(fd, name, dap) < 0)
- goto failed;
+ return (dladm_errno2status(errno));
- (void) close(fd);
- return (0);
+ status = i_dladm_info(fd, linkid, dap);
-failed:
(void) close(fd);
- return (-1);
+ return (status);
}
const char *
@@ -373,19 +251,678 @@ dladm_linkduplex2str(link_duplex_t duplex, char *buf)
}
/*
- * Do a "hold" operation to a link.
+ * Set zoneid of a given link
*/
-int
-dladm_hold_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+dladm_status_t
+dladm_setzid(const char *link, zoneid_t zoneid)
+{
+ int fd;
+ dladm_status_t status = DLADM_STATUS_OK;
+ dld_ioc_setzid_t dis;
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ bzero(&dis, sizeof (dld_ioc_setzid_t));
+ (void) strlcpy(dis.dis_link, link, MAXLINKNAMELEN);
+ dis.dis_zid = zoneid;
+
+ if (i_dladm_ioctl(fd, DLDIOC_SETZID, &dis, sizeof (dis)) < 0)
+ status = dladm_errno2status(errno);
+
+ (void) close(fd);
+ return (status);
+}
+
+/*
+ * Get zoneid of a given link
+ */
+dladm_status_t
+dladm_getzid(datalink_id_t linkid, zoneid_t *zoneidp)
+{
+ int fd;
+ dladm_status_t status = DLADM_STATUS_OK;
+ dld_ioc_getzid_t dig;
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ bzero(&dig, sizeof (dld_ioc_getzid_t));
+ dig.dig_linkid = linkid;
+ dig.dig_zid = -1;
+
+ if (i_dladm_ioctl(fd, DLDIOC_GETZID, &dig, sizeof (dig)) < 0)
+ status = dladm_errno2status(errno);
+
+ (void) close(fd);
+
+ if (status == DLADM_STATUS_OK)
+ *zoneidp = dig.dig_zid;
+
+ return (status);
+}
+
+/*
+ * Case 1: rename an existing link1 to a link2 that does not exist.
+ * Result: <linkid1, link2>
+ */
+static dladm_status_t
+i_dladm_rename_link_c1(datalink_id_t linkid1, const char *link1,
+ const char *link2, uint32_t flags)
{
- return (i_dladm_hold_link(name, zoneid, docheck));
+ dld_ioc_rename_t dir;
+ dladm_conf_t conf;
+ dladm_status_t status = DLADM_STATUS_OK;
+ int fd;
+
+ /*
+ * Link is currently available. Check to see whether anything is
+ * holding this link to prevent a rename operation.
+ */
+ if (flags & DLADM_OPT_ACTIVE) {
+ dir.dir_linkid1 = linkid1;
+ dir.dir_linkid2 = DATALINK_INVALID_LINKID;
+ (void) strlcpy(dir.dir_link, link2, MAXLINKNAMELEN);
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ if (i_dladm_ioctl(fd, DLDIOC_RENAME, &dir, sizeof (dir)) < 0) {
+ status = dladm_errno2status(errno);
+ (void) close(fd);
+ return (status);
+ }
+ }
+
+ status = dladm_remap_datalink_id(linkid1, link2);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ /*
+ * Flush the current mapping to persistent configuration.
+ */
+ if ((flags & DLADM_OPT_PERSIST) &&
+ (((status = dladm_read_conf(linkid1, &conf)) != DLADM_STATUS_OK) ||
+ ((status = dladm_write_conf(conf)) != DLADM_STATUS_OK))) {
+ (void) dladm_remap_datalink_id(linkid1, link1);
+ }
+done:
+ if (flags & DLADM_OPT_ACTIVE) {
+ if (status != DLADM_STATUS_OK) {
+ (void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN);
+ (void) i_dladm_ioctl(fd, DLDIOC_RENAME, &dir,
+ sizeof (dir));
+ }
+ (void) close(fd);
+ }
+ return (status);
+}
+
+typedef struct link_hold_arg_s {
+ datalink_id_t linkid;
+ datalink_id_t holder;
+ uint32_t flags;
+} link_hold_arg_t;
+
+static int
+i_dladm_aggr_link_hold(datalink_id_t aggrid, void *arg)
+{
+ link_hold_arg_t *hold_arg = arg;
+ dladm_aggr_grp_attr_t ginfo;
+ dladm_status_t status;
+ int i;
+
+ status = dladm_aggr_info(aggrid, &ginfo, hold_arg->flags);
+ if (status != DLADM_STATUS_OK)
+ return (DLADM_WALK_CONTINUE);
+
+ for (i = 0; i < ginfo.lg_nports; i++) {
+ if (ginfo.lg_ports[i].lp_linkid == hold_arg->linkid) {
+ hold_arg->holder = aggrid;
+ return (DLADM_WALK_TERMINATE);
+ }
+ }
+ return (DLADM_WALK_CONTINUE);
+}
+
+static int
+i_dladm_vlan_link_hold(datalink_id_t vlanid, void *arg)
+{
+ link_hold_arg_t *hold_arg = arg;
+ dladm_vlan_attr_t vinfo;
+ dladm_status_t status;
+
+ status = dladm_vlan_info(vlanid, &vinfo, hold_arg->flags);
+ if (status != DLADM_STATUS_OK)
+ return (DLADM_WALK_CONTINUE);
+
+ if (vinfo.dv_linkid == hold_arg->linkid) {
+ hold_arg->holder = vlanid;
+ return (DLADM_WALK_TERMINATE);
+ }
+ return (DLADM_WALK_CONTINUE);
}
/*
- * Do a "release" operation to a link.
+ * Case 2: rename an available physical link link1 to a REMOVED physical link
+ * link2. As a result, link1 directly inherits all datalinks configured
+ * over link2 (linkid2).
+ * Result: <linkid2, link2, link1_phymaj, link1_phyinst, link1_devname,
+ * link2_other_attr>
*/
+static dladm_status_t
+i_dladm_rename_link_c2(datalink_id_t linkid1, datalink_id_t linkid2)
+{
+ rcm_handle_t *rcm_hdl = NULL;
+ nvlist_t *nvl = NULL;
+ link_hold_arg_t arg;
+ dld_ioc_rename_t dir;
+ int fd;
+ dladm_conf_t conf1, conf2;
+ char devname[MAXLINKNAMELEN];
+ uint64_t phymaj, phyinst;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ /*
+ * First check if linkid1 is associated with any persistent
+ * aggregations or VLANs. If yes, return BUSY.
+ */
+ arg.linkid = linkid1;
+ arg.holder = DATALINK_INVALID_LINKID;
+ arg.flags = DLADM_OPT_PERSIST;
+ (void) dladm_walk_datalink_id(i_dladm_aggr_link_hold, &arg,
+ DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
+ if (arg.holder != DATALINK_INVALID_LINKID)
+ return (DLADM_STATUS_LINKBUSY);
+
+ arg.flags = DLADM_OPT_PERSIST;
+ (void) dladm_walk_datalink_id(i_dladm_vlan_link_hold, &arg,
+ DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
+ if (arg.holder != DATALINK_INVALID_LINKID)
+ return (DLADM_STATUS_LINKBUSY);
+
+ /*
+ * Send DLDIOC_RENAME to request to rename link1's linkid to
+ * be linkid2. This will check whether link1 is used by any
+ * aggregations or VLANs, or is held by any application. If yes,
+ * return failure.
+ */
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ dir.dir_linkid1 = linkid1;
+ dir.dir_linkid2 = linkid2;
+ if (i_dladm_ioctl(fd, DLDIOC_RENAME, &dir, sizeof (dir)) < 0)
+ status = dladm_errno2status(errno);
+
+ if (status != DLADM_STATUS_OK) {
+ (void) close(fd);
+ return (status);
+ }
+
+ /*
+ * Now change the phymaj, phyinst and devname associated with linkid1
+ * to be associated with linkid2. Before doing that, the old active
+ * linkprop of linkid1 should be deleted.
+ */
+ (void) dladm_set_linkprop(linkid1, NULL, NULL, 0, DLADM_OPT_ACTIVE);
+
+ if (((status = dladm_read_conf(linkid1, &conf1)) != DLADM_STATUS_OK) ||
+ ((status = dladm_get_conf_field(conf1, FDEVNAME, devname,
+ MAXLINKNAMELEN)) != DLADM_STATUS_OK) ||
+ ((status = dladm_get_conf_field(conf1, FPHYMAJ, &phymaj,
+ sizeof (uint64_t))) != DLADM_STATUS_OK) ||
+ ((status = dladm_get_conf_field(conf1, FPHYINST, &phyinst,
+ sizeof (uint64_t))) != DLADM_STATUS_OK) ||
+ ((status = dladm_read_conf(linkid2, &conf2)) != DLADM_STATUS_OK)) {
+ dir.dir_linkid1 = linkid2;
+ dir.dir_linkid2 = linkid1;
+ (void) dladm_init_linkprop(linkid1);
+ (void) i_dladm_ioctl(fd, DLDIOC_RENAME, &dir, sizeof (dir));
+ (void) close(fd);
+ return (status);
+ }
+ (void) close(fd);
+
+ dladm_destroy_conf(conf1);
+ (void) dladm_set_conf_field(conf2, FDEVNAME, DLADM_TYPE_STR, devname);
+ (void) dladm_set_conf_field(conf2, FPHYMAJ, DLADM_TYPE_UINT64, &phymaj);
+ (void) dladm_set_conf_field(conf2, FPHYINST,
+ DLADM_TYPE_UINT64, &phyinst);
+ (void) dladm_write_conf(conf2);
+ dladm_destroy_conf(conf2);
+
+ /*
+ * Delete link1 and mark link2 up.
+ */
+ (void) dladm_destroy_datalink_id(linkid1, DLADM_OPT_ACTIVE |
+ DLADM_OPT_PERSIST);
+ (void) dladm_remove_conf(linkid1);
+ (void) dladm_up_datalink_id(linkid2);
+
+ /*
+ * Now generate the RCM_RESOURCE_LINK_NEW sysevent which can be
+ * consumed by the RCM framework to restore all the datalink and
+ * IP configuration.
+ */
+ status = DLADM_STATUS_FAILED;
+ if ((nvlist_alloc(&nvl, 0, 0) != 0) ||
+ (nvlist_add_uint64(nvl, RCM_NV_LINKID, linkid2) != 0)) {
+ goto done;
+ }
+
+ if (rcm_alloc_handle(NULL, 0, NULL, &rcm_hdl) != RCM_SUCCESS)
+ goto done;
+
+ if (rcm_notify_event(rcm_hdl, RCM_RESOURCE_LINK_NEW, 0, nvl, NULL) ==
+ RCM_SUCCESS) {
+ status = DLADM_STATUS_OK;
+ }
+
+done:
+ if (rcm_hdl != NULL)
+ (void) rcm_free_handle(rcm_hdl);
+ if (nvl != NULL)
+ nvlist_free(nvl);
+ return (status);
+}
+
+/*
+ * case 3: rename a non-existent link to a REMOVED physical link.
+ * Set the removed physical link's device name to link1, so that
+ * when link1 attaches, it inherits all the link configuration of
+ * the removed physical link.
+ */
+static dladm_status_t
+i_dladm_rename_link_c3(const char *link1, datalink_id_t linkid2)
+{
+ dladm_conf_t conf;
+ dladm_status_t status;
+
+ if (!dladm_valid_linkname(link1))
+ return (DLADM_STATUS_LINKINVAL);
+
+ status = dladm_read_conf(linkid2, &conf);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ if ((status = dladm_set_conf_field(conf, FDEVNAME, DLADM_TYPE_STR,
+ link1)) == DLADM_STATUS_OK) {
+ status = dladm_write_conf(conf);
+ }
+
+ dladm_destroy_conf(conf);
+
+done:
+ return (status);
+}
+
+dladm_status_t
+dladm_rename_link(const char *link1, const char *link2)
+{
+ datalink_id_t linkid1 = DATALINK_INVALID_LINKID;
+ datalink_id_t linkid2 = DATALINK_INVALID_LINKID;
+ uint32_t flags1, flags2;
+ datalink_class_t class1, class2;
+ uint32_t media1, media2;
+ boolean_t remphy2 = B_FALSE;
+ dladm_status_t status;
+
+ (void) dladm_name2info(link1, &linkid1, &flags1, &class1, &media1);
+ if ((dladm_name2info(link2, &linkid2, &flags2, &class2, &media2) ==
+ DLADM_STATUS_OK) && (class2 == DATALINK_CLASS_PHYS) &&
+ (flags2 == DLADM_OPT_PERSIST)) {
+ /*
+ * see whether link2 is a removed physical link.
+ */
+ remphy2 = B_TRUE;
+ }
+
+ if (linkid1 != DATALINK_INVALID_LINKID) {
+ if (linkid2 == DATALINK_INVALID_LINKID) {
+ /*
+ * case 1: rename an existing link to a link that
+ * does not exist.
+ */
+ status = i_dladm_rename_link_c1(linkid1, link1, link2,
+ flags1);
+ } else if (remphy2) {
+ /*
+ * case 2: rename an available link to a REMOVED
+ * physical link. Return failure if link1 is not
+ * an active physical link.
+ */
+ if ((class1 != class2) || (media1 != media2) ||
+ !(flags1 & DLADM_OPT_ACTIVE)) {
+ status = DLADM_STATUS_BADARG;
+ } else {
+ status = i_dladm_rename_link_c2(linkid1,
+ linkid2);
+ }
+ } else {
+ status = DLADM_STATUS_EXIST;
+ }
+ } else if (remphy2) {
+ status = i_dladm_rename_link_c3(link1, linkid2);
+ } else {
+ status = DLADM_STATUS_NOTFOUND;
+ }
+ return (status);
+}
+
+typedef struct consumer_del_phys_arg_s {
+ datalink_id_t linkid;
+} consumer_del_phys_arg_t;
+
+static int
+i_dladm_vlan_link_del(datalink_id_t vlanid, void *arg)
+{
+ consumer_del_phys_arg_t *del_arg = arg;
+ dladm_vlan_attr_t vinfo;
+ dladm_status_t status;
+
+ status = dladm_vlan_info(vlanid, &vinfo, DLADM_OPT_PERSIST);
+ if (status != DLADM_STATUS_OK)
+ return (DLADM_WALK_CONTINUE);
+
+ if (vinfo.dv_linkid == del_arg->linkid)
+ (void) dladm_vlan_delete(vlanid, DLADM_OPT_PERSIST);
+ return (DLADM_WALK_CONTINUE);
+}
+
+static int
+i_dladm_aggr_link_del(datalink_id_t aggrid, void *arg)
+{
+ consumer_del_phys_arg_t *del_arg = arg;
+ dladm_aggr_grp_attr_t ginfo;
+ dladm_status_t status;
+ dladm_aggr_port_attr_db_t port[1];
+ int i;
+
+ status = dladm_aggr_info(aggrid, &ginfo, DLADM_OPT_PERSIST);
+ if (status != DLADM_STATUS_OK)
+ return (DLADM_WALK_CONTINUE);
+
+ for (i = 0; i < ginfo.lg_nports; i++)
+ if (ginfo.lg_ports[i].lp_linkid == del_arg->linkid)
+ break;
+
+ if (i != ginfo.lg_nports) {
+ if (ginfo.lg_nports == 1 && i == 0) {
+ consumer_del_phys_arg_t aggr_del_arg;
+
+ /*
+ * First delete all the VLANs on this aggregation, then
+ * delete the aggregation itself.
+ */
+ aggr_del_arg.linkid = aggrid;
+ (void) dladm_walk_datalink_id(i_dladm_vlan_link_del,
+ &aggr_del_arg, DATALINK_CLASS_VLAN,
+ DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
+ (void) dladm_aggr_delete(aggrid, DLADM_OPT_PERSIST);
+ } else {
+ port[0].lp_linkid = del_arg->linkid;
+ (void) dladm_aggr_remove(aggrid, 1, port,
+ DLADM_OPT_PERSIST);
+ }
+ }
+ return (DLADM_WALK_CONTINUE);
+}
+
+typedef struct del_phys_arg_s {
+ dladm_status_t rval;
+} del_phys_arg_t;
+
+static int
+i_dladm_phys_delete(datalink_id_t linkid, void *arg)
+{
+ uint32_t flags;
+ datalink_class_t class;
+ uint32_t media;
+ dladm_status_t status = DLADM_STATUS_OK;
+ del_phys_arg_t *del_phys_arg = arg;
+ consumer_del_phys_arg_t del_arg;
+
+ if ((status = dladm_datalink_id2info(linkid, &flags, &class,
+ &media, NULL, 0)) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ /*
+ * see whether this link is a removed physical link.
+ */
+ if ((class != DATALINK_CLASS_PHYS) || !(flags & DLADM_OPT_PERSIST) ||
+ (flags & DLADM_OPT_ACTIVE)) {
+ status = DLADM_STATUS_BADARG;
+ goto done;
+ }
+
+ if (media == DL_ETHER) {
+ del_arg.linkid = linkid;
+ (void) dladm_walk_datalink_id(i_dladm_aggr_link_del, &del_arg,
+ DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_PERSIST);
+ (void) dladm_walk_datalink_id(i_dladm_vlan_link_del, &del_arg,
+ DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_PERSIST);
+ }
+
+ (void) dladm_destroy_datalink_id(linkid, DLADM_OPT_PERSIST);
+ (void) dladm_remove_conf(linkid);
+
+done:
+ del_phys_arg->rval = status;
+ return (DLADM_WALK_CONTINUE);
+}
+
+dladm_status_t
+dladm_phys_delete(datalink_id_t linkid)
+{
+ del_phys_arg_t arg = {DLADM_STATUS_OK};
+
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(i_dladm_phys_delete, &arg,
+ DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_PERSIST);
+ return (DLADM_STATUS_OK);
+ } else {
+ (void) i_dladm_phys_delete(linkid, &arg);
+ return (arg.rval);
+ }
+}
+
+dladm_status_t
+dladm_phys_info(datalink_id_t linkid, dladm_phys_attr_t *dpap, uint32_t flags)
+{
+ dladm_status_t status;
+
+ assert(flags == DLADM_OPT_ACTIVE || flags == DLADM_OPT_PERSIST);
+
+ switch (flags) {
+ case DLADM_OPT_PERSIST: {
+ dladm_conf_t conf;
+
+ status = dladm_read_conf(linkid, &conf);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ status = dladm_get_conf_field(conf, FDEVNAME, dpap->dp_dev,
+ MAXLINKNAMELEN);
+ dladm_destroy_conf(conf);
+ return (status);
+ }
+ case DLADM_OPT_ACTIVE: {
+ dld_ioc_phys_attr_t dip;
+ int fd;
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ dip.dip_linkid = linkid;
+ if (i_dladm_ioctl(fd, DLDIOC_PHYS_ATTR, &dip, sizeof (dip))
+ < 0) {
+ status = dladm_errno2status(errno);
+ (void) close(fd);
+ return (status);
+ }
+ (void) close(fd);
+ dpap->dp_novanity = dip.dip_novanity;
+ (void) strlcpy(dpap->dp_dev, dip.dip_dev, MAXLINKNAMELEN);
+ return (DLADM_STATUS_OK);
+ }
+ default:
+ return (DLADM_STATUS_BADARG);
+ }
+}
+
+typedef struct i_walk_dev_state_s {
+ const char *devname;
+ datalink_id_t linkid;
+ boolean_t found;
+} i_walk_dev_state_t;
+
int
-dladm_rele_link(const char *name, zoneid_t zoneid, boolean_t docheck)
+i_dladm_walk_dev2linkid(datalink_id_t linkid, void *arg)
+{
+ dladm_phys_attr_t dpa;
+ dladm_status_t status;
+ i_walk_dev_state_t *statep = arg;
+
+ status = dladm_phys_info(linkid, &dpa, DLADM_OPT_PERSIST);
+ if ((status == DLADM_STATUS_OK) &&
+ (strcmp(statep->devname, dpa.dp_dev) == 0)) {
+ statep->found = B_TRUE;
+ statep->linkid = linkid;
+ return (DLADM_WALK_TERMINATE);
+ }
+ return (DLADM_WALK_CONTINUE);
+}
+
+/*
+ * Get the linkid from the physical device name.
+ */
+dladm_status_t
+dladm_dev2linkid(const char *devname, datalink_id_t *linkidp)
{
- return (i_dladm_rele_link(name, zoneid, docheck));
+ i_walk_dev_state_t state;
+
+ state.found = B_FALSE;
+ state.devname = devname;
+
+ (void) dladm_walk_datalink_id(i_dladm_walk_dev2linkid, &state,
+ DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
+ if (state.found == B_TRUE) {
+ *linkidp = state.linkid;
+ return (DLADM_STATUS_OK);
+ } else {
+ return (dladm_errno2status(ENOENT));
+ }
+}
+
+static int
+parse_devname(const char *devname, char *driver, uint_t *ppa, size_t maxlen)
+{
+ char *cp, *tp;
+ int len;
+
+ /*
+ * device name length must not be 0, and it must end with digit.
+ */
+ if (((len = strlen(devname)) == 0) || !isdigit(devname[len - 1]))
+ return (EINVAL);
+
+ (void) strlcpy(driver, devname, maxlen);
+ cp = (char *)&driver[len - 1];
+
+ for (tp = cp; isdigit(*tp); tp--) {
+ if (tp <= driver)
+ return (EINVAL);
+ }
+
+ *ppa = atoi(tp + 1);
+ *(tp + 1) = '\0';
+ return (0);
+}
+
+dladm_status_t
+dladm_linkid2legacyname(datalink_id_t linkid, char *dev, size_t len)
+{
+ char devname[MAXLINKNAMELEN];
+ uint16_t vid = VLAN_ID_NONE;
+ datalink_class_t class;
+ dladm_status_t status;
+
+ status = dladm_datalink_id2info(linkid, NULL, &class, NULL, NULL, 0);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ /*
+ * If this is a VLAN, we must first determine the class and linkid of
+ * the link the VLAN has been created over.
+ */
+ if (class == DATALINK_CLASS_VLAN) {
+ dladm_vlan_attr_t dva;
+
+ status = dladm_vlan_info(linkid, &dva, DLADM_OPT_ACTIVE);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ linkid = dva.dv_linkid;
+ vid = dva.dv_vid;
+
+ if ((status = dladm_datalink_id2info(linkid, NULL, &class, NULL,
+ NULL, 0)) != DLADM_STATUS_OK) {
+ goto done;
+ }
+ }
+
+ switch (class) {
+ case DATALINK_CLASS_AGGR: {
+ dladm_aggr_grp_attr_t dga;
+
+ status = dladm_aggr_info(linkid, &dga, DLADM_OPT_ACTIVE);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ if (dga.lg_key == 0) {
+ /*
+ * If the key was not specified when the aggregation
+ * is created, we cannot guess its /dev node name.
+ */
+ status = DLADM_STATUS_BADARG;
+ goto done;
+ }
+ (void) snprintf(devname, MAXLINKNAMELEN, "aggr%d", dga.lg_key);
+ break;
+ }
+ case DATALINK_CLASS_PHYS: {
+ dladm_phys_attr_t dpa;
+
+ status = dladm_phys_info(linkid, &dpa, DLADM_OPT_PERSIST);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ (void) strlcpy(devname, dpa.dp_dev, MAXLINKNAMELEN);
+ break;
+ }
+ default:
+ status = DLADM_STATUS_BADARG;
+ goto done;
+ }
+
+ if (vid != VLAN_ID_NONE) {
+ char drv[MAXNAMELEN];
+ uint_t ppa;
+
+ if (parse_devname(devname, drv, &ppa, MAXNAMELEN) != 0) {
+ status = DLADM_STATUS_BADARG;
+ goto done;
+ }
+ if (snprintf(dev, len, "%s%d", drv, vid * 1000 + ppa) >= len)
+ status = DLADM_STATUS_TOOSMALL;
+ } else {
+ if (strlcpy(dev, devname, len) >= len)
+ status = DLADM_STATUS_TOOSMALL;
+ }
+
+done:
+ return (status);
}
diff --git a/usr/src/lib/libdladm/common/libdllink.h b/usr/src/lib/libdladm/common/libdllink.h
index 12327456a5..2b762ff6d8 100644
--- a/usr/src/lib/libdladm/common/libdllink.h
+++ b/usr/src/lib/libdladm/common/libdllink.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,14 +29,12 @@
#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * This file includes strcutures, macros and routines used by general
- * link administration, which applies not limited to one specific
- * type of link.
+ * This file includes structures, macros and routines used by general
+ * link administration (i.e. not limited to one specific type of link).
*/
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/mac.h>
#include <libdladm.h>
#ifdef __cplusplus
@@ -44,11 +42,25 @@ extern "C" {
#endif
typedef struct dladm_attr {
- char da_dev[MAXNAMELEN];
uint_t da_max_sdu;
- uint16_t da_vid;
} dladm_attr_t;
+typedef struct dladm_phys_attr {
+ char dp_dev[MAXLINKNAMELEN];
+ /*
+ * Whether this physical link supports vanity naming (links with media
+ * types not supported by GLDv3 don't have vanity naming support).
+ */
+ boolean_t dp_novanity;
+} dladm_phys_attr_t;
+
+typedef enum {
+ DLADM_PROP_VAL_CURRENT = 1,
+ DLADM_PROP_VAL_DEFAULT,
+ DLADM_PROP_VAL_MODIFIABLE,
+ DLADM_PROP_VAL_PERSISTENT
+} dladm_prop_type_t;
+
/*
* Maximum size of secobj value. Note that it should not be greater than
* DLD_SECOBJ_VAL_MAX.
@@ -61,26 +73,31 @@ typedef struct dladm_attr {
*/
#define DLADM_SECOBJ_NAME_MAX 32
-#define DLADM_PROP_VAL_MAX 25
+#define DLADM_MAX_PROP_VALCNT 32
+#define DLADM_PROP_VAL_MAX 128
#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 *);
+typedef int (dladm_walkcb_t)(const char *, void *);
+
+extern dladm_status_t dladm_walk(dladm_walkcb_t *, void *, datalink_class_t,
+ datalink_media_t, uint32_t);
+extern dladm_status_t dladm_mac_walk(dladm_walkcb_t *, void *);
+extern dladm_status_t dladm_info(datalink_id_t, dladm_attr_t *);
+extern dladm_status_t dladm_setzid(const char *, zoneid_t);
+extern dladm_status_t dladm_getzid(datalink_id_t, zoneid_t *);
-extern int dladm_walk(dladm_walkcb_t *, void *);
-extern int dladm_mac_walk(void (*fn)(void *, const char *), void *);
-extern int dladm_info(const char *, dladm_attr_t *);
-extern int dladm_hold_link(const char *, zoneid_t, boolean_t);
-extern int dladm_rele_link(const char *, zoneid_t, boolean_t);
+extern dladm_status_t dladm_rename_link(const char *, const char *);
-extern dladm_status_t dladm_set_prop(const char *, const char *,
- char **, uint_t, uint_t, char **);
-extern dladm_status_t dladm_get_prop(const char *, dladm_prop_type_t,
+extern dladm_status_t dladm_set_linkprop(datalink_id_t, const char *,
+ char **, uint_t, uint_t);
+extern dladm_status_t dladm_get_linkprop(datalink_id_t, dladm_prop_type_t,
const char *, char **, uint_t *);
-extern dladm_status_t dladm_walk_prop(const char *, void *,
- boolean_t (*)(void *, const char *));
+extern dladm_status_t dladm_walk_linkprop(datalink_id_t, void *,
+ int (*)(datalink_id_t, const char *, void *));
+
extern dladm_status_t dladm_set_secobj(const char *, dladm_secobj_class_t,
uint8_t *, uint_t, uint_t);
extern dladm_status_t dladm_get_secobj(const char *, dladm_secobj_class_t *,
@@ -95,9 +112,40 @@ extern const char *dladm_secobjclass2str(dladm_secobj_class_t, char *);
extern dladm_status_t dladm_str2secobjclass(const char *,
dladm_secobj_class_t *);
-extern dladm_status_t dladm_init_linkprop(void);
+extern dladm_status_t dladm_init_linkprop(datalink_id_t);
extern dladm_status_t dladm_init_secobj(void);
+extern dladm_status_t dladm_create_datalink_id(const char *, datalink_class_t,
+ uint_t, uint32_t, datalink_id_t *);
+extern dladm_status_t dladm_destroy_datalink_id(datalink_id_t, uint32_t);
+extern dladm_status_t dladm_remap_datalink_id(datalink_id_t, const char *);
+extern dladm_status_t dladm_up_datalink_id(datalink_id_t);
+extern dladm_status_t dladm_name2info(const char *, datalink_id_t *,
+ uint32_t *, datalink_class_t *, uint32_t *);
+extern dladm_status_t dladm_datalink_id2info(datalink_id_t, uint32_t *,
+ datalink_class_t *, uint32_t *, char *, size_t);
+extern dladm_status_t dladm_walk_datalink_id(int (*)(datalink_id_t, void *),
+ void *, datalink_class_t, datalink_media_t,
+ uint32_t);
+extern dladm_status_t dladm_create_conf(const char *, datalink_id_t,
+ datalink_class_t, uint32_t, dladm_conf_t *);
+extern dladm_status_t dladm_read_conf(datalink_id_t, dladm_conf_t *);
+extern dladm_status_t dladm_write_conf(dladm_conf_t);
+extern dladm_status_t dladm_remove_conf(datalink_id_t);
+extern void dladm_destroy_conf(dladm_conf_t);
+extern dladm_status_t dladm_get_conf_field(dladm_conf_t, const char *,
+ void *, size_t);
+extern dladm_status_t dladm_set_conf_field(dladm_conf_t, const char *,
+ dladm_datatype_t, const void *);
+extern dladm_status_t dladm_unset_conf_field(dladm_conf_t, const char *);
+
+extern dladm_status_t dladm_dev2linkid(const char *, datalink_id_t *);
+extern dladm_status_t dladm_linkid2legacyname(datalink_id_t, char *, size_t);
+extern dladm_status_t dladm_phys_delete(datalink_id_t);
+
+extern dladm_status_t dladm_phys_info(datalink_id_t, dladm_phys_attr_t *,
+ uint32_t);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libdladm/common/libdlmgmt.c b/usr/src/lib/libdladm/common/libdlmgmt.c
new file mode 100644
index 0000000000..1826edf810
--- /dev/null
+++ b/usr/src/lib/libdladm/common/libdlmgmt.c
@@ -0,0 +1,676 @@
+/*
+ * 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
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <door.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/aggr.h>
+#include <fcntl.h>
+#include <libdladm.h>
+#include <libdladm_impl.h>
+#include <libdllink.h>
+#include <libdlmgmt.h>
+
+/*
+ * Table of data type sizes indexed by dladm_datatype_t.
+ */
+static size_t dladm_datatype_size[] = {
+ 0, /* DLADM_TYPE_STR, use strnlen() */
+ sizeof (boolean_t), /* DLADM_TYPE_BOOLEAN */
+ sizeof (uint64_t) /* DLADM_TYPE_UINT64 */
+};
+
+static dladm_status_t
+dladm_door_call(void *arg, size_t asize, void *rbuf, size_t *rsizep)
+{
+ door_arg_t darg;
+ dlmgmt_retval_t *retvalp = rbuf;
+ int fd;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ if ((fd = open(DLMGMT_DOOR, O_RDONLY)) == -1)
+ return (dladm_errno2status(errno));
+
+ darg.data_ptr = arg;
+ darg.data_size = asize;
+ darg.desc_ptr = NULL;
+ darg.desc_num = 0;
+ darg.rbuf = rbuf;
+ darg.rsize = *rsizep;
+
+ if (door_call(fd, &darg) == -1)
+ status = dladm_errno2status(errno);
+ (void) close(fd);
+
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (darg.rbuf != rbuf) {
+ /*
+ * The size of the input rbuf is not big enough so that
+ * the door allocate the rbuf itself. In this case, simply
+ * think something wrong with the door call.
+ */
+ (void) munmap(darg.rbuf, darg.rsize);
+ return (DLADM_STATUS_TOOSMALL);
+ }
+ if (darg.rsize > *rsizep || darg.rsize < sizeof (uint_t))
+ return (DLADM_STATUS_FAILED);
+
+ if (retvalp->lr_err != 0)
+ status = dladm_errno2status(retvalp->lr_err);
+ else
+ *rsizep = darg.rsize;
+ return (status);
+}
+
+/*
+ * Allocate a new linkid with the given name. Return the new linkid.
+ */
+dladm_status_t
+dladm_create_datalink_id(const char *link, datalink_class_t class,
+ uint32_t media, uint32_t flags, datalink_id_t *linkidp)
+{
+ dlmgmt_door_createid_t createid;
+ dlmgmt_createid_retval_t retval;
+ uint32_t dlmgmt_flags;
+ dladm_status_t status;
+ size_t rsize;
+
+ if (link == NULL || *link == '\0' || class == DATALINK_CLASS_ALL ||
+ !(flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST)) ||
+ linkidp == NULL) {
+ return (DLADM_STATUS_BADARG);
+ }
+
+ dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
+ dlmgmt_flags |= (flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0;
+
+ (void) strlcpy(createid.ld_link, link, MAXLINKNAMELEN);
+ createid.ld_class = class;
+ createid.ld_media = media;
+ createid.ld_flags = dlmgmt_flags;
+ createid.ld_cmd = DLMGMT_CMD_CREATE_LINKID;
+ createid.ld_prefix = (flags & DLADM_OPT_PREFIX);
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&createid, sizeof (createid), &retval, &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ *linkidp = retval.lr_linkid;
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Destroy the given link ID.
+ */
+dladm_status_t
+dladm_destroy_datalink_id(datalink_id_t linkid, uint32_t flags)
+{
+ dlmgmt_door_destroyid_t destroyid;
+ dlmgmt_destroyid_retval_t retval;
+ uint32_t dlmgmt_flags;
+ size_t rsize;
+ dladm_status_t status;
+
+ dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
+ dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
+
+ destroyid.ld_cmd = DLMGMT_CMD_DESTROY_LINKID;
+ destroyid.ld_linkid = linkid;
+ destroyid.ld_flags = dlmgmt_flags;
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&destroyid, sizeof (destroyid), &retval,
+ &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Remap a given link ID to a new name.
+ */
+dladm_status_t
+dladm_remap_datalink_id(datalink_id_t linkid, const char *link)
+{
+ dlmgmt_door_remapid_t remapid;
+ dlmgmt_remapid_retval_t retval;
+ size_t rsize;
+ dladm_status_t status;
+
+ remapid.ld_cmd = DLMGMT_CMD_REMAP_LINKID;
+ remapid.ld_linkid = linkid;
+ (void) strlcpy(remapid.ld_link, link, MAXLINKNAMELEN);
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&remapid, sizeof (remapid), &retval, &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Make a given link ID active.
+ */
+dladm_status_t
+dladm_up_datalink_id(datalink_id_t linkid)
+{
+ dlmgmt_door_upid_t upid;
+ dlmgmt_upid_retval_t retval;
+ size_t rsize;
+ dladm_status_t status;
+
+ upid.ld_cmd = DLMGMT_CMD_UP_LINKID;
+ upid.ld_linkid = linkid;
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&upid, sizeof (upid), &retval, &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Create a new link with the given name. Return the new link's handle
+ */
+dladm_status_t
+dladm_create_conf(const char *link, datalink_id_t linkid,
+ datalink_class_t class, uint32_t media, dladm_conf_t *confp)
+{
+ dlmgmt_door_createconf_t createconf;
+ dlmgmt_createconf_retval_t retval;
+ dladm_status_t status;
+ size_t rsize;
+
+ if (link == NULL || *link == '\0' || confp == NULL)
+ return (DLADM_STATUS_BADARG);
+
+ (void) strlcpy(createconf.ld_link, link, MAXLINKNAMELEN);
+ createconf.ld_class = class;
+ createconf.ld_media = media;
+ createconf.ld_linkid = linkid;
+ createconf.ld_cmd = DLMGMT_CMD_CREATECONF;
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&createconf, sizeof (createconf), &retval,
+ &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ *confp = retval.lr_conf;
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * An active physical link reported by the dlmgmtd daemon might not be active
+ * anymore as this link might be removed during system shutdown. Check its
+ * real status by calling dladm_phys_info().
+ */
+dladm_status_t
+i_dladm_phys_status(datalink_id_t linkid, uint32_t *flagsp)
+{
+ dladm_phys_attr_t dpa;
+ dladm_status_t status;
+
+ assert((*flagsp) & DLMGMT_ACTIVE);
+
+ status = dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE);
+ if (status == DLADM_STATUS_NOTFOUND) {
+ /*
+ * No active status, this link was removed. Update its status
+ * in the daemon and delete all active linkprops.
+ */
+ (void) dladm_destroy_datalink_id(linkid, DLADM_OPT_ACTIVE);
+ (void) dladm_set_linkprop(linkid, NULL, NULL, 0,
+ DLADM_OPT_ACTIVE);
+
+ (*flagsp) &= ~DLMGMT_ACTIVE;
+ status = DLADM_STATUS_OK;
+ }
+ return (status);
+}
+
+/*
+ * Walk each entry in the data link configuration repository and
+ * call fn on the linkid and arg.
+ */
+dladm_status_t
+dladm_walk_datalink_id(int (*fn)(datalink_id_t, void *), void *argp,
+ datalink_class_t class, datalink_media_t dmedia, uint32_t flags)
+{
+ dlmgmt_door_getnext_t getnext;
+ dlmgmt_getnext_retval_t retval;
+ uint32_t dlmgmt_flags;
+ size_t rsize;
+ datalink_id_t linkid = DATALINK_INVALID_LINKID;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ if (fn == NULL)
+ return (DLADM_STATUS_BADARG);
+
+ dlmgmt_flags = (flags & DLADM_OPT_ACTIVE) ? DLMGMT_ACTIVE : 0;
+ dlmgmt_flags |= ((flags & DLADM_OPT_PERSIST) ? DLMGMT_PERSIST : 0);
+
+ getnext.ld_cmd = DLMGMT_CMD_GETNEXT;
+ getnext.ld_class = class;
+ getnext.ld_dmedia = dmedia;
+ getnext.ld_flags = dlmgmt_flags;
+ rsize = sizeof (retval);
+
+ do {
+ getnext.ld_linkid = linkid;
+ status = dladm_door_call(&getnext, sizeof (getnext),
+ &retval, &rsize);
+ if (status != DLADM_STATUS_OK) {
+ /*
+ * done with walking
+ */
+ break;
+ }
+
+ if (rsize != sizeof (retval)) {
+ status = DLADM_STATUS_BADARG;
+ break;
+ }
+
+ linkid = retval.lr_linkid;
+ if ((retval.lr_class == DATALINK_CLASS_PHYS) &&
+ (retval.lr_flags & DLMGMT_ACTIVE)) {
+ /*
+ * An active physical link reported by the dlmgmtd
+ * daemon might not be active anymore. Check its
+ * real status.
+ */
+ if (i_dladm_phys_status(linkid, &retval.lr_flags) !=
+ DLADM_STATUS_OK) {
+ continue;
+ }
+
+ if (!(dlmgmt_flags & retval.lr_flags))
+ continue;
+ }
+
+ if (fn(linkid, argp) == DLADM_WALK_TERMINATE)
+ break;
+ } while (linkid != DATALINK_INVALID_LINKID);
+
+ return (status);
+}
+
+/*
+ * Get the link properties structure for the given link.
+ */
+dladm_status_t
+dladm_read_conf(datalink_id_t linkid, dladm_conf_t *confp)
+{
+ dlmgmt_door_readconf_t readconf;
+ dlmgmt_readconf_retval_t retval;
+ dladm_status_t status;
+ size_t rsize;
+
+ if (linkid == DATALINK_INVALID_LINKID || confp == NULL)
+ return (DLADM_STATUS_BADARG);
+
+ readconf.ld_linkid = linkid;
+ readconf.ld_cmd = DLMGMT_CMD_READCONF;
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&readconf, sizeof (readconf), &retval,
+ &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ *confp = retval.lr_conf;
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Commit the given link to the data link configuration repository so
+ * that it will persist across reboots.
+ */
+dladm_status_t
+dladm_write_conf(dladm_conf_t conf)
+{
+ dlmgmt_door_writeconf_t writeconf;
+ dlmgmt_writeconf_retval_t retval;
+ dladm_status_t status;
+ size_t rsize;
+
+ if (conf == DLADM_INVALID_CONF)
+ return (DLADM_STATUS_BADARG);
+
+ writeconf.ld_cmd = DLMGMT_CMD_WRITECONF;
+ writeconf.ld_conf = conf;
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&writeconf, sizeof (writeconf), &retval,
+ &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Given a link ID and a key, get the matching information from
+ * data link configuration repository.
+ */
+dladm_status_t
+dladm_get_conf_field(dladm_conf_t conf, const char *attr, void *attrval,
+ size_t attrsz)
+{
+ dlmgmt_door_getattr_t getattr;
+ dlmgmt_getattr_retval_t *retvalp;
+ dladm_status_t status = DLADM_STATUS_OK;
+ size_t oldsize, size;
+
+ if (conf == DLADM_INVALID_CONF || attrval == NULL ||
+ attrsz == 0 || attr == NULL || *attr == '\0') {
+ return (DLADM_STATUS_BADARG);
+ }
+
+ getattr.ld_cmd = DLMGMT_CMD_GETATTR;
+ getattr.ld_conf = conf;
+ (void) strlcpy(getattr.ld_attr, attr, MAXLINKATTRLEN);
+
+ oldsize = size = attrsz + sizeof (dlmgmt_getattr_retval_t) - 1;
+ if ((retvalp = calloc(1, oldsize)) == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ status = dladm_door_call(&getattr, sizeof (getattr), retvalp, &size);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ assert(size <= oldsize);
+ size = size + 1 - sizeof (dlmgmt_getattr_retval_t);
+ bcopy(retvalp->lr_attr, attrval, size);
+done:
+ free(retvalp);
+ return (status);
+}
+
+/*
+ * Get the link ID that is associated with the given name.
+ */
+dladm_status_t
+dladm_name2info(const char *link, datalink_id_t *linkidp, uint32_t *flagp,
+ datalink_class_t *classp, uint32_t *mediap)
+{
+ dlmgmt_door_getlinkid_t getlinkid;
+ dlmgmt_getlinkid_retval_t retval;
+ datalink_id_t linkid;
+ size_t rsize;
+ dladm_status_t status;
+
+ getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID;
+ (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN);
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&getlinkid, sizeof (getlinkid), &retval,
+ &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ linkid = retval.lr_linkid;
+ if (retval.lr_class == DATALINK_CLASS_PHYS &&
+ retval.lr_flags & DLMGMT_ACTIVE) {
+ /*
+ * An active physical link reported by the dlmgmtd daemon
+ * might not be active anymore. Check and set its real status.
+ */
+ status = i_dladm_phys_status(linkid, &retval.lr_flags);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ }
+
+ if (linkidp != NULL)
+ *linkidp = linkid;
+ if (flagp != NULL) {
+ *flagp = retval.lr_flags & DLMGMT_ACTIVE ? DLADM_OPT_ACTIVE : 0;
+ *flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
+ DLADM_OPT_PERSIST : 0;
+ }
+ if (classp != NULL)
+ *classp = retval.lr_class;
+ if (mediap != NULL)
+ *mediap = retval.lr_media;
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Get the link name that is associated with the given id.
+ */
+dladm_status_t
+dladm_datalink_id2info(datalink_id_t linkid, uint32_t *flagp,
+ datalink_class_t *classp, uint32_t *mediap, char *link, size_t len)
+{
+ dlmgmt_door_getname_t getname;
+ dlmgmt_getname_retval_t retval;
+ size_t rsize;
+ dladm_status_t status;
+
+ if ((linkid == DATALINK_INVALID_LINKID) || (link != NULL && len == 0) ||
+ (link == NULL && len != 0)) {
+ return (DLADM_STATUS_BADARG);
+ }
+
+ getname.ld_cmd = DLMGMT_CMD_GETNAME;
+ getname.ld_linkid = linkid;
+ rsize = sizeof (retval);
+ status = dladm_door_call(&getname, sizeof (getname), &retval, &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if ((rsize != sizeof (retval)) ||
+ (len != 0 && (strlen(retval.lr_link) + 1 > len))) {
+ return (DLADM_STATUS_TOOSMALL);
+ }
+
+ if (retval.lr_class == DATALINK_CLASS_PHYS &&
+ retval.lr_flags & DLMGMT_ACTIVE) {
+ /*
+ * An active physical link reported by the dlmgmtd daemon
+ * might not be active anymore. Check and set its real status.
+ */
+ status = i_dladm_phys_status(linkid, &retval.lr_flags);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ }
+
+ if (link != NULL)
+ (void) strlcpy(link, retval.lr_link, len);
+ if (classp != NULL)
+ *classp = retval.lr_class;
+ if (mediap != NULL)
+ *mediap = retval.lr_media;
+ if (flagp != NULL) {
+ *flagp = retval.lr_flags & DLMGMT_ACTIVE ?
+ DLADM_OPT_ACTIVE : 0;
+ *flagp |= (retval.lr_flags & DLMGMT_PERSIST) ?
+ DLADM_OPT_PERSIST : 0;
+ }
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Set the given attr with the given attrval for the given link.
+ */
+dladm_status_t
+dladm_set_conf_field(dladm_conf_t conf, const char *attr,
+ dladm_datatype_t type, const void *attrval)
+{
+ dlmgmt_door_setattr_t *setattrp;
+ dlmgmt_setattr_retval_t retval;
+ dladm_status_t status;
+ size_t asize, attrsz, rsize;
+
+ if (attr == NULL || attr == '\0' || attrval == NULL)
+ return (DLADM_STATUS_BADARG);
+
+ if (type == DLADM_TYPE_STR)
+ attrsz = strlen(attrval) + 1;
+ else
+ attrsz = dladm_datatype_size[type];
+
+ asize = sizeof (dlmgmt_door_setattr_t) + attrsz - 1;
+ if ((setattrp = calloc(1, asize)) == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ setattrp->ld_cmd = DLMGMT_CMD_SETATTR;
+ setattrp->ld_conf = conf;
+ (void) strlcpy(setattrp->ld_attr, attr, MAXLINKATTRLEN);
+ setattrp->ld_attrsz = attrsz;
+ setattrp->ld_type = type;
+ bcopy(attrval, &setattrp->ld_attrval, attrsz);
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(setattrp, asize, &retval, &rsize);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ if (rsize != sizeof (retval))
+ status = DLADM_STATUS_BADARG;
+
+done:
+ free(setattrp);
+ return (status);
+}
+
+/*
+ * Unset the given attr the given link.
+ */
+dladm_status_t
+dladm_unset_conf_field(dladm_conf_t conf, const char *attr)
+{
+ dlmgmt_door_unsetattr_t unsetattr;
+ dlmgmt_unsetattr_retval_t retval;
+ dladm_status_t status;
+ size_t rsize;
+
+ if (attr == NULL || attr == '\0')
+ return (DLADM_STATUS_BADARG);
+
+ unsetattr.ld_cmd = DLMGMT_CMD_UNSETATTR;
+ unsetattr.ld_conf = conf;
+ (void) strlcpy(unsetattr.ld_attr, attr, MAXLINKATTRLEN);
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&unsetattr, sizeof (unsetattr), &retval,
+ &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Remove the given link ID and its entry from the data link configuration
+ * repository.
+ */
+dladm_status_t
+dladm_remove_conf(datalink_id_t linkid)
+{
+ dlmgmt_door_removeconf_t removeconf;
+ dlmgmt_removeconf_retval_t retval;
+ size_t rsize;
+ dladm_status_t status;
+
+ removeconf.ld_cmd = DLMGMT_CMD_REMOVECONF;
+ removeconf.ld_linkid = linkid;
+ rsize = sizeof (retval);
+
+ status = dladm_door_call(&removeconf, sizeof (removeconf), &retval,
+ &rsize);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (rsize != sizeof (retval))
+ return (DLADM_STATUS_BADARG);
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Free the contents of the link structure.
+ */
+void
+dladm_destroy_conf(dladm_conf_t conf)
+{
+ dlmgmt_door_destroyconf_t destroyconf;
+ dlmgmt_destroyconf_retval_t retval;
+ size_t rsize;
+
+ if (conf == DLADM_INVALID_CONF)
+ return;
+
+ destroyconf.ld_cmd = DLMGMT_CMD_DESTROYCONF;
+ destroyconf.ld_conf = conf;
+ rsize = sizeof (retval);
+
+ (void) dladm_door_call(&destroyconf, sizeof (destroyconf), &retval,
+ &rsize);
+}
diff --git a/usr/src/lib/libdladm/common/libdlmgmt.h b/usr/src/lib/libdladm/common/libdlmgmt.h
new file mode 100644
index 0000000000..0459d7360b
--- /dev/null
+++ b/usr/src/lib/libdladm/common/libdlmgmt.h
@@ -0,0 +1,199 @@
+/*
+ * 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
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This file includes structures, macros used to communicate with linkmgmt
+ * daemon.
+ */
+
+#ifndef _LIBDLMGMT_H
+#define _LIBDLMGMT_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <libdladm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * datalink management related macros, structures.
+ */
+
+/*
+ * Door call commands.
+ */
+#define DLMGMT_CMD_CREATE_LINKID (DLMGMT_CMD_BASE + 0)
+#define DLMGMT_CMD_DESTROY_LINKID (DLMGMT_CMD_BASE + 1)
+#define DLMGMT_CMD_REMAP_LINKID (DLMGMT_CMD_BASE + 2)
+#define DLMGMT_CMD_CREATECONF (DLMGMT_CMD_BASE + 3)
+#define DLMGMT_CMD_READCONF (DLMGMT_CMD_BASE + 4)
+#define DLMGMT_CMD_WRITECONF (DLMGMT_CMD_BASE + 5)
+#define DLMGMT_CMD_UP_LINKID (DLMGMT_CMD_BASE + 6)
+#define DLMGMT_CMD_SETATTR (DLMGMT_CMD_BASE + 7)
+#define DLMGMT_CMD_UNSETATTR (DLMGMT_CMD_BASE + 8)
+#define DLMGMT_CMD_REMOVECONF (DLMGMT_CMD_BASE + 9)
+#define DLMGMT_CMD_DESTROYCONF (DLMGMT_CMD_BASE + 10)
+#define DLMGMT_CMD_GETATTR (DLMGMT_CMD_BASE + 11)
+
+typedef struct dlmgmt_door_createid_s {
+ int ld_cmd;
+ char ld_link[MAXLINKNAMELEN];
+ datalink_class_t ld_class;
+ uint32_t ld_media;
+ boolean_t ld_prefix;
+ uint32_t ld_flags;
+} dlmgmt_door_createid_t;
+
+typedef struct dlmgmt_door_destroyid_s {
+ int ld_cmd;
+ datalink_id_t ld_linkid;
+ uint32_t ld_flags;
+} dlmgmt_door_destroyid_t;
+
+typedef struct dlmgmt_door_remapid_s {
+ int ld_cmd;
+ datalink_id_t ld_linkid;
+ char ld_link[MAXLINKNAMELEN];
+} dlmgmt_door_remapid_t;
+
+typedef struct dlmgmt_door_upid_s {
+ int ld_cmd;
+ datalink_id_t ld_linkid;
+} dlmgmt_door_upid_t;
+
+typedef struct dlmgmt_door_createconf_s {
+ int ld_cmd;
+ char ld_link[MAXLINKNAMELEN];
+ datalink_id_t ld_linkid;
+ datalink_class_t ld_class;
+ uint32_t ld_media;
+} dlmgmt_door_createconf_t;
+
+typedef struct dlmgmt_door_setattr_s {
+ int ld_cmd;
+ dladm_conf_t ld_conf;
+ char ld_attr[MAXLINKATTRLEN];
+ size_t ld_attrsz;
+ dladm_datatype_t ld_type;
+ char ld_attrval[1];
+} dlmgmt_door_setattr_t;
+
+typedef struct dlmgmt_door_unsetattr_s {
+ int ld_cmd;
+ dladm_conf_t ld_conf;
+ char ld_attr[MAXLINKATTRLEN];
+} dlmgmt_door_unsetattr_t;
+
+typedef struct dlmgmt_door_writeconf_s {
+ int ld_cmd;
+ dladm_conf_t ld_conf;
+} dlmgmt_door_writeconf_t;
+
+typedef struct dlmgmt_door_removeconf_s {
+ int ld_cmd;
+ datalink_id_t ld_linkid;
+} dlmgmt_door_removeconf_t;
+
+typedef struct dlmgmt_door_destroyconf_s {
+ int ld_cmd;
+ dladm_conf_t ld_conf;
+} dlmgmt_door_destroyconf_t;
+
+typedef struct dlmgmt_door_readconf_s {
+ int ld_cmd;
+ datalink_id_t ld_linkid;
+} dlmgmt_door_readconf_t;
+
+typedef struct dlmgmt_door_getattr_s {
+ int ld_cmd;
+ dladm_conf_t ld_conf;
+ char ld_attr[MAXLINKATTRLEN];
+} dlmgmt_door_getattr_t;
+
+typedef union dlmgmt_door_arg_s {
+ int ld_cmd;
+ dlmgmt_upcall_arg_create_t kcreate;
+ dlmgmt_upcall_arg_destroy_t kdestroy;
+ dlmgmt_upcall_arg_getattr_t kgetattr;
+ dlmgmt_door_getlinkid_t getlinkid;
+ dlmgmt_door_getnext_t getnext;
+ dlmgmt_door_createid_t createid;
+ dlmgmt_door_destroyid_t destroyid;
+ dlmgmt_door_remapid_t remapid;
+ dlmgmt_door_upid_t upid;
+ dlmgmt_door_createconf_t createconf;
+ dlmgmt_door_getname_t getname;
+ dlmgmt_door_getattr_t getattr;
+ dlmgmt_door_setattr_t setattr;
+ dlmgmt_door_writeconf_t writeconf;
+ dlmgmt_door_removeconf_t removeconf;
+ dlmgmt_door_destroyconf_t destroyconf;
+ dlmgmt_door_readconf_t readconf;
+} dlmgmt_door_arg_t;
+
+typedef struct dlmgmt_handle_retval_s {
+ uint_t lr_err;
+ dladm_conf_t lr_conf;
+} dlmgmt_createconf_retval_t, dlmgmt_readconf_retval_t;
+
+typedef struct dlmgmt_null_retval_s dlmgmt_remapid_retval_t,
+ dlmgmt_upid_retval_t,
+ dlmgmt_destroyid_retval_t,
+ dlmgmt_setattr_retval_t,
+ dlmgmt_unsetattr_retval_t,
+ dlmgmt_writeconf_retval_t,
+ dlmgmt_removeconf_retval_t,
+ dlmgmt_destroyconf_retval_t;
+
+typedef struct dlmgmt_linkid_retval_s dlmgmt_createid_retval_t;
+
+typedef union dlmgmt_retval {
+ uint_t lr_err; /* return error code */
+ dlmgmt_create_retval_t kcreate;
+ dlmgmt_destroy_retval_t kdestroy;
+ dlmgmt_getattr_retval_t getattr;
+ dlmgmt_getname_retval_t getname;
+ dlmgmt_getlinkid_retval_t getlinkid;
+ dlmgmt_getnext_retval_t getnext;
+ dlmgmt_createid_retval_t createid;
+ dlmgmt_destroyid_retval_t destroyid;
+ dlmgmt_remapid_retval_t remapid;
+ dlmgmt_upid_retval_t upid;
+ dlmgmt_createconf_retval_t createconf;
+ dlmgmt_readconf_retval_t readconf;
+ dlmgmt_setattr_retval_t setattr;
+ dlmgmt_writeconf_retval_t writeconf;
+ dlmgmt_removeconf_retval_t removeconf;
+ dlmgmt_destroyconf_retval_t destroyconf;
+} dlmgmt_retval_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBDLMGMT_H */
diff --git a/usr/src/lib/libdladm/common/libdlvlan.c b/usr/src/lib/libdladm/common/libdlvlan.c
new file mode 100644
index 0000000000..fb84ad92f6
--- /dev/null
+++ b/usr/src/lib/libdladm/common/libdlvlan.c
@@ -0,0 +1,345 @@
+/*
+ * 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
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/dld.h>
+#include <libdladm_impl.h>
+#include <libdllink.h>
+#include <libdlvlan.h>
+
+/*
+ * VLAN Administration Library.
+ *
+ * This library is used by administration tools such as dladm(1M) to
+ * configure VLANs.
+ */
+
+/*
+ * Returns the current attributes of the specified VLAN.
+ */
+static dladm_status_t
+i_dladm_vlan_info_active(datalink_id_t vlanid, dladm_vlan_attr_t *dvap)
+{
+ int fd;
+ dld_ioc_vlan_attr_t div;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ div.div_vlanid = vlanid;
+
+ if (i_dladm_ioctl(fd, DLDIOC_VLAN_ATTR, &div, sizeof (div)) < 0)
+ status = dladm_errno2status(errno);
+
+ dvap->dv_vid = div.div_vid;
+ dvap->dv_linkid = div.div_linkid;
+ dvap->dv_force = div.div_force;
+ dvap->dv_implicit = div.div_implicit;
+done:
+ (void) close(fd);
+ return (status);
+}
+
+/*
+ * Returns the persistent attributes of the specified VLAN.
+ */
+static dladm_status_t
+i_dladm_vlan_info_persist(datalink_id_t vlanid, dladm_vlan_attr_t *dvap)
+{
+ dladm_conf_t conf = DLADM_INVALID_CONF;
+ dladm_status_t status;
+ uint64_t u64;
+
+ if ((status = dladm_read_conf(vlanid, &conf)) != DLADM_STATUS_OK)
+ return (status);
+
+ status = dladm_get_conf_field(conf, FLINKOVER, &u64, sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ dvap->dv_linkid = (datalink_id_t)u64;
+
+ status = dladm_get_conf_field(conf, FFORCE, &dvap->dv_force,
+ sizeof (boolean_t));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ dvap->dv_implicit = B_FALSE;
+
+ status = dladm_get_conf_field(conf, FVLANID, &u64, sizeof (u64));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ dvap->dv_vid = (uint16_t)u64;
+
+done:
+ dladm_destroy_conf(conf);
+ return (status);
+}
+
+dladm_status_t
+dladm_vlan_info(datalink_id_t vlanid, dladm_vlan_attr_t *dvap, uint32_t flags)
+{
+ assert(flags == DLADM_OPT_ACTIVE || flags == DLADM_OPT_PERSIST);
+ if (flags == DLADM_OPT_ACTIVE)
+ return (i_dladm_vlan_info_active(vlanid, dvap));
+ else
+ return (i_dladm_vlan_info_persist(vlanid, dvap));
+}
+
+static dladm_status_t
+dladm_persist_vlan_conf(const char *vlan, datalink_id_t vlanid,
+ boolean_t force, datalink_id_t linkid, uint16_t vid)
+{
+ dladm_conf_t conf = DLADM_INVALID_CONF;
+ dladm_status_t status;
+ uint64_t u64;
+
+ if ((status = dladm_create_conf(vlan, vlanid, DATALINK_CLASS_VLAN,
+ DL_ETHER, &conf)) != DLADM_STATUS_OK) {
+ return (status);
+ }
+
+ u64 = linkid;
+ status = dladm_set_conf_field(conf, FLINKOVER, DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ status = dladm_set_conf_field(conf, FFORCE, DLADM_TYPE_BOOLEAN, &force);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ u64 = vid;
+ status = dladm_set_conf_field(conf, FVLANID, DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ status = dladm_write_conf(conf);
+
+done:
+ dladm_destroy_conf(conf);
+ return (status);
+}
+
+/*
+ * Create a VLAN on given link.
+ */
+dladm_status_t
+dladm_vlan_create(const char *vlan, datalink_id_t linkid, uint16_t vid,
+ uint32_t flags)
+{
+ dld_ioc_create_vlan_t dic;
+ int fd;
+ datalink_id_t vlanid = DATALINK_INVALID_LINKID;
+ uint_t media;
+ datalink_class_t class;
+ dladm_status_t status;
+
+ if (vid < 1 || vid > 4094)
+ return (DLADM_STATUS_VIDINVAL);
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
+ if (status != DLADM_STATUS_OK || media != DL_ETHER ||
+ class == DATALINK_CLASS_VLAN) {
+ return (DLADM_STATUS_BADARG);
+ }
+
+ status = dladm_create_datalink_id(vlan, DATALINK_CLASS_VLAN, DL_ETHER,
+ flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST), &vlanid);
+ if (status != DLADM_STATUS_OK)
+ goto fail;
+
+ if (flags & DLADM_OPT_PERSIST) {
+ status = dladm_persist_vlan_conf(vlan, vlanid,
+ (flags & DLADM_OPT_FORCE) != 0, linkid, vid);
+ if (status != DLADM_STATUS_OK)
+ goto fail;
+ }
+
+ if (flags & DLADM_OPT_ACTIVE) {
+ dic.dic_vlanid = vlanid;
+ dic.dic_linkid = linkid;
+ dic.dic_vid = vid;
+ dic.dic_force = (flags & DLADM_OPT_FORCE) != 0;
+
+ if (i_dladm_ioctl(fd, DLDIOC_CREATE_VLAN, &dic,
+ sizeof (dic)) < 0) {
+ status = dladm_errno2status(errno);
+ if (flags & DLADM_OPT_PERSIST)
+ (void) dladm_remove_conf(vlanid);
+ goto fail;
+ }
+ }
+
+ (void) close(fd);
+ return (DLADM_STATUS_OK);
+
+fail:
+ if (vlanid != DATALINK_INVALID_LINKID) {
+ (void) dladm_destroy_datalink_id(vlanid,
+ flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST));
+ }
+ (void) close(fd);
+ return (status);
+}
+
+/*
+ * Delete a given VLAN.
+ */
+dladm_status_t
+dladm_vlan_delete(datalink_id_t vlanid, uint32_t flags)
+{
+ dld_ioc_delete_vlan_t did;
+ int fd;
+ datalink_class_t class;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ if ((dladm_datalink_id2info(vlanid, NULL, &class, NULL, NULL, 0) !=
+ DLADM_STATUS_OK) || (class != DATALINK_CLASS_VLAN)) {
+ return (DLADM_STATUS_BADARG);
+ }
+
+ if (flags & DLADM_OPT_ACTIVE) {
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ did.did_linkid = vlanid;
+ if ((i_dladm_ioctl(fd, DLDIOC_DELETE_VLAN, &did,
+ sizeof (did)) < 0) &&
+ ((errno != ENOENT) || !(flags & DLADM_OPT_PERSIST))) {
+ (void) close(fd);
+ return (dladm_errno2status(errno));
+ }
+ (void) close(fd);
+
+ /*
+ * Delete active linkprop before this active link is deleted.
+ */
+ (void) dladm_set_linkprop(vlanid, NULL, NULL, 0,
+ DLADM_OPT_ACTIVE);
+ }
+
+ (void) dladm_destroy_datalink_id(vlanid,
+ flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST));
+
+ if (flags & DLADM_OPT_PERSIST)
+ (void) dladm_remove_conf(vlanid);
+
+ return (status);
+}
+
+/*
+ * Callback used by dladm_vlan_up()
+ */
+static int
+i_dladm_vlan_up(datalink_id_t vlanid, void *arg)
+{
+ dladm_vlan_attr_t dva;
+ dld_ioc_create_vlan_t dic;
+ dladm_status_t *statusp = arg;
+ uint32_t flags;
+ int fd;
+ dladm_status_t status;
+
+ status = dladm_vlan_info(vlanid, &dva, DLADM_OPT_PERSIST);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ /*
+ * Validate (and delete) the link associated with this VLAN, see if
+ * the specific hardware has been removed during system shutdown.
+ */
+ if ((status = dladm_datalink_id2info(dva.dv_linkid, &flags, NULL,
+ NULL, NULL, 0)) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if (!(flags & DLADM_OPT_ACTIVE)) {
+ status = DLADM_STATUS_BADARG;
+ goto done;
+ }
+
+ dic.dic_linkid = dva.dv_linkid;
+ dic.dic_force = dva.dv_force;
+ dic.dic_vid = dva.dv_vid;
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
+ status = dladm_errno2status(errno);
+ goto done;
+ }
+
+ dic.dic_vlanid = vlanid;
+ if (i_dladm_ioctl(fd, DLDIOC_CREATE_VLAN, &dic, sizeof (dic)) < 0) {
+ status = dladm_errno2status(errno);
+ goto done;
+ }
+
+ if ((status = dladm_up_datalink_id(vlanid)) != DLADM_STATUS_OK) {
+ dld_ioc_delete_vlan_t did;
+
+ did.did_linkid = vlanid;
+ (void) i_dladm_ioctl(fd, DLDIOC_DELETE_VLAN, &did,
+ sizeof (did));
+ } else {
+ /*
+ * Reset the active linkprop of this specific link.
+ */
+ (void) dladm_init_linkprop(vlanid);
+ }
+
+ (void) close(fd);
+done:
+ *statusp = status;
+ return (DLADM_WALK_CONTINUE);
+}
+
+/*
+ * Bring up one VLAN, or all persistent VLANs. In the latter case, the
+ * walk may terminate early if bringup of a VLAN fails.
+ */
+dladm_status_t
+dladm_vlan_up(datalink_id_t linkid)
+{
+ dladm_status_t status;
+
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(i_dladm_vlan_up, &status,
+ DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_PERSIST);
+ return (DLADM_STATUS_OK);
+ } else {
+ (void) i_dladm_vlan_up(linkid, &status);
+ return (status);
+ }
+}
diff --git a/usr/src/lib/libdladm/common/libdlvlan.h b/usr/src/lib/libdladm/common/libdlvlan.h
new file mode 100644
index 0000000000..7a305443df
--- /dev/null
+++ b/usr/src/lib/libdladm/common/libdlvlan.h
@@ -0,0 +1,60 @@
+/*
+ * 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
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBDLVLAN_H
+#define _LIBDLVLAN_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This file includes structures, macros and routines used by VLAN link
+ * administration.
+ */
+
+#include <libdladm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct dladm_vlan_attr {
+ uint16_t dv_vid;
+ datalink_id_t dv_linkid;
+ boolean_t dv_force;
+ boolean_t dv_implicit;
+} dladm_vlan_attr_t;
+
+extern dladm_status_t dladm_vlan_info(datalink_id_t, dladm_vlan_attr_t *,
+ uint32_t);
+extern dladm_status_t dladm_vlan_create(const char *, datalink_id_t,
+ uint16_t, uint32_t);
+extern dladm_status_t dladm_vlan_delete(datalink_id_t, uint32_t);
+extern dladm_status_t dladm_vlan_up(datalink_id_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBDLVLAN_H */
diff --git a/usr/src/lib/libdladm/common/libdlvnic.c b/usr/src/lib/libdladm/common/libdlvnic.c
index da9d57cd1b..272763b61d 100644
--- a/usr/src/lib/libdladm/common/libdlvnic.c
+++ b/usr/src/lib/libdladm/common/libdlvnic.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -39,6 +39,7 @@
#include <net/if_types.h>
#include <net/if_dl.h>
#include <libdladm_impl.h>
+#include <libdllink.h>
#include <libdlvnic.h>
/*
@@ -47,51 +48,19 @@
#define VNIC_DEV "/devices/pseudo/vnic@0:" VNIC_CTL_NODE_NAME
-/*
- * Because by default the id is used as the DLPI device PPA and default
- * VLAN PPA's are calculated as ((1000 * vid) + PPA), the largest id
- * can't be > 999. We reserve the last 100 VNIC ids for automatic
- * VNIC id assignment.
- */
-#define DLADM_VNIC_MIN_VNIC_ID 1 /* total range */
-#define DLADM_VNIC_MAX_VNIC_ID 999
-#define DLADM_VNIC_MIN_VNIC_SPEC_ID 1 /* specified by user */
-#define DLADM_VNIC_MAX_VNIC_SPEC_ID 899
-#define DLADM_VNIC_MIN_VNIC_AUTO_ID 900 /* picked automatically */
-#define DLADM_VNIC_MAX_VNIC_AUTO_ID 999
-
-#define DLADM_VNIC_NUM_VNIC_AUTO_ID (DLADM_VNIC_MAX_VNIC_AUTO_ID - \
- DLADM_VNIC_MIN_VNIC_AUTO_ID + 1)
-
/* Limits on buffer size for VNIC_IOC_INFO request */
#define MIN_INFO_SIZE (4*1024)
#define MAX_INFO_SIZE (128*1024)
/* configuration database entry */
typedef struct dladm_vnic_attr_db {
- uint_t vt_vnic_id;
- char vt_dev_name[MAXNAMELEN];
+ datalink_id_t vt_vnic_id;
+ datalink_id_t vt_link_id;
vnic_mac_addr_type_t vt_mac_addr_type;
uint_t vt_mac_len;
uchar_t vt_mac_addr[MAXMACADDRLEN];
} dladm_vnic_attr_db_t;
-typedef struct dladm_vnic_up {
- uint_t vu_vnic_id;
- boolean_t vu_found;
- int vu_fd;
-} dladm_vnic_up_t;
-
-typedef struct dladm_vnic_down {
- uint32_t vd_vnic_id;
- boolean_t vd_found;
-} dladm_vnic_down_t;
-
-typedef struct dladm_vnic_modify {
- uint32_t vm_vnic_id;
- boolean_t vm_found;
-} dladm_vnic_modify_t;
-
typedef struct dladm_vnic_modify_attr {
vnic_mac_addr_type_t vm_mac_addr_type;
int vm_mac_len;
@@ -108,7 +77,7 @@ i_dladm_vnic_create_sys(int fd, dladm_vnic_attr_db_t *attr)
vnic_ioc_create_t ioc;
ioc.vc_vnic_id = attr->vt_vnic_id;
- bcopy(attr->vt_dev_name, ioc.vc_dev_name, MAXNAMELEN);
+ ioc.vc_link_id = attr->vt_link_id;
ioc.vc_mac_addr_type = attr->vt_mac_addr_type;
ioc.vc_mac_len = attr->vt_mac_len;
bcopy(attr->vt_mac_addr, ioc.vc_mac_addr, attr->vt_mac_len);
@@ -122,31 +91,10 @@ i_dladm_vnic_create_sys(int fd, dladm_vnic_attr_db_t *attr)
}
/*
- * Invoked to bring up a VNIC.
- */
-static dladm_status_t
-i_dladm_vnic_up(void *arg, dladm_vnic_attr_db_t *attr)
-{
- dladm_vnic_up_t *up = (dladm_vnic_up_t *)arg;
- dladm_status_t status;
-
- if (up->vu_vnic_id != 0 && up->vu_vnic_id != attr->vt_vnic_id)
- return (DLADM_STATUS_OK);
-
- up->vu_found = B_TRUE;
-
- status = i_dladm_vnic_create_sys(up->vu_fd, attr);
- if ((status != DLADM_STATUS_OK) && (up->vu_vnic_id != 0))
- return (status);
-
- return (DLADM_STATUS_OK);
-}
-
-/*
* Send a modify command to the VNIC driver.
*/
static dladm_status_t
-i_dladm_vnic_modify_sys(uint_t vnic_id, uint32_t modify_mask,
+i_dladm_vnic_modify_sys(datalink_id_t vnic_id, uint32_t modify_mask,
dladm_vnic_modify_attr_t *attr)
{
int rc;
@@ -177,75 +125,49 @@ i_dladm_vnic_modify_sys(uint_t vnic_id, uint32_t modify_mask,
}
/*
- * Walk through the vnics defined on the system and for each vnic <vnic>,
- * invoke <fn>(<arg>, <vnic>);
+ * Get the configuration information of the given VNIC.
*/
dladm_status_t
-dladm_vnic_walk_sys(dladm_status_t (*fn)(void *, dladm_vnic_attr_sys_t *),
- void *arg)
+dladm_vnic_info(datalink_id_t vnic_id, dladm_vnic_attr_sys_t *attrp,
+ uint32_t flags)
{
vnic_ioc_info_t *ioc;
vnic_ioc_info_vnic_t *vnic;
- dladm_vnic_attr_sys_t attr;
- int rc, i, bufsize, fd;
- char *where;
+ int rc, bufsize, fd;
dladm_status_t status = DLADM_STATUS_OK;
+ /* for now, only temporary creations are supported */
+ if (flags & DLADM_OPT_PERSIST)
+ return (dladm_errno2status(ENOTSUP));
+
if ((fd = open(VNIC_DEV, O_RDWR)) == -1)
return (dladm_errno2status(errno));
- bufsize = MIN_INFO_SIZE;
+ bufsize = sizeof (vnic_ioc_info_t) + sizeof (vnic_ioc_info_vnic_t);
ioc = (vnic_ioc_info_t *)calloc(1, bufsize);
if (ioc == NULL) {
(void) close(fd);
return (dladm_errno2status(ENOMEM));
}
-tryagain:
-
+ ioc->vi_vnic_id = vnic_id;
rc = i_dladm_ioctl(fd, VNIC_IOC_INFO, ioc, bufsize);
-
if (rc != 0) {
- if (errno == ENOSPC) {
- bufsize *= 2;
- if (bufsize <= MAX_INFO_SIZE) {
- ioc = (vnic_ioc_info_t *)realloc(ioc, bufsize);
- if (ioc != NULL) {
- bzero(ioc, bufsize);
- goto tryagain;
- }
- }
- }
status = dladm_errno2status(errno);
goto bail;
}
- /*
- * Go through each vnic returned by the vnic driver
- */
- where = (char *)(ioc + 1);
-
- for (i = 0; i < ioc->vi_nvnics; i++) {
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- vnic = (vnic_ioc_info_vnic_t *)where;
-
- attr.va_vnic_id = vnic->vn_vnic_id;
- bcopy(vnic->vn_dev_name, attr.va_dev_name,
- MAXNAMELEN);
- attr.va_mac_addr_type = vnic->vn_mac_addr_type;
- bcopy(vnic->vn_mac_addr, attr.va_mac_addr, ETHERADDRL);
- attr.va_mac_len = vnic->vn_mac_len;
- where = (char *)(vnic + 1);
-
- status = fn(arg, &attr);
- if (status != DLADM_STATUS_OK)
- goto bail;
- }
+ vnic = (vnic_ioc_info_vnic_t *)(ioc + 1);
+
+ attrp->va_vnic_id = vnic->vn_vnic_id;
+ attrp->va_link_id = vnic->vn_link_id;
+ attrp->va_mac_addr_type = vnic->vn_mac_addr_type;
+ bcopy(vnic->vn_mac_addr, attrp->va_mac_addr, ETHERADDRL);
+ attrp->va_mac_len = vnic->vn_mac_len;
bail:
free(ioc);
(void) close(fd);
-
return (status);
}
@@ -269,34 +191,6 @@ i_dladm_vnic_delete_sys(int fd, dladm_vnic_attr_sys_t *attr)
}
/*
- * Invoked to bring down a VNIC.
- */
-static dladm_status_t
-i_dladm_vnic_down(void *arg, dladm_vnic_attr_sys_t *attr)
-{
- dladm_vnic_down_t *down = (dladm_vnic_down_t *)arg;
- int fd;
- dladm_status_t status;
-
- if (down->vd_vnic_id != 0 && down->vd_vnic_id != attr->va_vnic_id)
- return (DLADM_STATUS_OK);
-
- down->vd_found = B_TRUE;
-
- if ((fd = open(VNIC_DEV, O_RDWR)) < 0)
- return (dladm_errno2status(errno));
-
- status = i_dladm_vnic_delete_sys(fd, attr);
- if ((status != DLADM_STATUS_OK) && (down->vd_vnic_id != 0)) {
- (void) close(fd);
- return (status);
- }
-
- (void) close(fd);
- return (DLADM_STATUS_OK);
-}
-
-/*
* Convert between MAC address types and their string representations.
*/
@@ -311,9 +205,12 @@ static dladm_vnic_addr_type_t addr_types[] = {
#define NADDR_TYPES (sizeof (addr_types) / sizeof (dladm_vnic_addr_type_t))
-/* returns B_TRUE if a matching type was found, B_FALSE otherwise */
-boolean_t
-dladm_vnic_mac_addr_str_to_type(const char *str, vnic_mac_addr_type_t *val)
+/*
+ * Return DLADM_STATUS_OK if a matching type was found,
+ * DLADM_STATUS_BADARG otherwise
+ */
+dladm_status_t
+dladm_vnic_str2macaddrtype(const char *str, vnic_mac_addr_type_t *val)
{
int i;
dladm_vnic_addr_type_t *type;
@@ -322,127 +219,34 @@ dladm_vnic_mac_addr_str_to_type(const char *str, vnic_mac_addr_type_t *val)
type = &addr_types[i];
if (strncmp(str, type->va_str, strlen(type->va_str)) == 0) {
*val = type->va_type;
- return (B_TRUE);
+ return (DLADM_STATUS_OK);
}
}
- return (B_FALSE);
-}
-
-/*
- * Select a VNIC id automatically.
- */
-
-typedef struct dladm_vnic_auto_state_s {
- uint_t as_nslots;
- uint_t *as_slots;
-} dladm_vnic_auto_state_t;
-
-static dladm_status_t
-i_dladm_vnic_create_auto_walker(void *arg, dladm_vnic_attr_sys_t *attr)
-{
- dladm_vnic_auto_state_t *state = arg;
-
- if (attr->va_vnic_id < DLADM_VNIC_MIN_VNIC_AUTO_ID ||
- attr->va_vnic_id > DLADM_VNIC_MAX_VNIC_AUTO_ID)
- return (DLADM_STATUS_OK);
-
- state->as_slots[state->as_nslots++] = attr->va_vnic_id;
-
- return (DLADM_STATUS_OK);
-}
-
-static int
-i_dladm_vnic_compare(const void *p1, const void *p2)
-{
- uint_t i = *((uint_t *)p1);
- uint_t j = *((uint_t *)p2);
-
- if (i > j)
- return (1);
- if (i < j)
- return (-1);
- return (0);
-}
-
-/*ARGSUSED*/
-static dladm_status_t
-i_dladm_vnic_get_auto_id(dladm_vnic_attr_db_t *attr, uint32_t *vnic_id_out)
-{
- dladm_vnic_auto_state_t state;
- uint_t vnic_ids[DLADM_VNIC_NUM_VNIC_AUTO_ID];
- int i;
- uint_t last_id, vnic_id;
- dladm_status_t status;
-
- /*
- * Build a sorted array containing the existing VNIC ids in the range
- * allocated for automatic allocation.
- */
- state.as_nslots = 0;
- state.as_slots = vnic_ids;
-
- status = dladm_vnic_walk_sys(i_dladm_vnic_create_auto_walker, &state);
- if (status != DLADM_STATUS_OK)
- return (status);
-
- qsort(vnic_ids, state.as_nslots, sizeof (uint_t),
- i_dladm_vnic_compare);
-
- /*
- * Find a gap in the sequence of existing VNIC ids.
- */
- last_id = DLADM_VNIC_MIN_VNIC_AUTO_ID - 1;
- vnic_id = 0;
- for (i = 0; i < state.as_nslots; i++) {
- if (vnic_ids[i] > (last_id + 1)) {
- vnic_id = last_id + 1;
- break;
- }
- last_id = vnic_ids[i];
- }
-
- if (vnic_id == 0) {
- /*
- * Did not find a gap between existing entries, see if we
- * can add one.
- */
- if (last_id + 1 > DLADM_VNIC_MAX_VNIC_AUTO_ID)
- return (DLADM_STATUS_AUTOIDNOAVAILABLEID);
-
- /* still have room for one more VNIC */
- vnic_id = last_id + 1;
- }
-
- *vnic_id_out = vnic_id;
-
- return (DLADM_STATUS_OK);
+ return (DLADM_STATUS_BADARG);
}
/*
* Create a new VNIC. Update the configuration file and bring it up.
*/
dladm_status_t
-dladm_vnic_create(uint_t vnic_id, char *dev_name,
+dladm_vnic_create(const char *vnic, datalink_id_t linkid,
vnic_mac_addr_type_t mac_addr_type, uchar_t *mac_addr, int mac_len,
- uint_t *vnic_id_out, uint32_t flags)
+ datalink_id_t *vnic_id_out, uint32_t flags)
{
dladm_vnic_attr_db_t attr;
- int i;
- boolean_t tempop = ((flags & DLADM_VNIC_OPT_TEMP) != 0);
- boolean_t autoid = ((flags & DLADM_VNIC_OPT_AUTOID) != 0);
- dladm_vnic_up_t up;
+ int i, fd;
+ datalink_id_t vnic_id;
+ datalink_class_t class;
+ uint32_t media;
+ char *name = (char *)vnic;
dladm_status_t status;
/*
* Sanity test arguments.
*/
- if (autoid && !tempop)
- return (DLADM_STATUS_AUTOIDNOTEMP);
-
- if (!autoid && ((vnic_id < DLADM_VNIC_MIN_VNIC_SPEC_ID) ||
- (vnic_id > DLADM_VNIC_MAX_VNIC_SPEC_ID)))
- return (DLADM_STATUS_INVALIDID);
+ if (flags & DLADM_OPT_PERSIST)
+ return (dladm_errno2status(ENOTSUP));
if (mac_len > MAXMACADDRLEN)
return (DLADM_STATUS_INVALIDMACADDRLEN);
@@ -454,40 +258,46 @@ dladm_vnic_create(uint_t vnic_id, char *dev_name,
if (i == NADDR_TYPES)
return (DLADM_STATUS_INVALIDMACADDRTYPE);
- /* for now, only temporary creations are supported */
- if (!tempop)
- return (dladm_errno2status(ENOTSUP));
+ if ((status = dladm_datalink_id2info(linkid, NULL, &class, &media,
+ NULL, 0)) != DLADM_STATUS_OK) {
+ return (status);
+ }
-auto_again:
- if (autoid) {
- /*
- * Find an unused VNIC id.
- */
- status = i_dladm_vnic_get_auto_id(&attr, vnic_id_out);
- if (status != DLADM_STATUS_OK)
- return (status);
- vnic_id = *vnic_id_out;
+ if (class == DATALINK_CLASS_VNIC)
+ return (DLADM_STATUS_BADARG);
+
+ if (vnic == NULL) {
+ flags |= DLADM_OPT_PREFIX;
+ name = "vnic";
+ }
+
+ if ((status = dladm_create_datalink_id(name, DATALINK_CLASS_VNIC,
+ media, flags, &vnic_id)) != DLADM_STATUS_OK) {
+ return (status);
}
bzero(&attr, sizeof (attr));
attr.vt_vnic_id = vnic_id;
- (void) strncpy(attr.vt_dev_name, dev_name,
- sizeof (attr.vt_dev_name) - 1);
+ attr.vt_link_id = linkid;
attr.vt_mac_addr_type = mac_addr_type;
attr.vt_mac_len = mac_len;
bcopy(mac_addr, attr.vt_mac_addr, mac_len);
- up.vu_vnic_id = vnic_id;
- up.vu_found = B_FALSE;
- up.vu_fd = open(VNIC_DEV, O_RDWR);
- if (up.vu_fd < 0)
- return (dladm_errno2status(errno));
+ if ((fd = open(VNIC_DEV, O_RDWR)) < 0) {
+ status = dladm_errno2status(errno);
+ goto done;
+ }
- status = i_dladm_vnic_up((void *)&up, &attr);
- (void) close(up.vu_fd);
+ status = i_dladm_vnic_create_sys(fd, &attr);
+ (void) close(fd);
- if ((status == DLADM_STATUS_EXIST) && autoid)
- goto auto_again;
+done:
+ if (status != DLADM_STATUS_OK) {
+ (void) dladm_destroy_datalink_id(vnic_id,
+ flags & ~DLADM_OPT_PREFIX);
+ } else {
+ *vnic_id_out = vnic_id;
+ }
return (status);
}
@@ -496,19 +306,14 @@ auto_again:
* Modify the properties of a VNIC.
*/
dladm_status_t
-dladm_vnic_modify(uint_t vnic_id, uint32_t modify_mask,
+dladm_vnic_modify(datalink_id_t vnic_id, uint32_t modify_mask,
vnic_mac_addr_type_t mac_addr_type, uint_t mac_len, uchar_t *mac_addr,
uint32_t flags)
{
dladm_vnic_modify_attr_t new_attr;
- boolean_t tempop = ((flags & DLADM_VNIC_OPT_TEMP) != 0);
-
- if ((vnic_id < DLADM_VNIC_MIN_VNIC_ID) ||
- (vnic_id > DLADM_VNIC_MAX_VNIC_ID))
- return (DLADM_STATUS_INVALIDID);
/* for now, only temporary creations are supported */
- if (!tempop)
+ if (flags & DLADM_OPT_PERSIST)
return (dladm_errno2status(ENOTSUP));
bzero(&new_attr, sizeof (new_attr));
@@ -523,27 +328,30 @@ dladm_vnic_modify(uint_t vnic_id, uint32_t modify_mask,
return (i_dladm_vnic_modify_sys(vnic_id, modify_mask, &new_attr));
}
-
/*
* Delete a VNIC.
*/
dladm_status_t
-dladm_vnic_delete(uint_t vnic_id, uint32_t flags)
+dladm_vnic_delete(datalink_id_t vnic_id, uint32_t flags)
{
- boolean_t tempop = ((flags & DLADM_VNIC_OPT_TEMP) != 0);
- dladm_vnic_down_t down;
+ dladm_status_t status;
dladm_vnic_attr_sys_t sys_attr;
-
- if ((vnic_id < DLADM_VNIC_MIN_VNIC_ID) ||
- (vnic_id > DLADM_VNIC_MAX_VNIC_ID))
- return (DLADM_STATUS_INVALIDID);
+ int fd;
/* for now, only temporary deletes are supported */
- if (!tempop)
+ if (flags & DLADM_OPT_PERSIST)
return (dladm_errno2status(ENOTSUP));
- down.vd_vnic_id = vnic_id;
- down.vd_found = B_FALSE;
+ if ((fd = open(VNIC_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
sys_attr.va_vnic_id = vnic_id;
- return (i_dladm_vnic_down((void *)&down, &sys_attr));
+ status = i_dladm_vnic_delete_sys(fd, &sys_attr);
+ (void) close(fd);
+
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ (void) dladm_destroy_datalink_id(vnic_id, flags);
+ return (status);
}
diff --git a/usr/src/lib/libdladm/common/libdlvnic.h b/usr/src/lib/libdladm/common/libdlvnic.h
index 4f0726746c..79b4b01ba2 100644
--- a/usr/src/lib/libdladm/common/libdlvnic.h
+++ b/usr/src/lib/libdladm/common/libdlvnic.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,32 +38,26 @@ extern "C" {
#endif
typedef struct dladm_vnic_attr_sys {
- uint_t va_vnic_id;
- char va_dev_name[MAXNAMELEN + 1];
+ datalink_id_t va_vnic_id;
+ datalink_id_t va_link_id;
vnic_mac_addr_type_t va_mac_addr_type;
uchar_t va_mac_addr[ETHERADDRL];
uint_t va_mac_len;
} dladm_vnic_attr_sys_t;
/*
- * General operations flags.
- */
-#define DLADM_VNIC_OPT_TEMP 0x00000001
-#define DLADM_VNIC_OPT_AUTOID 0x00000002
-
-/*
* Modification flags for dladm_vnic_modify().
*/
#define DLADM_VNIC_MODIFY_ADDR 0x01
-extern dladm_status_t dladm_vnic_create(uint_t, char *, vnic_mac_addr_type_t,
- uchar_t *, int, uint_t *, uint32_t);
-extern dladm_status_t dladm_vnic_modify(uint_t, uint32_t, vnic_mac_addr_type_t,
- uint_t, uchar_t *, uint32_t);
-extern dladm_status_t dladm_vnic_delete(uint_t, uint32_t);
-extern dladm_status_t dladm_vnic_walk_sys(
- dladm_status_t (*)(void *, dladm_vnic_attr_sys_t *), void *);
-extern boolean_t dladm_vnic_mac_addr_str_to_type(const char *,
+extern dladm_status_t dladm_vnic_create(const char *, datalink_id_t,
+ vnic_mac_addr_type_t, uchar_t *, int, uint_t *, uint32_t);
+extern dladm_status_t dladm_vnic_modify(datalink_id_t, uint32_t,
+ vnic_mac_addr_type_t, uint_t, uchar_t *, uint32_t);
+extern dladm_status_t dladm_vnic_delete(datalink_id_t, uint32_t);
+extern dladm_status_t dladm_vnic_info(datalink_id_t, dladm_vnic_attr_sys_t *,
+ uint32_t);
+extern dladm_status_t dladm_vnic_str2macaddrtype(const char *,
vnic_mac_addr_type_t *);
#ifdef __cplusplus
diff --git a/usr/src/lib/libdladm/common/libdlwlan.c b/usr/src/lib/libdladm/common/libdlwlan.c
index 3819dd5050..6597b84ce0 100644
--- a/usr/src/lib/libdladm/common/libdlwlan.c
+++ b/usr/src/lib/libdladm/common/libdlwlan.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -28,163 +28,96 @@
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
-#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
+#include <stddef.h>
#include <string.h>
#include <stropts.h>
#include <libdevinfo.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
+#include <libdlpi.h>
+#include <libdllink.h>
#include <libscf.h>
#include <libdlwlan.h>
+#include <libdladm_impl.h>
#include <libdlwlan_impl.h>
#include <net/wpa.h>
-typedef struct val_desc {
- char *vd_name;
- uint_t vd_val;
-} val_desc_t;
-
-struct prop_desc;
-
-typedef dladm_status_t wl_pd_getf_t(int, wldp_t *, char **, uint_t *);
-typedef dladm_status_t wl_pd_setf_t(int, wldp_t *, val_desc_t *, uint_t);
-typedef dladm_status_t wl_pd_checkf_t(int, wldp_t *, struct prop_desc *,
- char **, uint_t, val_desc_t **);
-typedef struct prop_desc {
- char *pd_name;
- val_desc_t pd_defval;
- val_desc_t *pd_modval;
- uint_t pd_nmodval;
- wl_pd_setf_t *pd_set;
- wl_pd_getf_t *pd_getmod;
- wl_pd_getf_t *pd_get;
- 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 *);
-static int do_get_signal(int, wldp_t *);
-static int do_get_encryption(int, wldp_t *);
-static int do_get_authmode(int, wldp_t *);
-static int do_get_linkstatus(int, wldp_t *);
-static int do_get_esslist(int, wldp_t *);
-static int do_get_rate(int, wldp_t *);
-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_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 *);
-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(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 *);
+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_set_bsstype(datalink_id_t, dladm_wlan_bsstype_t *);
+static dladm_status_t do_set_authmode(datalink_id_t, dladm_wlan_auth_t *);
+static dladm_status_t do_set_encryption(datalink_id_t,
+ dladm_wlan_secmode_t *);
+static dladm_status_t do_set_essid(datalink_id_t, dladm_wlan_essid_t *);
+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 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 *);
static dladm_status_t dladm_wlan_wlresult2status(wldp_t *);
-
-static wl_pd_getf_t do_get_rate_mod, do_get_rate_prop, do_get_channel_prop,
- do_get_powermode_prop, do_get_radio_prop;
-static wl_pd_setf_t do_set_rate_prop, do_set_powermode_prop,
- do_set_radio_prop;
-static wl_pd_checkf_t do_check_prop, do_check_rate;
+static dladm_status_t dladm_wlan_validate(datalink_id_t);
static val_desc_t linkstatus_vals[] = {
- { "disconnected", DLADM_WLAN_LINKSTATUS_DISCONNECTED },
- { "connected", DLADM_WLAN_LINKSTATUS_CONNECTED }
+ { "disconnected", DLADM_WLAN_LINK_DISCONNECTED },
+ { "connected", DLADM_WLAN_LINK_CONNECTED }
};
static val_desc_t secmode_vals[] = {
- { "none", DLADM_WLAN_SECMODE_NONE },
- { "wep", DLADM_WLAN_SECMODE_WEP },
- { "wpa", DLADM_WLAN_SECMODE_WPA }
+ { "none", DLADM_WLAN_SECMODE_NONE },
+ { "wep", DLADM_WLAN_SECMODE_WEP },
+ { "wpa", DLADM_WLAN_SECMODE_WPA }
};
static val_desc_t strength_vals[] = {
- { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK },
- { "weak", DLADM_WLAN_STRENGTH_WEAK },
- { "good", DLADM_WLAN_STRENGTH_GOOD },
- { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD },
- { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT }
+ { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK },
+ { "weak", DLADM_WLAN_STRENGTH_WEAK },
+ { "good", DLADM_WLAN_STRENGTH_GOOD },
+ { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD},
+ { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT}
};
static val_desc_t mode_vals[] = {
- { "a", DLADM_WLAN_MODE_80211A },
- { "b", DLADM_WLAN_MODE_80211B },
- { "g", DLADM_WLAN_MODE_80211G },
+ { "a", DLADM_WLAN_MODE_80211A },
+ { "b", DLADM_WLAN_MODE_80211B },
+ { "g", DLADM_WLAN_MODE_80211G },
};
static val_desc_t auth_vals[] = {
- { "open", DLADM_WLAN_AUTH_OPEN },
- { "shared", DLADM_WLAN_AUTH_SHARED }
+ { "open", DLADM_WLAN_AUTH_OPEN },
+ { "shared", DLADM_WLAN_AUTH_SHARED }
};
static val_desc_t bsstype_vals[] = {
- { "bss", DLADM_WLAN_BSSTYPE_BSS },
- { "ibss", DLADM_WLAN_BSSTYPE_IBSS },
- { "any", DLADM_WLAN_BSSTYPE_ANY }
-};
-
-static val_desc_t radio_vals[] = {
- { "on", DLADM_WLAN_RADIO_ON },
- { "off", DLADM_WLAN_RADIO_OFF }
-};
-
-static val_desc_t powermode_vals[] = {
- { "off", DLADM_WLAN_PM_OFF },
- { "fast", DLADM_WLAN_PM_FAST },
- { "max", DLADM_WLAN_PM_MAX }
+ { "bss", DLADM_WLAN_BSSTYPE_BSS },
+ { "ibss", DLADM_WLAN_BSSTYPE_IBSS },
+ { "any", DLADM_WLAN_BSSTYPE_ANY }
};
-#define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t))
-static prop_desc_t prop_table[] = {
-
- { "channel", { NULL, 0 }, NULL, 0,
- NULL, NULL, do_get_channel_prop, do_check_prop},
-
- { "powermode", { "off", DLADM_WLAN_PM_OFF }, powermode_vals,
- VALCNT(powermode_vals),
- do_set_powermode_prop, NULL,
- do_get_powermode_prop, do_check_prop},
-
- { "radio", { "on", DLADM_WLAN_RADIO_ON }, radio_vals,
- VALCNT(radio_vals),
- do_set_radio_prop, NULL,
- do_get_radio_prop, do_check_prop},
-
- { "speed", { "", 0 }, NULL, 0,
- do_set_rate_prop, do_get_rate_mod,
- do_get_rate_prop, do_check_rate}
-};
-/*
- * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
- * rates to be retrieved. However, we cannot increase it at this
- * time because it will break binary comatibility with unbundled
- * WiFi drivers and utilities. So for now we define an additional
- * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
- */
-#define MAX_SUPPORT_RATES 64
-#define DLADM_WLAN_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
#define IS_CONNECTED(gbuf) \
((*(wl_linkstatus_t *)((gbuf)->wldp_buf) == WL_CONNECTED))
@@ -209,38 +142,6 @@ dladm_wlan_wlresult2status(wldp_t *gbuf)
return (DLADM_STATUS_FAILED);
}
-static int
-open_link(const char *link)
-{
- char linkname[MAXPATHLEN];
- wldp_t *gbuf;
- int fd;
-
- if (link == NULL)
- return (-1);
-
- (void) snprintf(linkname, MAXPATHLEN, "/dev/%s", link);
- if ((fd = open(linkname, O_RDWR)) < 0)
- return (-1);
-
- if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
- (void) close(fd);
- return (-1);
- }
-
- /*
- * Check to see if the link is wireless.
- */
- if (do_get_bsstype(fd, gbuf) < 0) {
- free(gbuf);
- (void) close(fd);
- return (-1);
- }
-
- free(gbuf);
- return (fd);
-}
-
static dladm_wlan_mode_t
do_convert_mode(wl_phy_conf_t *phyp)
{
@@ -259,8 +160,8 @@ do_convert_mode(wl_phy_conf_t *phyp)
return (DLADM_WLAN_MODE_NONE);
}
-static boolean_t
-do_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp)
+boolean_t
+i_dladm_wlan_convert_chan(wl_phy_conf_t *phyp, uint32_t *channelp)
{
wl_fhss_t *wlfp = &phyp->wl_phy_fhss_conf;
wl_ofdm_t *wlop = &phyp->wl_phy_ofdm_conf;
@@ -326,16 +227,16 @@ fill_wlan_attr(wl_ess_conf_t *wlp, dladm_wlan_attr_t *attrp)
if (attrp->wa_speed > 0)
attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED;
- if (do_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf,
+ if (i_dladm_wlan_convert_chan((wl_phy_conf_t *)&wlp->wl_phy_conf,
&attrp->wa_channel))
attrp->wa_valid |= DLADM_WLAN_ATTR_CHANNEL;
}
dladm_status_t
-dladm_wlan_scan(const char *link, void *arg,
+dladm_wlan_scan(datalink_id_t linkid, void *arg,
boolean_t (*func)(void *, dladm_wlan_attr_t *))
{
- int fd, i;
+ int i;
uint32_t count;
wl_ess_conf_t *wlp;
wldp_t *gbuf;
@@ -343,34 +244,28 @@ dladm_wlan_scan(const char *link, void *arg,
dladm_status_t status;
boolean_t connected;
- if ((fd = open_link(link)) < 0)
- return (DLADM_STATUS_LINKINVAL);
+ 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 (do_get_linkstatus(fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
- }
connected = IS_CONNECTED(gbuf);
- if (do_scan(fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ if ((status = do_scan(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
- }
if (func == NULL) {
status = DLADM_STATUS_OK;
goto done;
}
- if (do_get_esslist(fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ if ((status = do_get_esslist(linkid, gbuf)) != 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;
@@ -382,18 +277,16 @@ dladm_wlan_scan(const char *link, void *arg,
}
if (!connected) {
- if (do_get_linkstatus(fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ status = do_get_linkstatus(linkid, gbuf);
+ if (status != DLADM_STATUS_OK)
goto done;
- }
if (IS_CONNECTED(gbuf))
- (void) do_disconnect(link, fd, gbuf);
+ (void) do_disconnect(linkid, gbuf);
}
status = DLADM_STATUS_OK;
done:
free(gbuf);
- (void) close(fd);
return (status);
}
@@ -507,51 +400,61 @@ append:
#define IEEE80211_C_WPA 0x01800000
static dladm_status_t
-do_connect(const char *link, int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
+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)
{
- 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;
- dladm_wlan_channel_t channel;
- hrtime_t start;
- wl_capability_t *caps;
+ 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;
+ dladm_status_t status;
+ dladm_wlan_channel_t channel;
+ hrtime_t start;
+ wl_capability_t *caps;
if ((attrp->wa_valid & DLADM_WLAN_ATTR_CHANNEL) != 0) {
channel = attrp->wa_channel;
- if (do_set_channel(fd, gbuf, &channel) < 0)
+ status = do_set_channel(linkid, &channel);
+ if (status != DLADM_STATUS_OK)
goto fail;
}
secmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_SECMODE) != 0) ?
attrp->wa_secmode : DLADM_WLAN_SECMODE_NONE;
- if (do_set_encryption(fd, gbuf, &secmode) < 0)
+ if ((status = do_set_encryption(linkid, &secmode)) != DLADM_STATUS_OK)
goto fail;
authmode = ((attrp->wa_valid & DLADM_WLAN_ATTR_AUTH) != 0) ?
attrp->wa_auth : DLADM_WLAN_AUTH_OPEN;
- if (do_set_authmode(fd, gbuf, &authmode) < 0)
+ if ((status = do_set_authmode(linkid, &authmode)) != DLADM_STATUS_OK)
goto fail;
bsstype = ((attrp->wa_valid & DLADM_WLAN_ATTR_BSSTYPE) != 0) ?
attrp->wa_bsstype : DLADM_WLAN_BSSTYPE_BSS;
- if (do_set_bsstype(fd, gbuf, &bsstype) < 0)
+ if ((status = do_set_bsstype(linkid, &bsstype)) != DLADM_STATUS_OK)
goto fail;
if (secmode == DLADM_WLAN_SECMODE_WEP) {
- if (keys == NULL || key_count == 0 || key_count > MAX_NWEPKEYS)
- return (DLADM_STATUS_BADARG);
- if (do_set_key(fd, gbuf, keys, key_count) < 0)
+ if (keys == NULL || key_count == 0 ||
+ key_count > MAX_NWEPKEYS) {
+ status = DLADM_STATUS_BADARG;
+ goto fail;
+ }
+ status = do_set_key(linkid, keys, key_count);
+ if (status != DLADM_STATUS_OK)
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)
+ if (keys == NULL || key_count == 0 ||
+ key_count > MAX_NWEPKEYS) {
+ status = DLADM_STATUS_BADARG;
+ goto fail;
+ }
+ status = do_get_capability(linkid, gbuf);
+ if (status != DLADM_STATUS_OK)
goto fail;
caps = (wl_capability_t *)(gbuf->wldp_buf);
if ((caps->caps & IEEE80211_C_WPA) == 0)
@@ -559,10 +462,12 @@ do_connect(const char *link, int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
}
if (create_ibss) {
- if (do_set_channel(fd, gbuf, &channel) < 0)
+ status = do_set_channel(linkid, &channel);
+ if (status != DLADM_STATUS_OK)
goto fail;
- if (do_set_createibss(fd, gbuf, &create_ibss) < 0)
+ status = do_set_createibss(linkid, &create_ibss);
+ if (status != DLADM_STATUS_OK)
goto fail;
if ((attrp->wa_valid & DLADM_WLAN_ATTR_ESSID) == 0) {
@@ -576,9 +481,12 @@ do_connect(const char *link, int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
essid_valid = B_TRUE;
}
- if (!essid_valid)
- return (DLADM_STATUS_FAILED);
- if (do_set_essid(fd, gbuf, &essid) < 0)
+ if (!essid_valid) {
+ status = DLADM_STATUS_FAILED;
+ goto fail;
+ }
+
+ if ((status = do_set_essid(linkid, &essid)) != DLADM_STATUS_OK)
goto fail;
/*
@@ -586,11 +494,12 @@ do_connect(const char *link, int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
* 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);
+ (void) wpa_instance_create(linkid, keys);
start = gethrtime();
for (;;) {
- if (do_get_linkstatus(fd, gbuf) < 0)
+ status = do_get_linkstatus(linkid, gbuf);
+ if (status != DLADM_STATUS_OK)
goto fail;
if (IS_CONNECTED(gbuf))
@@ -598,38 +507,38 @@ do_connect(const char *link, int fd, wldp_t *gbuf, dladm_wlan_attr_t *attrp,
(void) poll(NULL, 0, DLADM_WLAN_CONNECT_POLLRATE);
if ((timeout >= 0) && (gethrtime() - start) /
- NANOSEC >= timeout)
- return (DLADM_STATUS_TIMEDOUT);
+ NANOSEC >= timeout) {
+ status = DLADM_STATUS_TIMEDOUT;
+ goto fail;
+ }
}
- return (DLADM_STATUS_OK);
+ status = DLADM_STATUS_OK;
fail:
- return (dladm_wlan_wlresult2status(gbuf));
+ return (status);
}
dladm_status_t
-dladm_wlan_connect(const char *link, dladm_wlan_attr_t *attrp,
+dladm_wlan_connect(datalink_id_t linkid, dladm_wlan_attr_t *attrp,
int timeout, void *keys, uint_t key_count, uint_t flags)
{
- int fd, i;
+ int i;
wldp_t *gbuf = NULL;
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 = DLADM_STATUS_FAILED;
+ dladm_status_t status;
- if ((fd = open_link(link)) < 0)
- return (DLADM_STATUS_LINKINVAL);
+ 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 (do_get_linkstatus(fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
- }
if (IS_CONNECTED(gbuf)) {
status = DLADM_STATUS_ISCONN;
@@ -646,8 +555,8 @@ 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(link, fd, gbuf, attrp,
- create_ibss, keys, key_count, timeout);
+ status = do_connect(linkid, gbuf, attrp, create_ibss, keys,
+ key_count, timeout);
goto done;
}
@@ -655,7 +564,7 @@ dladm_wlan_connect(const char *link, dladm_wlan_attr_t *attrp,
state.cs_list = NULL;
state.cs_count = 0;
- status = dladm_wlan_scan(link, &state, connect_cb);
+ status = dladm_wlan_scan(linkid, &state, connect_cb);
if (status != DLADM_STATUS_OK)
goto done;
@@ -664,8 +573,8 @@ dladm_wlan_connect(const char *link, dladm_wlan_attr_t *attrp,
status = DLADM_STATUS_NOTFOUND;
goto done;
}
- status = do_connect(link, fd, gbuf, attrp, create_ibss,
- keys, key_count, timeout);
+ status = do_connect(linkid, gbuf, attrp, create_ibss, keys,
+ key_count, timeout);
goto done;
}
@@ -686,7 +595,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(link, fd, gbuf, ap, create_ibss, keys,
+ status = do_connect(linkid, gbuf, ap, create_ibss, keys,
key_count, timeout);
if (status == DLADM_STATUS_OK)
break;
@@ -694,15 +603,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(link, fd, gbuf, ap, create_ibss,
- keys, key_count, timeout);
+ status = do_connect(linkid, 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(link, fd, gbuf);
+ (void) do_disconnect(linkid, gbuf);
while (state.cs_list != NULL) {
nodep = state.cs_list;
@@ -711,44 +620,36 @@ done:
}
free(gbuf);
free(wl_list);
- (void) close(fd);
return (status);
}
dladm_status_t
-dladm_wlan_disconnect(const char *link)
+dladm_wlan_disconnect(datalink_id_t linkid)
{
- int fd;
wldp_t *gbuf;
dladm_status_t status;
- if ((fd = open_link(link)) < 0)
- return (DLADM_STATUS_BADARG);
+ 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 (do_get_linkstatus(fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
- }
if (!IS_CONNECTED(gbuf)) {
status = DLADM_STATUS_NOTCONN;
goto done;
}
- if (do_disconnect(link, fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ if ((status = do_disconnect(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
- }
- if (do_get_linkstatus(fd, gbuf) < 0) {
- status = DLADM_STATUS_FAILED;
+ if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
- }
if (IS_CONNECTED(gbuf)) {
status = DLADM_STATUS_FAILED;
@@ -758,85 +659,12 @@ dladm_wlan_disconnect(const char *link)
status = DLADM_STATUS_OK;
done:
free(gbuf);
- (void) close(fd);
return (status);
}
-typedef struct dladm_wlan_linkname {
- char wl_name[MAXNAMELEN];
- struct dladm_wlan_linkname *wl_next;
-} dladm_wlan_linkname_t;
-
-typedef struct dladm_wlan_walk {
- dladm_wlan_linkname_t *ww_list;
- dladm_status_t ww_status;
-} dladm_wlan_walk_t;
-
-/* ARGSUSED */
-static int
-append_linkname(di_node_t node, di_minor_t minor, void *arg)
-{
- dladm_wlan_walk_t *statep = arg;
- dladm_wlan_linkname_t **lastp = &statep->ww_list;
- dladm_wlan_linkname_t *wlp = *lastp;
- char name[MAXNAMELEN];
-
- (void) snprintf(name, MAXNAMELEN, "%s%d",
- di_driver_name(node), di_instance(node));
-
- while (wlp != NULL) {
- if (strcmp(wlp->wl_name, name) == 0)
- return (DI_WALK_CONTINUE);
-
- lastp = &wlp->wl_next;
- wlp = wlp->wl_next;
- }
- if ((wlp = malloc(sizeof (*wlp))) == NULL) {
- statep->ww_status = DLADM_STATUS_NOMEM;
- return (DI_WALK_CONTINUE);
- }
-
- (void) strlcpy(wlp->wl_name, name, MAXNAMELEN);
- wlp->wl_next = NULL;
- *lastp = wlp;
-
- return (DI_WALK_CONTINUE);
-}
-
-dladm_status_t
-dladm_wlan_walk(void *arg, boolean_t (*func)(void *, const char *))
-{
- di_node_t root;
- dladm_wlan_walk_t state;
- dladm_wlan_linkname_t *wlp, *wlp_next;
- boolean_t cont = B_TRUE;
-
- if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
- return (DLADM_STATUS_FAILED);
-
- state.ww_list = NULL;
- state.ww_status = DLADM_STATUS_OK;
- (void) di_walk_minor(root, DDI_NT_NET_WIFI, DI_CHECK_ALIAS,
- &state, append_linkname);
- di_fini(root);
-
- for (wlp = state.ww_list; wlp != NULL; wlp = wlp_next) {
- /*
- * NOTE: even if (*func)() returns B_FALSE, the loop continues
- * since all memory must be freed.
- */
- if (cont)
- cont = (*func)(arg, wlp->wl_name);
- wlp_next = wlp->wl_next;
- free(wlp);
- }
- return (state.ww_status);
-}
-
dladm_status_t
-dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
+dladm_wlan_get_linkattr(datalink_id_t linkid, dladm_wlan_linkattr_t *attrp)
{
- int fd;
wldp_t *gbuf;
wl_rssi_t signal;
wl_bss_type_t bsstype;
@@ -844,13 +672,13 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
wl_encryption_t encryption;
wl_rates_t *ratesp;
dladm_wlan_attr_t *wl_attrp;
- dladm_status_t status = DLADM_STATUS_FAILED;
+ dladm_status_t status;
if (attrp == NULL)
return (DLADM_STATUS_BADARG);
- if ((fd = open_link(link)) < 0)
- return (DLADM_STATUS_LINKINVAL);
+ if ((status = dladm_wlan_validate(linkid)) != DLADM_STATUS_OK)
+ goto done;
if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
status = DLADM_STATUS_NOMEM;
@@ -860,17 +688,16 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
(void) memset(attrp, 0, sizeof (*attrp));
wl_attrp = &attrp->la_wlan_attr;
- if (do_get_linkstatus(fd, gbuf) < 0)
+ if ((status = do_get_linkstatus(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
attrp->la_valid |= DLADM_WLAN_LINKATTR_STATUS;
- if (!IS_CONNECTED(gbuf)) {
- attrp->la_status = DLADM_WLAN_LINKSTATUS_DISCONNECTED;
- } else {
- attrp->la_status = DLADM_WLAN_LINKSTATUS_CONNECTED;
- }
+ if (!IS_CONNECTED(gbuf))
+ attrp->la_status = DLADM_WLAN_LINK_DISCONNECTED;
+ else
+ attrp->la_status = DLADM_WLAN_LINK_CONNECTED;
- if (do_get_essid(fd, gbuf) < 0)
+ if ((status = do_get_essid(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
(void) strlcpy(wl_attrp->wa_essid.we_bytes,
@@ -879,7 +706,7 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
wl_attrp->wa_valid |= DLADM_WLAN_ATTR_ESSID;
- if (do_get_bssid(fd, gbuf) < 0)
+ if ((status = do_get_bssid(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
(void) memcpy(wl_attrp->wa_bssid.wb_bytes, gbuf->wldp_buf,
@@ -887,13 +714,13 @@ 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) {
+ if (attrp->la_status == DLADM_WLAN_LINK_DISCONNECTED) {
attrp->la_valid |= DLADM_WLAN_LINKATTR_WLAN;
status = DLADM_STATUS_OK;
goto done;
}
- if (do_get_encryption(fd, gbuf) < 0)
+ if ((status = do_get_encryption(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
encryption = *(wl_encryption_t *)(gbuf->wldp_buf);
@@ -914,14 +741,14 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
break;
}
- if (do_get_signal(fd, gbuf) < 0)
+ if ((status = do_get_signal(linkid, gbuf)) != 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 (do_get_rate(fd, gbuf) < 0)
+ if ((status = do_get_rate(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
ratesp = (wl_rates_t *)(gbuf->wldp_buf);
@@ -936,7 +763,7 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
wl_attrp->wa_valid |= DLADM_WLAN_ATTR_SPEED;
}
- if (do_get_authmode(fd, gbuf) < 0)
+ if ((status = do_get_authmode(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
authmode = *(wl_authmode_t *)(gbuf->wldp_buf);
@@ -954,7 +781,7 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
break;
}
- if (do_get_bsstype(fd, gbuf) < 0)
+ if ((status = do_get_bsstype(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
bsstype = *(wl_bss_type_t *)(gbuf->wldp_buf);
@@ -975,7 +802,7 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
break;
}
- if (do_get_mode(fd, gbuf) < 0)
+ if ((status = do_get_mode(linkid, gbuf)) != DLADM_STATUS_OK)
goto done;
wl_attrp->wa_mode = do_convert_mode((wl_phy_conf_t *)(gbuf->wldp_buf));
@@ -988,231 +815,30 @@ dladm_wlan_get_linkattr(const char *link, dladm_wlan_linkattr_t *attrp)
done:
free(gbuf);
- (void) close(fd);
return (status);
}
-boolean_t
-dladm_wlan_is_valid(const char *link)
-{
- int fd = open_link(link);
-
- if (fd < 0)
- return (B_FALSE);
-
- (void) close(fd);
- return (B_TRUE);
-}
-
-/* ARGSUSED */
-static dladm_status_t
-do_check_prop(int fd, wldp_t *guf, prop_desc_t *pdp, char **prop_val,
- uint_t val_cnt, val_desc_t **vdpp)
-{
- int i;
- val_desc_t *vdp;
-
- if (pdp->pd_nmodval == 0)
- return (DLADM_STATUS_PROPRDONLY);
-
- if (val_cnt != 1)
- return (DLADM_STATUS_BADVALCNT);
-
- for (i = 0; i < pdp->pd_nmodval; i++)
- if (strcasecmp(*prop_val, pdp->pd_modval[i].vd_name) == 0)
- break;
-
- if (i == pdp->pd_nmodval)
- return (DLADM_STATUS_BADVAL);
-
- vdp = malloc(sizeof (val_desc_t));
- if (vdp == NULL)
- return (DLADM_STATUS_NOMEM);
-
- (void) memcpy(vdp, &pdp->pd_modval[i], sizeof (val_desc_t));
- *vdpp = vdp;
- return (DLADM_STATUS_OK);
-}
-
static dladm_status_t
-do_set_prop(int fd, wldp_t *gbuf, prop_desc_t *pdp,
- char **prop_val, uint_t val_cnt)
+dladm_wlan_validate(datalink_id_t linkid)
{
+ wldp_t *gbuf;
dladm_status_t status;
- val_desc_t *vdp = NULL;
- uint_t cnt;
-
- if (pdp->pd_set == NULL)
- return (DLADM_STATUS_PROPRDONLY);
-
- if (prop_val != NULL) {
- status = pdp->pd_check(fd, gbuf, pdp, prop_val,
- val_cnt, &vdp);
-
- if (status != DLADM_STATUS_OK)
- return (status);
-
- cnt = val_cnt;
- } else {
- if (pdp->pd_defval.vd_name == NULL)
- return (DLADM_STATUS_NOTSUP);
-
- if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
- return (DLADM_STATUS_NOMEM);
-
- *vdp = pdp->pd_defval;
- cnt = 1;
- }
- status = pdp->pd_set(fd, gbuf, vdp, cnt);
- if (status == DLADM_STATUS_OK) {
- /*
- * Some ioctls return 0 but store error code in
- * wldp_result. Need to fix them.
- */
- if (gbuf->wldp_result != WL_SUCCESS)
- status = dladm_wlan_wlresult2status(gbuf);
- }
- free(vdp);
- return (status);
-}
-
-dladm_status_t
-dladm_wlan_set_prop(const char *link, const char *prop_name,
- char **prop_val, uint_t val_cnt, char **errprop)
-{
- int fd, i;
- wldp_t *gbuf = NULL;
- boolean_t found = B_FALSE;
- dladm_status_t status = DLADM_STATUS_OK;
-
- if ((prop_name == NULL && prop_val != NULL) ||
- (prop_val != NULL && val_cnt == 0))
- return (DLADM_STATUS_BADARG);
-
- if ((fd = open_link(link)) < 0)
- return (DLADM_STATUS_LINKINVAL);
if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
status = DLADM_STATUS_NOMEM;
goto done;
}
- for (i = 0; i < DLADM_WLAN_MAX_PROPS; i++) {
- prop_desc_t *pdp = &prop_table[i];
- dladm_status_t s;
-
- if (prop_name != NULL &&
- (strcasecmp(prop_name, pdp->pd_name) != 0))
- continue;
-
- found = B_TRUE;
- s = do_set_prop(fd, gbuf, pdp, prop_val, val_cnt);
-
- if (prop_name != NULL) {
- status = s;
- break;
- } else {
- if (s != DLADM_STATUS_OK &&
- s != DLADM_STATUS_NOTSUP) {
- if (errprop != NULL)
- *errprop = pdp->pd_name;
- status = s;
- break;
- }
- }
- }
- if (!found)
- status = DLADM_STATUS_NOTFOUND;
-done:
- free(gbuf);
- (void) close(fd);
- return (status);
-}
-
-/* ARGSUSED */
-dladm_status_t
-dladm_wlan_walk_prop(const char *link, void *arg,
- boolean_t (*func)(void *, const char *))
-{
- int i;
-
- for (i = 0; i < DLADM_WLAN_MAX_PROPS; i++) {
- if (!func(arg, prop_table[i].pd_name))
- break;
- }
- return (DLADM_STATUS_OK);
-}
-
-dladm_status_t
-dladm_wlan_get_prop(const char *link, dladm_prop_type_t type,
- const char *prop_name, char **prop_val, uint_t *val_cnt)
-{
- int fd;
- int i;
- wldp_t *gbuf;
- dladm_status_t status;
- uint_t cnt;
- prop_desc_t *pdp;
-
- if (prop_val == NULL || val_cnt == NULL || *val_cnt == 0)
- return (DLADM_STATUS_BADARG);
-
- for (i = 0; i < DLADM_WLAN_MAX_PROPS; i++)
- if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
- break;
-
- if (i == DLADM_WLAN_MAX_PROPS)
- return (DLADM_STATUS_NOTFOUND);
-
- if ((fd = open_link(link)) < 0)
- return (DLADM_STATUS_LINKINVAL);
-
- if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
- status = DLADM_STATUS_NOMEM;
+ /*
+ * Check to see if the link is wireless.
+ */
+ if ((status = do_get_bsstype(linkid, gbuf)) != DLADM_STATUS_OK) {
+ status = DLADM_STATUS_LINKINVAL;
goto done;
}
- pdp = &prop_table[i];
- status = DLADM_STATUS_OK;
- switch (type) {
- case DLADM_PROP_VAL_CURRENT:
- status = pdp->pd_get(fd, gbuf, prop_val, val_cnt);
- break;
-
- case DLADM_PROP_VAL_DEFAULT:
- if (pdp->pd_defval.vd_name == NULL) {
- status = DLADM_STATUS_NOTSUP;
- break;
- }
- (void) strcpy(*prop_val, pdp->pd_defval.vd_name);
- *val_cnt = 1;
- break;
-
- case DLADM_PROP_VAL_MODIFIABLE:
- if (pdp->pd_getmod != NULL) {
- status = pdp->pd_getmod(fd, gbuf, prop_val, val_cnt);
- break;
- }
- cnt = pdp->pd_nmodval;
- if (cnt == 0) {
- status = DLADM_STATUS_NOTSUP;
- } else if (cnt > *val_cnt) {
- status = DLADM_STATUS_TOOSMALL;
- } else {
- for (i = 0; i < cnt; i++) {
- (void) strcpy(prop_val[i],
- pdp->pd_modval[i].vd_name);
- }
- *val_cnt = cnt;
- }
- break;
- default:
- status = DLADM_STATUS_BADARG;
- break;
- }
done:
free(gbuf);
- (void) close(fd);
return (status);
}
@@ -1422,19 +1048,45 @@ dladm_wlan_str2linkstatus(const char *str, dladm_wlan_linkstatus_t *linkstatus)
{
uint_t val;
- if (!find_val_by_name(str, linkstatus_vals, VALCNT(linkstatus_vals),
- &val))
+ if (!find_val_by_name(str, linkstatus_vals,
+ VALCNT(linkstatus_vals), &val)) {
return (DLADM_STATUS_BADARG);
+ }
*linkstatus = (dladm_wlan_linkstatus_t)val;
return (DLADM_STATUS_OK);
}
-static int
-do_ioctl(int fd, wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen)
+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)
{
- int rc;
+ char linkname[MAXPATHLEN];
+ int fd, rc;
struct strioctl stri;
+ uint32_t flags;
+ dladm_status_t status;
+ uint32_t media;
+ char link[MAXLINKNAMELEN];
+
+ if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media,
+ link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
+ return (status);
+ }
+
+ if (media != DL_WIFI)
+ return (DLADM_STATUS_BADARG);
+
+ if (!(flags & DLADM_OPT_ACTIVE))
+ return (DLADM_STATUS_TEMPONLY);
+
+ /*
+ * dlpi_open() is not used here because libdlpi depends on libdladm,
+ * and we do not want to introduce recursive dependencies.
+ */
+ (void) snprintf(linkname, MAXPATHLEN, "/dev/net/%s", link);
+ if ((fd = open(linkname, O_RDWR)) < 0)
+ return (DLADM_STATUS_LINKINVAL);
gbuf->wldp_type = NET_802_11;
gbuf->wldp_id = id;
@@ -1446,250 +1098,140 @@ do_ioctl(int fd, wldp_t *gbuf, uint_t id, size_t len, uint_t cmd, size_t cmdlen)
stri.ic_len = cmdlen;
if ((rc = ioctl(fd, I_STR, &stri)) != 0) {
- if (rc > 0)
- errno = rc;
- return (-1);
+ if (rc > 0) {
+ /*
+ * Non-negative return value indicates the specific
+ * operation failed and the reason for the failure
+ * was stored in gbuf->wldp_result.
+ */
+ status = dladm_wlan_wlresult2status(gbuf);
+ } else {
+ /*
+ * Negative return value indicates the ioctl failed.
+ */
+ status = dladm_errno2status(errno);
+ }
}
- return (0);
+ (void) close(fd);
+ return (status);
}
-static int
-do_get_ioctl(int fd, wldp_t *gbuf, uint_t id)
+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 (do_ioctl(fd, gbuf, id, MAX_BUF_LEN, WLAN_GET_PARAM,
- MAX_BUF_LEN));
+ return (i_dladm_wlan_ioctl(linkid, gbuf, id, MAX_BUF_LEN,
+ WLAN_GET_PARAM, MAX_BUF_LEN));
}
-static int
-do_set_ioctl(int fd, wldp_t *gbuf, uint_t id, void *buf, uint_t buflen)
+dladm_status_t
+i_dladm_wlan_set_ioctl(datalink_id_t linkid, uint_t id, void *buf,
+ uint_t buflen)
{
+ 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;
- return (do_ioctl(fd, gbuf, id, buflen, WLAN_SET_PARAM, buflen));
+ status = i_dladm_wlan_ioctl(linkid, gbuf, id, buflen,
+ WLAN_SET_PARAM, buflen);
+
+ free(gbuf);
+ return (status);
}
-static int
-do_cmd_ioctl(int fd, wldp_t *gbuf, uint_t cmd)
+static dladm_status_t
+do_cmd_ioctl(datalink_id_t linkid, wldp_t *gbuf, uint_t cmd)
{
(void) memset(gbuf, 0, MAX_BUF_LEN);
- return (do_ioctl(fd, gbuf, cmd, sizeof (wldp_t), WLAN_COMMAND,
- sizeof (wldp_t)));
+ return (i_dladm_wlan_ioctl(linkid, gbuf, cmd, sizeof (wldp_t),
+ WLAN_COMMAND, sizeof (wldp_t)));
}
-static int
-do_scan(int fd, wldp_t *gbuf)
+static dladm_status_t
+do_scan(datalink_id_t linkid, wldp_t *gbuf)
{
- return (do_cmd_ioctl(fd, gbuf, WL_SCAN));
+ return (do_cmd_ioctl(linkid, gbuf, WL_SCAN));
}
-static int
-do_disconnect(const char *link, int fd, wldp_t *gbuf)
+static dladm_status_t
+do_disconnect(datalink_id_t linkid, wldp_t *gbuf)
{
- if (do_get_wpamode(fd, gbuf) == 0 && ((wl_wpa_t *)(gbuf->
- wldp_buf))->wpa_flag > 0)
- (void) wpa_instance_delete(link);
+ if (do_get_wpamode(linkid, gbuf) == 0 &&
+ ((wl_wpa_t *)(gbuf->wldp_buf))->wpa_flag > 0)
+ (void) wpa_instance_delete(linkid);
- return (do_cmd_ioctl(fd, gbuf, WL_DISASSOCIATE));
+ return (do_cmd_ioctl(linkid, gbuf, WL_DISASSOCIATE));
}
-static int
-do_get_esslist(int fd, wldp_t *gbuf)
+static dladm_status_t
+do_get_esslist(datalink_id_t linkid, wldp_t *gbuf)
{
(void) memset(gbuf, 0, MAX_BUF_LEN);
- return (do_ioctl(fd, gbuf, WL_ESS_LIST, MAX_BUF_LEN,
+ return (i_dladm_wlan_ioctl(linkid, gbuf, WL_ESS_LIST, MAX_BUF_LEN,
WLAN_GET_PARAM, sizeof (wldp_t)));
}
-static int
-do_get_bssid(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_BSSID));
-}
-
-static int
-do_get_essid(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_ESSID));
-}
-
-static int
-do_get_bsstype(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_BSS_TYPE));
-}
-
-static int
-do_get_linkstatus(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_LINKSTATUS));
-}
-
-static int
-do_get_rate(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_DESIRED_RATES));
-}
-
-static int
-do_get_phyconf(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_PHY_CONFIG));
-}
-
-static int
-do_get_powermode(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_POWER_MODE));
-}
-
-static int
-do_get_radio(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_RADIO));
-}
-
-static int
-do_get_authmode(int fd, wldp_t *gbuf)
-{
- return (do_get_ioctl(fd, gbuf, WL_AUTH_MODE));
-}
-
-static int
-do_get_encryption(int fd, wldp_t *gbuf)
+static dladm_status_t
+do_get_bssid(datalink_id_t linkid, wldp_t *gbuf)
{
- return (do_get_ioctl(fd, gbuf, WL_ENCRYPTION));
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSSID));
}
-static int
-do_get_signal(int fd, wldp_t *gbuf)
+static dladm_status_t
+do_get_essid(datalink_id_t linkid, wldp_t *gbuf)
{
- return (do_get_ioctl(fd, gbuf, WL_RSSI));
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ESSID));
}
-static int
-do_get_mode(int fd, wldp_t *gbuf)
+static dladm_status_t
+do_get_bsstype(datalink_id_t linkid, wldp_t *gbuf)
{
- return (do_get_ioctl(fd, gbuf, WL_PHY_CONFIG));
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_BSS_TYPE));
}
static dladm_status_t
-do_get_rate_common(wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+do_get_linkstatus(datalink_id_t linkid, wldp_t *gbuf)
{
- wl_rates_t *wrp = (wl_rates_t *)gbuf->wldp_buf;
- uint_t cnt = wrp->wl_rates_num;
- uint_t i;
-
- if (cnt > *val_cnt)
- return (DLADM_STATUS_TOOSMALL);
- if (wrp->wl_rates_rates[0] == 0) {
- prop_val[0][0] = '\0';
- *val_cnt = 1;
- return (DLADM_STATUS_OK);
- }
-
- for (i = 0; i < cnt; i++) {
- (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
- wrp->wl_rates_rates[i] % 2,
- (float)wrp->wl_rates_rates[i] / 2);
- }
- *val_cnt = cnt;
- return (DLADM_STATUS_OK);
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_LINKSTATUS));
}
static dladm_status_t
-do_get_rate_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+do_get_rate(datalink_id_t linkid, wldp_t *gbuf)
{
- if (do_get_rate(fd, gbuf) < 0)
- return (dladm_wlan_wlresult2status(gbuf));
-
- return (do_get_rate_common(gbuf, prop_val, val_cnt));
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_DESIRED_RATES));
}
static dladm_status_t
-do_get_rate_mod(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+do_get_authmode(datalink_id_t linkid, wldp_t *gbuf)
{
- if (do_get_ioctl(fd, gbuf, WL_SUPPORTED_RATES) < 0)
- return (DLADM_STATUS_FAILED);
-
- return (do_get_rate_common(gbuf, prop_val, val_cnt));
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_AUTH_MODE));
}
static dladm_status_t
-do_get_channel_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+do_get_encryption(datalink_id_t linkid, wldp_t *gbuf)
{
- uint32_t channel;
-
- if (do_get_phyconf(fd, gbuf) < 0)
- return (dladm_wlan_wlresult2status(gbuf));
-
- if (!do_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf, &channel))
- return (DLADM_STATUS_NOTFOUND);
-
- (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
- *val_cnt = 1;
-
- return (DLADM_STATUS_OK);
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_ENCRYPTION));
}
static dladm_status_t
-do_get_powermode_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+do_get_signal(datalink_id_t linkid, wldp_t *gbuf)
{
- wl_ps_mode_t *mode;
- const char *s;
-
- if (do_get_powermode(fd, gbuf) < 0)
- return (dladm_wlan_wlresult2status(gbuf));
-
- mode = (wl_ps_mode_t *)(gbuf->wldp_buf);
- switch (mode->wl_ps_mode) {
- case WL_PM_AM:
- s = "off";
- break;
- case WL_PM_MPS:
- s = "max";
- break;
- case WL_PM_FAST:
- s = "fast";
- break;
- default:
- return (DLADM_STATUS_NOTFOUND);
- }
- (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
- *val_cnt = 1;
-
- return (DLADM_STATUS_OK);
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RSSI));
}
static dladm_status_t
-do_get_radio_prop(int fd, wldp_t *gbuf, char **prop_val, uint_t *val_cnt)
+do_get_mode(datalink_id_t linkid, wldp_t *gbuf)
{
- wl_radio_t radio;
- const char *s;
-
- if (do_get_radio(fd, gbuf) < 0)
- return (dladm_wlan_wlresult2status(gbuf));
-
- radio = *(wl_radio_t *)(gbuf->wldp_buf);
- switch (radio) {
- case B_TRUE:
- s = "on";
- break;
- case B_FALSE:
- s = "off";
- break;
- default:
- return (DLADM_STATUS_NOTFOUND);
- }
- (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
- *val_cnt = 1;
-
- return (DLADM_STATUS_OK);
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG));
}
-static int
-do_set_bsstype(int fd, wldp_t *gbuf, dladm_wlan_bsstype_t *bsstype)
+static dladm_status_t
+do_set_bsstype(datalink_id_t linkid, dladm_wlan_bsstype_t *bsstype)
{
wl_bss_type_t ibsstype;
@@ -1704,12 +1246,12 @@ do_set_bsstype(int fd, wldp_t *gbuf, dladm_wlan_bsstype_t *bsstype)
ibsstype = WL_BSS_ANY;
break;
}
- return (do_set_ioctl(fd, gbuf, WL_BSS_TYPE, &ibsstype,
+ return (i_dladm_wlan_set_ioctl(linkid, WL_BSS_TYPE, &ibsstype,
sizeof (ibsstype)));
}
-static int
-do_set_authmode(int fd, wldp_t *gbuf, dladm_wlan_auth_t *auth)
+static dladm_status_t
+do_set_authmode(datalink_id_t linkid, dladm_wlan_auth_t *auth)
{
wl_authmode_t auth_mode;
@@ -1721,14 +1263,14 @@ do_set_authmode(int fd, wldp_t *gbuf, dladm_wlan_auth_t *auth)
auth_mode = WL_SHAREDKEY;
break;
default:
- return (-1);
+ return (DLADM_STATUS_NOTSUP);
}
- return (do_set_ioctl(fd, gbuf, WL_AUTH_MODE, &auth_mode,
+ return (i_dladm_wlan_set_ioctl(linkid, WL_AUTH_MODE, &auth_mode,
sizeof (auth_mode)));
}
-static int
-do_set_encryption(int fd, wldp_t *gbuf, dladm_wlan_secmode_t *secmode)
+static dladm_status_t
+do_set_encryption(datalink_id_t linkid, dladm_wlan_secmode_t *secmode)
{
wl_encryption_t encryption;
@@ -1742,14 +1284,14 @@ do_set_encryption(int fd, wldp_t *gbuf, dladm_wlan_secmode_t *secmode)
case DLADM_WLAN_SECMODE_WPA:
return (0);
default:
- return (-1);
+ return (DLADM_STATUS_NOTSUP);
}
- return (do_set_ioctl(fd, gbuf, WL_ENCRYPTION, &encryption,
+ return (i_dladm_wlan_set_ioctl(linkid, WL_ENCRYPTION, &encryption,
sizeof (encryption)));
}
-static int
-do_set_key(int fd, wldp_t *gbuf, dladm_wlan_key_t *keys,
+static dladm_status_t
+do_set_key(datalink_id_t linkid, dladm_wlan_key_t *keys,
uint_t key_count)
{
int i;
@@ -1758,7 +1300,7 @@ do_set_key(int fd, wldp_t *gbuf, dladm_wlan_key_t *keys,
dladm_wlan_key_t *kp;
if (key_count == 0 || key_count > MAX_NWEPKEYS || keys == NULL)
- return (-1);
+ return (DLADM_STATUS_BADARG);
(void) memset(wepkey_tab, 0, sizeof (wepkey_tab));
for (i = 0; i < MAX_NWEPKEYS; i++)
@@ -1767,10 +1309,10 @@ do_set_key(int fd, wldp_t *gbuf, dladm_wlan_key_t *keys,
for (i = 0; i < key_count; i++) {
kp = &keys[i];
if (kp->wk_idx == 0 || kp->wk_idx > MAX_NWEPKEYS)
- return (-1);
+ return (DLADM_STATUS_BADARG);
if (kp->wk_len != DLADM_WLAN_WEPKEY64_LEN &&
kp->wk_len != DLADM_WLAN_WEPKEY128_LEN)
- return (-1);
+ return (DLADM_STATUS_BADARG);
wkp = &wepkey_tab[kp->wk_idx - 1];
wkp->wl_wep_operation = WL_ADD;
@@ -1778,12 +1320,12 @@ do_set_key(int fd, wldp_t *gbuf, dladm_wlan_key_t *keys,
(void) memcpy(wkp->wl_wep_key, kp->wk_val, kp->wk_len);
}
- return (do_set_ioctl(fd, gbuf, WL_WEP_KEY_TAB, &wepkey_tab,
+ return (i_dladm_wlan_set_ioctl(linkid, WL_WEP_KEY_TAB, &wepkey_tab,
sizeof (wepkey_tab)));
}
-static int
-do_set_essid(int fd, wldp_t *gbuf, dladm_wlan_essid_t *essid)
+static dladm_status_t
+do_set_essid(datalink_id_t linkid, dladm_wlan_essid_t *essid)
{
wl_essid_t iessid;
@@ -1794,186 +1336,34 @@ do_set_essid(int fd, wldp_t *gbuf, dladm_wlan_essid_t *essid)
(void) strlcpy(iessid.wl_essid_essid, essid->we_bytes,
sizeof (iessid.wl_essid_essid));
} else {
- return (-1);
- }
- return (do_set_ioctl(fd, gbuf, WL_ESSID, &iessid, sizeof (iessid)));
-}
-
-/* ARGSUSED */
-static dladm_status_t
-do_check_rate(int fd, wldp_t *gbuf, prop_desc_t *pdp, char **prop_val,
- uint_t val_cnt, val_desc_t **vdpp)
-{
- int i;
- uint_t modval_cnt = MAX_SUPPORT_RATES;
- char *buf, **modval;
- dladm_status_t status;
- val_desc_t *vdp = NULL;
-
- if (val_cnt != 1)
- return (DLADM_STATUS_BADVALCNT);
-
- buf = malloc((sizeof (char *) + DLADM_STRSIZE) * MAX_SUPPORT_RATES);
- if (buf == NULL) {
- status = DLADM_STATUS_NOMEM;
- goto done;
- }
-
- modval = (char **)(void *)buf;
- for (i = 0; i < MAX_SUPPORT_RATES; i++) {
- modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
- i * DLADM_STRSIZE;
- }
-
- status = do_get_rate_mod(fd, gbuf, modval, &modval_cnt);
- if (status != DLADM_STATUS_OK)
- goto done;
-
- vdp = malloc(sizeof (val_desc_t));
- if (vdp == NULL) {
- status = DLADM_STATUS_NOMEM;
- goto done;
- }
-
- for (i = 0; i < modval_cnt; i++) {
- if (strcasecmp(*prop_val, modval[i]) == 0) {
- vdp->vd_val = (uint_t)(atof(*prop_val) * 2);
- status = DLADM_STATUS_OK;
- *vdpp = vdp;
- vdp = NULL;
- break;
- }
- }
- if (i == modval_cnt)
- status = DLADM_STATUS_BADVAL;
-done:
- free(buf);
- free(vdp);
- return (status);
-}
-
-static dladm_status_t
-do_set_rate_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
-{
- dladm_wlan_rates_t rates;
-
- if (val_cnt != 1)
- return (DLADM_STATUS_BADVALCNT);
-
- rates.wr_cnt = 1;
- rates.wr_rates[0] = vdp[0].vd_val;
-
- if (do_set_rate(fd, gbuf, &rates) < 0)
- return (dladm_wlan_wlresult2status(gbuf));
-
- return (DLADM_STATUS_OK);
-}
-
-static int
-do_set_rate(int fd, wldp_t *gbuf, dladm_wlan_rates_t *rates)
-{
- int i;
- uint_t len;
- wl_rates_t *wrp = (wl_rates_t *)gbuf->wldp_buf;
-
- (void) memset(gbuf, 0, MAX_BUF_LEN);
-
- 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;
- return (do_ioctl(fd, gbuf, WL_DESIRED_RATES, len, WLAN_SET_PARAM, len));
-}
-
-/* ARGSUSED */
-static dladm_status_t
-do_set_powermode_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
-{
- dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
-
- if (do_set_powermode(fd, gbuf, &powermode) < 0)
- return (dladm_wlan_wlresult2status(gbuf));
-
- return (DLADM_STATUS_OK);
-}
-
-static int
-do_set_powermode(int fd, wldp_t *gbuf, dladm_wlan_powermode_t *pm)
-{
- wl_ps_mode_t ps_mode;
-
- (void) memset(&ps_mode, 0xff, sizeof (ps_mode));
-
- switch (*pm) {
- case DLADM_WLAN_PM_OFF:
- ps_mode.wl_ps_mode = WL_PM_AM;
- break;
- case DLADM_WLAN_PM_MAX:
- ps_mode.wl_ps_mode = WL_PM_MPS;
- break;
- case DLADM_WLAN_PM_FAST:
- ps_mode.wl_ps_mode = WL_PM_FAST;
- break;
- default:
- return (-1);
+ return (DLADM_STATUS_BADARG);
}
- return (do_set_ioctl(fd, gbuf, WL_POWER_MODE, &ps_mode,
- sizeof (ps_mode)));
+ return (i_dladm_wlan_set_ioctl(linkid, WL_ESSID, &iessid,
+ sizeof (iessid)));
}
-/* ARGSUSED */
static dladm_status_t
-do_set_radio_prop(int fd, wldp_t *gbuf, val_desc_t *vdp, uint_t val_cnt)
-{
- dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
-
- if (do_set_radio(fd, gbuf, &radio) < 0)
- return (dladm_wlan_wlresult2status(gbuf));
-
- return (DLADM_STATUS_OK);
-}
-
-static int
-do_set_radio(int fd, wldp_t *gbuf, dladm_wlan_radio_t *radio)
-{
- wl_radio_t r;
-
- switch (*radio) {
- case DLADM_WLAN_RADIO_ON:
- r = B_TRUE;
- break;
- case DLADM_WLAN_RADIO_OFF:
- r = B_FALSE;
- break;
- default:
- return (-1);
- }
- return (do_set_ioctl(fd, gbuf, WL_RADIO, &r, sizeof (r)));
-}
-
-static int
-do_set_channel(int fd, wldp_t *gbuf, dladm_wlan_channel_t *channel)
+do_set_channel(datalink_id_t linkid, dladm_wlan_channel_t *channel)
{
wl_phy_conf_t phy_conf;
if (*channel > MAX_CHANNEL_NUM)
- return (-1);
+ return (DLADM_STATUS_BADVAL);
(void) memset(&phy_conf, 0xff, sizeof (phy_conf));
phy_conf.wl_phy_dsss_conf.wl_dsss_channel = *channel;
- return (do_set_ioctl(fd, gbuf, WL_PHY_CONFIG, &phy_conf,
+ return (i_dladm_wlan_set_ioctl(linkid, WL_PHY_CONFIG, &phy_conf,
sizeof (phy_conf)));
}
-static int
-do_set_createibss(int fd, wldp_t *gbuf, boolean_t *create_ibss)
+static dladm_status_t
+do_set_createibss(datalink_id_t linkid, boolean_t *create_ibss)
{
wl_create_ibss_t cr = (wl_create_ibss_t)(*create_ibss);
- return (do_set_ioctl(fd, gbuf, WL_CREATE_IBSS, &cr, sizeof (cr)));
+ return (i_dladm_wlan_set_ioctl(linkid, WL_CREATE_IBSS,
+ &cr, sizeof (cr)));
}
static void
@@ -1984,55 +1374,21 @@ generate_essid(dladm_wlan_essid_t *essid)
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)
+do_get_capability(datalink_id_t linkid, wldp_t *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));
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_CAPABILITY));
}
static dladm_status_t
-ioctl_set(const char *link, int id, void *buf, uint_t buflen)
+do_get_wpamode(datalink_id_t linkid, wldp_t *gbuf)
{
- 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);
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_WPA));
}
dladm_status_t
-dladm_wlan_wpa_get_sr(const char *link, dladm_wlan_ess_t *sr, uint_t escnt,
- uint_t *estot)
+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;
@@ -2042,7 +1398,7 @@ dladm_wlan_wpa_get_sr(const char *link, dladm_wlan_ess_t *sr, uint_t escnt,
if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
return (DLADM_STATUS_NOMEM);
- status = ioctl_get(link, WL_SCANRESULTS, gbuf);
+ status = i_dladm_wlan_get_ioctl(linkid, gbuf, WL_SCANRESULTS);
if (status == DLADM_STATUS_OK) {
es = (wl_wpa_ess_t *)(gbuf->wldp_buf);
@@ -2066,8 +1422,7 @@ dladm_wlan_wpa_get_sr(const char *link, dladm_wlan_ess_t *sr, uint_t escnt,
}
dladm_status_t
-dladm_wlan_wpa_set_ie(const char *link, uint8_t *wpa_ie,
- uint_t wpa_ie_len)
+dladm_wlan_wpa_set_ie(datalink_id_t linkid, uint8_t *wpa_ie, uint_t wpa_ie_len)
{
wl_wpa_ie_t *ie;
uint_t len;
@@ -2084,41 +1439,43 @@ dladm_wlan_wpa_set_ie(const char *link, uint8_t *wpa_ie,
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);
+ status = i_dladm_wlan_set_ioctl(linkid, WL_SETOPTIE, ie, len);
free(ie);
return (status);
}
dladm_status_t
-dladm_wlan_wpa_set_wpa(const char *link, boolean_t flag)
+dladm_wlan_wpa_set_wpa(datalink_id_t linkid, boolean_t flag)
{
- wl_wpa_t wpa;
+ wl_wpa_t wpa;
wpa.wpa_flag = flag;
- return (ioctl_set(link, WL_WPA, &wpa, sizeof (wl_wpa_t)));
+ return (i_dladm_wlan_set_ioctl(linkid, WL_WPA, &wpa,
+ sizeof (wl_wpa_t)));
}
dladm_status_t
-dladm_wlan_wpa_del_key(const char *link, uint_t key_idx,
+dladm_wlan_wpa_del_key(datalink_id_t linkid, uint_t key_idx,
const dladm_wlan_bssid_t *addr)
{
- wl_del_key_t wk;
+ 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)));
+ return (i_dladm_wlan_set_ioctl(linkid, WL_DELKEY, &wk,
+ sizeof (wl_del_key_t)));
}
dladm_status_t
-dladm_wlan_wpa_set_key(const char *link, dladm_wlan_cipher_t cipher,
+dladm_wlan_wpa_set_key(datalink_id_t linkid, dladm_wlan_cipher_t cipher,
const dladm_wlan_bssid_t *addr, boolean_t set_tx, uint64_t seq,
uint_t key_idx, uint8_t *key, uint_t key_len)
{
- wl_key_t wk;
+ wl_key_t wk;
(void) memset(&wk, 0, sizeof (wl_key_t));
switch (cipher) {
@@ -2155,11 +1512,11 @@ dladm_wlan_wpa_set_key(const char *link, 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 (ioctl_set(link, WL_KEY, &wk, sizeof (wl_key_t)));
+ return (i_dladm_wlan_set_ioctl(linkid, 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_wpa_set_mlme(datalink_id_t linkid, dladm_wlan_mlme_op_t op,
dladm_wlan_reason_t reason, dladm_wlan_bssid_t *bssid)
{
wl_mlme_t mlme;
@@ -2180,7 +1537,8 @@ dladm_wlan_wpa_set_mlme(const char *link, dladm_wlan_mlme_op_t op,
(void) memcpy(mlme.im_macaddr, bssid->wb_bytes,
DLADM_WLAN_BSSID_LEN);
- return (ioctl_set(link, WL_MLME, &mlme, sizeof (wl_mlme_t)));
+ return (i_dladm_wlan_set_ioctl(linkid, WL_MLME, &mlme,
+ sizeof (wl_mlme_t)));
}
/*
@@ -2204,7 +1562,7 @@ add_property_group_to_instance(scf_handle_t *handle, scf_instance_t *instance,
return (pg);
}
-static int
+static dladm_status_t
add_new_property(scf_handle_t *handle, const char *prop_name,
scf_type_t type, const char *val, scf_transaction_t *tx)
{
@@ -2228,7 +1586,7 @@ add_new_property(scf_handle_t *handle, const char *prop_name,
if (scf_entry_add_value(entry, value) != 0)
goto out;
- return (DLADM_WLAN_SVC_SUCCESS);
+ return (DLADM_STATUS_OK);
out:
if (value != NULL)
@@ -2236,18 +1594,15 @@ out:
if (entry != NULL)
scf_entry_destroy(entry);
- return (DLADM_WLAN_SVC_FAILURE);
+ return (DLADM_STATUS_FAILED);
}
-/*
- * DLADM_WLAN_SVC_APP_FAILURE means allocate buffer failed.
- */
-static int
+static dladm_status_t
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;
+ dladm_status_t status = DLADM_STATUS_FAILED;
char *command = NULL;
scf_transaction_t *tran = NULL;
scf_propertygroup_t *pg;
@@ -2264,7 +1619,7 @@ add_pg_method(scf_handle_t *handle, scf_instance_t *instance,
size = strlen(SVC_METHOD) + strlen(" ") + strlen(flags) + 1;
command = malloc(size);
if (command == NULL) {
- status = DLADM_WLAN_SVC_APP_FAILURE;
+ status = DLADM_STATUS_NOMEM;
goto out;
}
(void) snprintf(command, size, "%s %s", SVC_METHOD, flags);
@@ -2274,15 +1629,14 @@ add_pg_method(scf_handle_t *handle, scf_instance_t *instance,
goto out;
if (add_new_property(handle, SCF_PROPERTY_EXEC,
- SCF_TYPE_ASTRING, command, tran) !=
- DLADM_WLAN_SVC_SUCCESS) {
+ SCF_TYPE_ASTRING, command, tran) != DLADM_STATUS_OK) {
goto out;
}
rv = scf_transaction_commit(tran);
switch (rv) {
case 1:
- status = DLADM_WLAN_SVC_SUCCESS;
+ status = DLADM_STATUS_OK;
goto out;
case 0:
scf_transaction_destroy_children(tran);
@@ -2311,11 +1665,11 @@ out:
return (status);
}
-static int
+static dladm_status_t
do_create_instance(scf_handle_t *handle, scf_service_t *svc,
const char *instance_name, const char *command)
{
- int status = DLADM_WLAN_SVC_FAILURE;
+ dladm_status_t status = DLADM_STATUS_FAILED;
char *buf;
ssize_t max_fmri_len;
scf_instance_t *instance;
@@ -2327,12 +1681,12 @@ do_create_instance(scf_handle_t *handle, scf_service_t *svc,
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;
+ status = DLADM_STATUS_EXIST;
goto out;
}
if (add_pg_method(handle, instance, "start",
- command) != DLADM_WLAN_SVC_SUCCESS) {
+ command) != DLADM_STATUS_OK) {
goto out;
}
@@ -2346,7 +1700,7 @@ do_create_instance(scf_handle_t *handle, scf_service_t *svc,
(smf_enable_instance(buf, SMF_TEMPORARY) != 0)) {
goto out;
}
- status = DLADM_WLAN_SVC_SUCCESS;
+ status = DLADM_STATUS_OK;
}
out:
@@ -2355,10 +1709,10 @@ out:
return (status);
}
-static int
+static dladm_status_t
create_instance(const char *instance_name, const char *command)
{
- int status = DLADM_WLAN_SVC_FAILURE;
+ dladm_status_t status = DLADM_STATUS_FAILED;
scf_service_t *svc = NULL;
scf_handle_t *handle = NULL;
@@ -2430,10 +1784,10 @@ wait_until_disabled(scf_handle_t *handle, char *fmri)
}
}
-static int
+static dladm_status_t
delete_instance(const char *instance_name)
{
- int status = DLADM_WLAN_SVC_FAILURE;
+ dladm_status_t status = DLADM_STATUS_FAILED;
char *buf;
ssize_t max_fmri_len;
scf_scope_t *scope = NULL;
@@ -2468,7 +1822,7 @@ delete_instance(const char *instance_name)
scf_error_t scf_errnum = scf_error();
if (scf_errnum == SCF_ERROR_NOT_FOUND)
- status = DLADM_WLAN_SVC_SUCCESS;
+ status = DLADM_STATUS_OK;
scf_instance_destroy(instance);
goto out;
@@ -2503,7 +1857,7 @@ delete_instance(const char *instance_name)
scf_instance_destroy(instance);
- status = DLADM_WLAN_SVC_SUCCESS;
+ status = DLADM_STATUS_OK;
out:
if (svc != NULL)
@@ -2520,33 +1874,39 @@ out:
return (status);
}
-/*
- * DLADM_WLAN_SVC_APP_FAILURE means allocate buffer failed.
- */
-static int
-wpa_instance_create(const char *instance_name, void *key)
+static dladm_status_t
+wpa_instance_create(datalink_id_t linkid, void *key)
{
- int status = DLADM_WLAN_SVC_FAILURE;
+ dladm_status_t status = DLADM_STATUS_FAILED;
char *command = NULL;
char *wk_name = ((dladm_wlan_key_t *)key)->wk_name;
int size;
+ char instance_name[MAXLINKNAMELEN];
+
+ /*
+ * Use the link name as the instance name of the network/wpad service.
+ */
+ status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name,
+ sizeof (instance_name));
+ if (status != DLADM_STATUS_OK)
+ goto out;
size = strlen(instance_name) + strlen(" -i -k ") + strlen(wk_name) + 1;
command = malloc(size);
if (command == NULL) {
- status = DLADM_WLAN_SVC_APP_FAILURE;
+ status = DLADM_STATUS_NOMEM;
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) {
+ if (status == DLADM_STATUS_EXIST) {
/*
* Delete the existing instance and create a new instance
* with the supplied arguments.
*/
if ((status = delete_instance(instance_name)) ==
- DLADM_WLAN_SVC_SUCCESS) {
+ DLADM_STATUS_OK) {
status = create_instance(instance_name, command);
}
}
@@ -2558,12 +1918,18 @@ out:
return (status);
}
-static int
-wpa_instance_delete(const char *instance_name)
+static dladm_status_t
+wpa_instance_delete(datalink_id_t linkid)
{
- int status;
+ char instance_name[MAXLINKNAMELEN];
- status = delete_instance(instance_name);
+ /*
+ * Get the instance name of the network/wpad service (the same as
+ * the link name).
+ */
+ if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, instance_name,
+ sizeof (instance_name)) != DLADM_STATUS_OK)
+ return (DLADM_STATUS_FAILED);
- return (status);
+ return (delete_instance(instance_name));
}
diff --git a/usr/src/lib/libdladm/common/libdlwlan.h b/usr/src/lib/libdladm/common/libdlwlan.h
index b1729ae658..b784ad73ba 100644
--- a/usr/src/lib/libdladm/common/libdlwlan.h
+++ b/usr/src/lib/libdladm/common/libdlwlan.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -125,20 +125,13 @@ typedef enum {
} dladm_wlan_bsstype_t;
typedef enum {
- DLADM_WLAN_LINKSTATUS_DISCONNECTED = 1,
- DLADM_WLAN_LINKSTATUS_CONNECTED
+ DLADM_WLAN_LINK_DISCONNECTED = 1,
+ DLADM_WLAN_LINK_CONNECTED
} dladm_wlan_linkstatus_t;
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,
@@ -186,33 +179,24 @@ typedef struct dladm_wlan_key {
uint_t wk_class;
} dladm_wlan_key_t;
-extern dladm_status_t dladm_wlan_scan(const char *, void *,
+extern dladm_status_t dladm_wlan_scan(datalink_id_t, void *,
boolean_t (*)(void *, dladm_wlan_attr_t *));
-extern dladm_status_t dladm_wlan_connect(const char *, dladm_wlan_attr_t *,
+extern dladm_status_t dladm_wlan_connect(datalink_id_t, dladm_wlan_attr_t *,
int, void *, uint_t, uint_t);
-extern dladm_status_t dladm_wlan_disconnect(const char *);
-extern dladm_status_t dladm_wlan_get_linkattr(const char *,
+extern dladm_status_t dladm_wlan_disconnect(datalink_id_t);
+extern dladm_status_t dladm_wlan_get_linkattr(datalink_id_t,
dladm_wlan_linkattr_t *);
-extern dladm_status_t dladm_wlan_walk(void *,
- boolean_t (*)(void *, const char *));
-extern boolean_t dladm_wlan_is_valid(const char *);
-extern dladm_status_t dladm_wlan_set_prop(const char *, const char *,
- char **, uint_t, char **);
-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 *,
+extern dladm_status_t dladm_wlan_wpa_get_sr(datalink_id_t, dladm_wlan_ess_t *,
+ uint_t, uint_t *);
+extern dladm_status_t dladm_wlan_wpa_set_ie(datalink_id_t, uint8_t *, uint_t);
+extern dladm_status_t dladm_wlan_wpa_set_wpa(datalink_id_t, boolean_t);
+extern dladm_status_t dladm_wlan_wpa_del_key(datalink_id_t, uint_t,
+ const dladm_wlan_bssid_t *);
+extern dladm_status_t dladm_wlan_wpa_set_key(datalink_id_t,
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 *,
+extern dladm_status_t dladm_wlan_wpa_set_mlme(datalink_id_t,
dladm_wlan_mlme_op_t,
dladm_wlan_reason_t, dladm_wlan_bssid_t *);
diff --git a/usr/src/lib/libdladm/common/libdlwlan_impl.h b/usr/src/lib/libdladm/common/libdlwlan_impl.h
index 764a951bed..9611b5319b 100644
--- a/usr/src/lib/libdladm/common/libdlwlan_impl.h
+++ b/usr/src/lib/libdladm/common/libdlwlan_impl.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -57,10 +57,9 @@ extern "C" {
#define DLADM_WLAN_OFDM2CHAN(mhz) (((mhz) - 5000) / 5)
#define DLADM_WLAN_CONNECT_POLLRATE 200 /* milliseconds */
-#define DLADM_WLAN_CONNECT_DEFAULT_CHANNEL 1
#define DLADM_WLAN_MAX_RATES 4
-typedef struct dladm_wlan_rates {
+typedef struct dladm_wlan_rates {
uint8_t wr_rates[DLADM_WLAN_MAX_RATES];
int wr_cnt;
} dladm_wlan_rates_t;
@@ -70,12 +69,20 @@ typedef enum {
DLADM_WLAN_RADIO_OFF
} dladm_wlan_radio_t;
-typedef enum {
+typedef enum {
DLADM_WLAN_PM_OFF = 1,
DLADM_WLAN_PM_MAX,
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 boolean_t i_dladm_wlan_convert_chan(wl_phy_conf_t *, uint32_t *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c
index e624cec0ec..a05f6ce877 100644
--- a/usr/src/lib/libdladm/common/linkprop.c
+++ b/usr/src/lib/libdladm/common/linkprop.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -29,6 +29,7 @@
#include <strings.h>
#include <errno.h>
#include <ctype.h>
+#include <stddef.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dld.h>
@@ -39,721 +40,533 @@
#include <zone.h>
#include <libdllink.h>
#include <libdladm_impl.h>
+#include <libdlwlan_impl.h>
#include <libdlwlan.h>
+#include <libdlvlan.h>
#include <dlfcn.h>
#include <link.h>
+#include <inet/wifi_ioctl.h>
-static dladm_status_t i_dladm_set_prop_db(const char *, const char *,
- char **, uint_t);
-static dladm_status_t i_dladm_get_prop_db(const char *, const char *,
- char **, uint_t *);
-static dladm_status_t i_dladm_get_prop_temp(const char *, dladm_prop_type_t,
- const char *, char **, uint_t *);
-static dladm_status_t i_dladm_set_prop_temp(const char *, const char *,
- char **, uint_t, uint_t, char **);
-static boolean_t i_dladm_is_prop_temponly(const char *prop_name,
- char **);
+/*
+ * The linkprop get() callback.
+ * - propstrp: a property string array to keep the returned property.
+ * Caller allocated.
+ * - cntp: number of returned properties.
+ * Caller also uses it to indicate how many it expects.
+ */
+typedef dladm_status_t pd_getf_t(datalink_id_t, char **propstp, uint_t *cntp);
-typedef struct val_desc {
- char *vd_name;
- void *vd_val;
-} val_desc_t;
+/*
+ * The linkprop set() callback.
+ * - propval: a val_desc_t array which keeps the property values to be set.
+ * - cnt: number of properties to be set.
+ */
+typedef dladm_status_t pd_setf_t(datalink_id_t, val_desc_t *propval,
+ uint_t cnt);
-struct prop_desc;
+#define PD_TEMPONLY 0x1
-typedef dladm_status_t pd_getf_t(const char *, char **, uint_t *);
-typedef dladm_status_t pd_setf_t(const char *, val_desc_t *, uint_t);
-typedef dladm_status_t pd_checkf_t(struct prop_desc *, char **,
- uint_t, val_desc_t **);
+/*
+ * The linkprop check() callback.
+ * - propstrp: property string array which keeps the property to be checked.
+ * - cnt: number of properties.
+ * - propval: return value; the property values of the given property strings.
+ * - dofree: indicates whether the caller needs to free propvalp->vd_val.
+ */
+typedef dladm_status_t pd_checkf_t(datalink_id_t, char **propstrp,
+ uint_t cnt, val_desc_t *propval, boolean_t *dofree);
-static pd_getf_t do_get_zone;
-static pd_setf_t do_set_zone;
-static pd_checkf_t do_check_zone;
+static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod,
+ do_get_rate_prop, do_get_channel_prop,
+ do_get_powermode_prop, do_get_radio_prop;
+static pd_setf_t do_set_zone, do_set_autopush, do_set_rate_prop,
+ do_set_powermode_prop, do_set_radio_prop;
+static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate;
typedef struct prop_desc {
- char *pd_name;
- val_desc_t pd_defval;
- val_desc_t *pd_modval;
- uint_t pd_nmodval;
- boolean_t pd_temponly;
- pd_setf_t *pd_set;
- pd_getf_t *pd_getmod;
- pd_getf_t *pd_get;
- pd_checkf_t *pd_check;
+ /*
+ * link property name
+ */
+ char *pd_name;
+
+ /*
+ * default property value, can be set to { "", NULL }
+ */
+ val_desc_t pd_defval;
+
+ /*
+ * list of optional property values, can be NULL.
+ *
+ * This is set to non-NULL if there is a list of possible property
+ * values. pd_optval would point to the array of possible values.
+ */
+ val_desc_t *pd_optval;
+
+ /*
+ * count of the above optional property values. 0 if pd_optval is NULL.
+ */
+ uint_t pd_noptval;
+
+ /*
+ * callback to set link property;
+ * set to NULL if this property is read-only
+ */
+ pd_setf_t *pd_set;
+
+ /*
+ * callback to get modifiable link property
+ */
+ pd_getf_t *pd_getmod;
+
+ /*
+ * callback to get current link property
+ */
+ pd_getf_t *pd_get;
+
+ /*
+ * callback to validate link property value, set to NULL if pd_optval
+ * is not NULL. In that case, validate the value by comparing it with
+ * the pd_optval. Return a val_desc_t array pointer if the value is
+ * valid.
+ */
+ pd_checkf_t *pd_check;
+
+ /*
+ * currently only PD_TEMPONLY is valid, which indicates the property
+ * is temporary only.
+ */
+ uint_t pd_flags;
+
+ /*
+ * indicate link classes this property applies to.
+ */
+ datalink_class_t pd_class;
+
+ /*
+ * indicate link media type this property applies to.
+ */
+ datalink_media_t pd_dmedia;
} prop_desc_t;
+static val_desc_t dladm_wlan_radio_vals[] = {
+ { "on", DLADM_WLAN_RADIO_ON },
+ { "off", DLADM_WLAN_RADIO_OFF }
+};
+
+static val_desc_t dladm_wlan_powermode_vals[] = {
+ { "off", DLADM_WLAN_PM_OFF },
+ { "fast", DLADM_WLAN_PM_FAST },
+ { "max", DLADM_WLAN_PM_MAX }
+};
+
static prop_desc_t prop_table[] = {
- { "zone", { "", NULL }, NULL, 0, B_TRUE,
+
+ { "channel", { NULL, 0 }, NULL, 0, NULL, NULL,
+ do_get_channel_prop, NULL, 0,
+ DATALINK_CLASS_PHYS, DL_WIFI},
+
+ { "powermode", { "off", DLADM_WLAN_PM_OFF },
+ dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
+ do_set_powermode_prop, NULL,
+ do_get_powermode_prop, NULL, 0,
+ DATALINK_CLASS_PHYS, DL_WIFI},
+
+ { "radio", { "on", DLADM_WLAN_RADIO_ON },
+ dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
+ do_set_radio_prop, NULL,
+ do_get_radio_prop, NULL, 0,
+ DATALINK_CLASS_PHYS, DL_WIFI},
+
+ { "speed", { "", 0 }, NULL, 0,
+ do_set_rate_prop, do_get_rate_mod,
+ do_get_rate_prop, do_check_rate, 0,
+ DATALINK_CLASS_PHYS, DL_WIFI},
+
+ { "autopush", { "", NULL }, NULL, 0,
+ do_set_autopush, NULL,
+ do_get_autopush, do_check_autopush, 0,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE},
+
+ { "zone", { "", NULL }, NULL, 0,
do_set_zone, NULL,
- do_get_zone, do_check_zone}
+ do_get_zone, do_check_zone, PD_TEMPONLY,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE}
};
-#define MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
+#define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
-dladm_status_t
-dladm_set_prop(const char *link, const char *prop_name, char **prop_val,
- uint_t val_cnt, uint_t flags, char **errprop)
-{
- dladm_status_t status = DLADM_STATUS_BADARG;
+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 *,
+ char **, uint_t *);
+static dladm_status_t i_dladm_set_single_prop(datalink_id_t, datalink_class_t,
+ uint32_t, prop_desc_t *, char **, uint_t, uint_t);
+static dladm_status_t i_dladm_set_linkprop(datalink_id_t, const char *,
+ char **, uint_t, uint_t);
- if (link == NULL || (prop_val == NULL && val_cnt > 0) ||
- (prop_val != NULL && val_cnt == 0) || flags == 0)
- return (DLADM_STATUS_BADARG);
+/*
+ * Unfortunately, MAX_SCAN_SUPPORT_RATES is too small to allow all
+ * rates to be retrieved. However, we cannot increase it at this
+ * time because it will break binary compatibility with unbundled
+ * WiFi drivers and utilities. So for now we define an additional
+ * constant, MAX_SUPPORT_RATES, to allow all rates to be retrieved.
+ */
+#define MAX_SUPPORT_RATES 64
- if ((flags & DLADM_OPT_TEMP) != 0) {
- status = i_dladm_set_prop_temp(link, prop_name, prop_val,
- val_cnt, flags, errprop);
- if (status == DLADM_STATUS_TEMPONLY &&
- (flags & DLADM_OPT_PERSIST) != 0)
- return (DLADM_STATUS_TEMPONLY);
+#define AP_ANCHOR "[anchor]"
+#define AP_DELIMITER '.'
- if (status == DLADM_STATUS_NOTFOUND) {
- status = DLADM_STATUS_BADARG;
- if (dladm_wlan_is_valid(link)) {
- status = dladm_wlan_set_prop(link, prop_name,
- prop_val, val_cnt, errprop);
+static dladm_status_t
+do_check_prop(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
+ val_desc_t *vdp)
+{
+ int i, j;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ for (j = 0; j < val_cnt; j++) {
+ for (i = 0; i < pdp->pd_noptval; i++) {
+ if (strcasecmp(*prop_val,
+ pdp->pd_optval[i].vd_name) == 0) {
+ break;
}
}
- if (status != DLADM_STATUS_OK)
- return (status);
+ if (i == pdp->pd_noptval) {
+ status = DLADM_STATUS_BADVAL;
+ goto done;
+ }
+ (void) memcpy(vdp + j, &pdp->pd_optval[i], sizeof (val_desc_t));
}
- if ((flags & DLADM_OPT_PERSIST) != 0) {
- if (i_dladm_is_prop_temponly(prop_name, errprop))
- return (DLADM_STATUS_TEMPONLY);
- status = i_dladm_set_prop_db(link, prop_name,
- prop_val, val_cnt);
- }
+done:
return (status);
}
-dladm_status_t
-dladm_walk_prop(const char *link, void *arg,
- boolean_t (*func)(void *, const char *))
+static dladm_status_t
+i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class,
+ uint32_t media, prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
+ uint_t flags)
{
- int i;
+ dladm_status_t status = DLADM_STATUS_OK;
+ val_desc_t *vdp = NULL;
+ boolean_t needfree = B_FALSE;
+ uint_t cnt, i;
- if (link == NULL || func == NULL)
+ if (!(pdp->pd_class & class))
return (DLADM_STATUS_BADARG);
- /* For wifi links, show wifi properties first */
- if (dladm_wlan_is_valid(link)) {
- dladm_status_t status;
-
- status = dladm_wlan_walk_prop(link, arg, func);
- if (status != DLADM_STATUS_OK)
- return (status);
- }
-
- /* Then show data-link properties if there are any */
- for (i = 0; i < MAX_PROPS; i++) {
- if (!func(arg, prop_table[i].pd_name))
- break;
- }
- return (DLADM_STATUS_OK);
-}
-
-dladm_status_t
-dladm_get_prop(const char *link, dladm_prop_type_t type,
- const char *prop_name, char **prop_val, uint_t *val_cntp)
-{
- dladm_status_t status;
-
- if (link == NULL || prop_name == NULL || prop_val == NULL ||
- val_cntp == NULL || *val_cntp == 0)
+ if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
return (DLADM_STATUS_BADARG);
- if (type == DLADM_PROP_VAL_PERSISTENT) {
- if (i_dladm_is_prop_temponly(prop_name, NULL))
- return (DLADM_STATUS_TEMPONLY);
- return (i_dladm_get_prop_db(link, prop_name,
- prop_val, val_cntp));
- }
+ if ((flags & DLADM_OPT_PERSIST) && (pdp->pd_flags & PD_TEMPONLY))
+ return (DLADM_STATUS_TEMPONLY);
- status = i_dladm_get_prop_temp(link, type, prop_name,
- prop_val, val_cntp);
- if (status != DLADM_STATUS_NOTFOUND)
- return (status);
+ if (!(flags & DLADM_OPT_ACTIVE))
+ return (DLADM_STATUS_OK);
- if (dladm_wlan_is_valid(link)) {
- return (dladm_wlan_get_prop(link, type, prop_name,
- prop_val, val_cntp));
- }
- return (DLADM_STATUS_BADARG);
-}
+ if (pdp->pd_set == NULL)
+ return (DLADM_STATUS_PROPRDONLY);
-/*
- * Data structures used for implementing persistent link properties
- */
-typedef struct linkprop_val {
- const char *lv_name;
- struct linkprop_val *lv_nextval;
-} linkprop_val_t;
-
-typedef struct linkprop_info {
- const char *li_name;
- struct linkprop_info *li_nextprop;
- struct linkprop_val *li_val;
-} linkprop_info_t;
-
-typedef struct linkprop_db_state linkprop_db_state_t;
-
-typedef boolean_t (*linkprop_db_op_t)(linkprop_db_state_t *,
- char *, linkprop_info_t *, dladm_status_t *);
-
-struct linkprop_db_state {
- linkprop_db_op_t ls_op;
- const char *ls_link;
- const char *ls_propname;
- char **ls_propval;
- uint_t *ls_valcntp;
-};
+ if (prop_val != NULL) {
+ vdp = malloc(sizeof (val_desc_t) * val_cnt);
+ if (vdp == NULL)
+ return (DLADM_STATUS_NOMEM);
-static void
-free_linkprops(linkprop_info_t *lip)
-{
- linkprop_info_t *lip_next;
- linkprop_val_t *lvp, *lvp_next;
-
- for (; lip != NULL; lip = lip_next) {
- lip_next = lip->li_nextprop;
- for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) {
- lvp_next = lvp->lv_nextval;
- free(lvp);
+ if (pdp->pd_check != NULL) {
+ status = pdp->pd_check(linkid, prop_val, val_cnt, vdp,
+ &needfree);
+ } else if (pdp->pd_optval != NULL) {
+ status = do_check_prop(pdp, prop_val, val_cnt, vdp);
+ } else {
+ status = DLADM_STATUS_BADARG;
}
- free(lip);
- }
-}
-/*
- * Generate an entry in the link property database.
- * Each entry has this format:
- * <linkname> <prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>;
- */
-static void
-generate_linkprop_line(linkprop_db_state_t *lsp, char *buf,
- linkprop_info_t *listp, dladm_status_t *statusp)
-{
- char tmpbuf[MAXLINELEN];
- char *ptr, *lim = tmpbuf + MAXLINELEN;
- linkprop_info_t *lip = listp;
- linkprop_val_t *lvp = NULL;
+ if (status != DLADM_STATUS_OK)
+ goto done;
- /*
- * Delete line if there are no properties left.
- */
- if (lip == NULL ||
- (lip->li_val == NULL && lip->li_nextprop == NULL)) {
- buf[0] = '\0';
- return;
- }
- ptr = tmpbuf;
- ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", lsp->ls_link);
- for (; lip != NULL; lip = lip->li_nextprop) {
- /*
- * Skip properties without values.
- */
- if (lip->li_val == NULL)
- continue;
+ cnt = val_cnt;
+ } else {
+ if (pdp->pd_defval.vd_name == NULL)
+ return (DLADM_STATUS_NOTSUP);
- ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s=", lip->li_name);
- for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) {
- ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s%c",
- lvp->lv_name,
- ((lvp->lv_nextval == NULL) ? ';' : ','));
- }
+ if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t));
+ cnt = 1;
}
- if (ptr > lim) {
- *statusp = DLADM_STATUS_TOOSMALL;
- return;
+ status = pdp->pd_set(linkid, vdp, cnt);
+ if (needfree) {
+ for (i = 0; i < cnt; i++)
+ free((void *)(((val_desc_t *)vdp + i)->vd_val));
}
- (void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
+done:
+ free(vdp);
+ return (status);
}
-/*
- * This function is used to update or create an entry in the persistent db.
- * process_linkprop_db() will first scan the db for an entry matching the
- * specified link. If a match is found, this function is invoked with the
- * entry's contents (buf) and its linked-list representation (listp). lsp
- * holds the name and values of the property to be added or updated; this
- * information will be merged with listp. Subsequently, an updated entry
- * will be written to buf, which will in turn be written to disk by
- * process_linkprop_db(). If no entry matches the specified link, listp
- * will be NULL; a new entry will be generated in this case and it will
- * contain only the property information in lsp.
- */
-static boolean_t
-process_linkprop_set(linkprop_db_state_t *lsp, char *buf,
- linkprop_info_t *listp, dladm_status_t *statusp)
+static dladm_status_t
+i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name,
+ char **prop_val, uint_t val_cnt, uint_t flags)
{
- dladm_status_t status;
- linkprop_info_t *lastp = NULL, *lip = listp, *nlip = NULL;
- linkprop_val_t **lvpp;
- int i;
-
- if (lsp->ls_propname == NULL) {
- buf[0] = '\0';
- return (B_FALSE);
- }
+ int i;
+ boolean_t found = B_FALSE;
+ datalink_class_t class;
+ uint32_t media;
+ dladm_status_t status = DLADM_STATUS_OK;
- /*
- * Find the linkprop we want to change.
- */
- for (; lip != NULL; lip = lip->li_nextprop) {
- if (strcmp(lip->li_name, lsp->ls_propname) == 0)
- break;
+ status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
+ if (status != DLADM_STATUS_OK)
+ return (status);
- lastp = lip;
- }
+ for (i = 0; i < DLADM_MAX_PROPS; i++) {
+ prop_desc_t *pdp = &prop_table[i];
+ dladm_status_t s;
- if (lip == NULL) {
- /*
- * If the linkprop is not found, append it to the list.
- */
- if ((nlip = malloc(sizeof (linkprop_info_t))) == NULL) {
- status = DLADM_STATUS_NOMEM;
- goto fail;
- }
- /*
- * nlip will need to be freed later if there is no list to
- * append to.
- */
- if (lastp != NULL)
- lastp->li_nextprop = nlip;
- nlip->li_name = lsp->ls_propname;
- nlip->li_nextprop = NULL;
- nlip->li_val = NULL;
- lvpp = &nlip->li_val;
- } else {
- linkprop_val_t *lvp, *lvp_next;
+ if (prop_name != NULL &&
+ (strcasecmp(prop_name, pdp->pd_name) != 0))
+ continue;
- /*
- * If the linkprop is found, delete the existing values from it.
- */
- for (lvp = lip->li_val; lvp != NULL; lvp = lvp_next) {
- lvp_next = lvp->lv_nextval;
- free(lvp);
- }
- lip->li_val = NULL;
- lvpp = &lip->li_val;
- }
+ found = B_TRUE;
+ s = i_dladm_set_single_prop(linkid, class, media, pdp, prop_val,
+ val_cnt, flags);
- /*
- * Fill our linkprop with the specified values.
- */
- for (i = 0; i < *lsp->ls_valcntp; i++) {
- if ((*lvpp = malloc(sizeof (linkprop_val_t))) == NULL) {
- status = DLADM_STATUS_NOMEM;
- goto fail;
+ if (prop_name != NULL) {
+ status = s;
+ break;
+ } else {
+ if (s != DLADM_STATUS_OK &&
+ s != DLADM_STATUS_NOTSUP)
+ status = s;
}
- (*lvpp)->lv_name = lsp->ls_propval[i];
- (*lvpp)->lv_nextval = NULL;
- lvpp = &(*lvpp)->lv_nextval;
}
+ if (!found)
+ status = DLADM_STATUS_NOTFOUND;
- if (listp != NULL) {
- generate_linkprop_line(lsp, buf, listp, statusp);
- } else {
- generate_linkprop_line(lsp, buf, nlip, statusp);
- free_linkprops(nlip);
- }
- return (B_FALSE);
-
-fail:
- *statusp = status;
- if (listp == NULL)
- free_linkprops(nlip);
-
- return (B_FALSE);
+ return (status);
}
/*
- * This function is used for retrieving the values for a specific property.
- * It gets called if an entry matching the specified link exists in the db.
- * The entry is converted into a linked-list listp. This list is then scanned
- * for the specified property name; if a matching property exists, its
- * associated values are copied to the array lsp->ls_propval.
+ * Set/reset link property for specific link
*/
-/* ARGSUSED */
-static boolean_t
-process_linkprop_get(linkprop_db_state_t *lsp, char *buf,
- linkprop_info_t *listp, dladm_status_t *statusp)
+dladm_status_t
+dladm_set_linkprop(datalink_id_t linkid, const char *prop_name, char **prop_val,
+ uint_t val_cnt, uint_t flags)
{
- linkprop_info_t *lip = listp;
- linkprop_val_t *lvp;
- uint_t valcnt = 0;
+ dladm_status_t status = DLADM_STATUS_OK;
- /*
- * Find the linkprop we want to get.
- */
- for (; lip != NULL; lip = lip->li_nextprop) {
- if (strcmp(lip->li_name, lsp->ls_propname) == 0)
- break;
- }
- if (lip == NULL) {
- *statusp = DLADM_STATUS_NOTFOUND;
- return (B_FALSE);
+ if ((linkid == DATALINK_INVALID_LINKID) || (flags == 0) ||
+ (prop_val == NULL && val_cnt > 0) ||
+ (prop_val != NULL && val_cnt == 0) ||
+ (prop_name == NULL && prop_val != NULL)) {
+ return (DLADM_STATUS_BADARG);
}
- for (lvp = lip->li_val; lvp != NULL; lvp = lvp->lv_nextval) {
- (void) strncpy(lsp->ls_propval[valcnt], lvp->lv_name,
- DLADM_PROP_VAL_MAX);
+ status = i_dladm_set_linkprop(linkid, prop_name, prop_val,
+ val_cnt, flags);
+ if (status != DLADM_STATUS_OK)
+ return (status);
- if (++valcnt >= *lsp->ls_valcntp && lvp->lv_nextval != NULL) {
- *statusp = DLADM_STATUS_TOOSMALL;
- return (B_FALSE);
- }
+ if (flags & DLADM_OPT_PERSIST) {
+ status = i_dladm_set_linkprop_db(linkid, prop_name,
+ prop_val, val_cnt);
}
- /*
- * This function is meant to be called at most once for each call
- * to process_linkprop_db(). For this reason, it's ok to overwrite
- * the caller's valcnt array size with the actual number of values
- * returned.
- */
- *lsp->ls_valcntp = valcnt;
- return (B_FALSE);
+ return (status);
}
/*
- * This is used for initializing link properties.
- * Unlike the other routines, this gets called for every entry in the
- * database. lsp->ls_link is not user-specified but instead is set to
- * the current link being processed.
+ * Walk link properties of the given specific link.
*/
-/* ARGSUSED */
-static boolean_t
-process_linkprop_init(linkprop_db_state_t *lsp, char *buf,
- linkprop_info_t *listp, dladm_status_t *statusp)
+dladm_status_t
+dladm_walk_linkprop(datalink_id_t linkid, void *arg,
+ int (*func)(datalink_id_t, const char *, void *))
{
- dladm_status_t status = DLADM_STATUS_OK;
- linkprop_info_t *lip = listp;
- linkprop_val_t *lvp;
- uint_t valcnt, i;
- char **propval;
-
- for (; lip != NULL; lip = lip->li_nextprop) {
- /*
- * Construct the propval array and fill it with
- * values from listp.
- */
- for (lvp = lip->li_val, valcnt = 0;
- lvp != NULL; lvp = lvp->lv_nextval, valcnt++)
- ;
+ dladm_status_t status;
+ datalink_class_t class;
+ uint_t media;
+ int i;
- propval = malloc(sizeof (char *) * valcnt);
- if (propval == NULL) {
- *statusp = DLADM_STATUS_NOMEM;
- break;
- }
- lvp = lip->li_val;
- for (i = 0; i < valcnt; i++, lvp = lvp->lv_nextval)
- propval[i] = (char *)lvp->lv_name;
-
- status = dladm_set_prop(lsp->ls_link, lip->li_name,
- propval, valcnt, DLADM_OPT_TEMP, NULL);
-
- /*
- * We continue with initializing other properties even
- * after encountering an error. This error will be
- * propagated to the caller via 'statusp'.
- */
- if (status != DLADM_STATUS_OK)
- *statusp = status;
-
- free(propval);
- }
- return (B_TRUE);
-}
+ if (linkid == DATALINK_INVALID_LINKID || func == NULL)
+ return (DLADM_STATUS_BADARG);
-static int
-parse_linkprops(char *buf, linkprop_info_t **lipp)
-{
- int i, len;
- char *curr;
- linkprop_info_t *lip = NULL;
- linkprop_info_t **tailp = lipp;
- linkprop_val_t *lvp = NULL;
- linkprop_val_t **vtailp = NULL;
-
- curr = buf;
- len = strlen(buf);
- for (i = 0; i < len; i++) {
- char c = buf[i];
- boolean_t match = (c == '=' || c == ',' || c == ';');
+ status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
+ if (status != DLADM_STATUS_OK)
+ return (status);
- /*
- * Move to the next character if there is no match and
- * if we have not reached the last character.
- */
- if (!match && i != len - 1)
+ for (i = 0; i < DLADM_MAX_PROPS; i++) {
+ if (!(prop_table[i].pd_class & class))
continue;
- if (match) {
- /*
- * Nul-terminate the string pointed to by 'curr'.
- */
- buf[i] = '\0';
- if (*curr == '\0')
- goto fail;
- }
+ if (!DATALINK_MEDIA_ACCEPTED(prop_table[i].pd_dmedia, media))
+ continue;
- if (lip != NULL) {
- /*
- * We get here after we have processed the "<prop>="
- * pattern. The pattern we are now interested in is
- * "<val0>,<val1>,...,<valn>;". For each value we
- * find, a linkprop_val_t will be allocated and
- * added to the current 'lip'.
- */
- if (c == '=')
- goto fail;
-
- lvp = malloc(sizeof (*lvp));
- if (lvp == NULL)
- goto fail;
-
- lvp->lv_name = curr;
- lvp->lv_nextval = NULL;
- *vtailp = lvp;
- vtailp = &lvp->lv_nextval;
-
- if (c == ';') {
- tailp = &lip->li_nextprop;
- vtailp = NULL;
- lip = NULL;
- }
- } else {
- /*
- * lip == NULL indicates that 'curr' must be refering
- * to a property name. We allocate a new linkprop_info_t
- * append it to the list given by the caller.
- */
- if (c != '=')
- goto fail;
-
- lip = malloc(sizeof (*lip));
- if (lip == NULL)
- goto fail;
-
- lip->li_name = curr;
- lip->li_val = NULL;
- lip->li_nextprop = NULL;
- *tailp = lip;
- vtailp = &lip->li_val;
+ if (func(linkid, prop_table[i].pd_name, arg) ==
+ DLADM_WALK_TERMINATE) {
+ break;
}
- curr = buf + i + 1;
}
- /*
- * The list must be non-empty and the last character must be ';'.
- */
- if (*lipp == NULL || lip != NULL)
- goto fail;
-
- return (0);
-fail:
- free_linkprops(*lipp);
- *lipp = NULL;
- return (-1);
+ return (DLADM_STATUS_OK);
}
-static boolean_t
-process_linkprop_line(linkprop_db_state_t *lsp, char *buf,
- dladm_status_t *statusp)
+/*
+ * Get linkprop of the given specific link.
+ */
+dladm_status_t
+dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type,
+ const char *prop_name, char **prop_val, uint_t *val_cntp)
{
- linkprop_info_t *lip = NULL;
- int i, len, llen;
- char *str, *lasts;
- boolean_t cont, nolink = B_FALSE;
+ dladm_status_t status = DLADM_STATUS_OK;
+ datalink_class_t class;
+ uint_t media;
+ prop_desc_t *pdp;
+ uint_t cnt;
+ int i;
+
+ if (linkid == DATALINK_INVALID_LINKID || prop_name == NULL ||
+ prop_val == NULL || val_cntp == NULL || *val_cntp == 0)
+ return (DLADM_STATUS_BADARG);
- /*
- * Skip leading spaces, blank lines, and comments.
- */
- len = strlen(buf);
- for (i = 0; i < len; i++) {
- if (!isspace(buf[i]))
+ for (i = 0; i < DLADM_MAX_PROPS; i++)
+ if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
break;
- }
- if (i == len || buf[i] == '#')
- return (B_TRUE);
- str = buf + i;
- if (lsp->ls_link != NULL) {
- /*
- * Skip links we're not interested in.
- * Note that strncmp() and isspace() are used here
- * instead of strtok() and strcmp() because we don't
- * want to modify buf in case it does not contain the
- * specified link.
- */
- llen = strlen(lsp->ls_link);
- if (strncmp(str, lsp->ls_link, llen) != 0 ||
- !isspace(str[llen]))
- return (B_TRUE);
- } else {
- /*
- * If a link is not specified, find the link name
- * and assign it to lsp->ls_link.
- */
- if (strtok_r(str, " \n\t", &lasts) == NULL)
- goto fail;
-
- llen = strlen(str);
- lsp->ls_link = str;
- nolink = B_TRUE;
- }
- str += llen + 1;
- if (str >= buf + len)
- goto fail;
-
- /*
- * Now find the list of link properties.
- */
- if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
- goto fail;
+ if (i == DLADM_MAX_PROPS)
+ return (DLADM_STATUS_NOTFOUND);
- if (parse_linkprops(str, &lip) < 0)
- goto fail;
+ pdp = &prop_table[i];
- cont = (*lsp->ls_op)(lsp, buf, lip, statusp);
- free_linkprops(lip);
- if (nolink)
- lsp->ls_link = NULL;
- return (cont);
+ status = dladm_datalink_id2info(linkid, NULL, &class, &media, NULL, 0);
+ if (status != DLADM_STATUS_OK)
+ return (status);
-fail:
- free_linkprops(lip);
- if (nolink)
- lsp->ls_link = NULL;
+ if (!(pdp->pd_class & class))
+ return (DLADM_STATUS_BADARG);
- /*
- * Delete corrupted line.
- */
- buf[0] = '\0';
- return (B_TRUE);
-}
+ if (!DATALINK_MEDIA_ACCEPTED(pdp->pd_dmedia, media))
+ return (DLADM_STATUS_BADARG);
-static dladm_status_t
-process_linkprop_db(void *arg, FILE *fp, FILE *nfp)
-{
- linkprop_db_state_t *lsp = arg;
- dladm_status_t status = DLADM_STATUS_OK;
- char buf[MAXLINELEN];
- boolean_t cont = B_TRUE;
+ switch (type) {
+ case DLADM_PROP_VAL_CURRENT:
+ status = pdp->pd_get(linkid, prop_val, val_cntp);
+ break;
- /*
- * This loop processes each line of the configuration file.
- * buf can potentially be modified by process_linkprop_line().
- * If this is a write operation and buf is not truncated, buf will
- * be written to disk. process_linkprop_line() will no longer be
- * called after it returns B_FALSE; at which point the remainder
- * of the file will continue to be read and, if necessary, written
- * to disk as well.
- */
- while (fgets(buf, MAXLINELEN, fp) != NULL) {
- if (cont)
- cont = process_linkprop_line(lsp, buf, &status);
+ case DLADM_PROP_VAL_DEFAULT:
+ if (pdp->pd_defval.vd_name == NULL) {
+ status = DLADM_STATUS_NOTSUP;
+ break;
+ }
+ (void) strcpy(*prop_val, pdp->pd_defval.vd_name);
+ *val_cntp = 1;
+ break;
- if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
- status = dladm_errno2status(errno);
+ case DLADM_PROP_VAL_MODIFIABLE:
+ if (pdp->pd_getmod != NULL) {
+ status = pdp->pd_getmod(linkid, prop_val, val_cntp);
break;
}
+ cnt = pdp->pd_noptval;
+ if (cnt == 0) {
+ status = DLADM_STATUS_NOTSUP;
+ } else if (cnt > *val_cntp) {
+ status = DLADM_STATUS_TOOSMALL;
+ } else {
+ for (i = 0; i < cnt; i++) {
+ (void) strcpy(prop_val[i],
+ pdp->pd_optval[i].vd_name);
+ }
+ *val_cntp = cnt;
+ }
+ break;
+ case DLADM_PROP_VAL_PERSISTENT:
+ if (pdp->pd_flags & PD_TEMPONLY)
+ return (DLADM_STATUS_TEMPONLY);
+ status = i_dladm_get_linkprop_db(linkid, prop_name,
+ prop_val, val_cntp);
+ break;
+ default:
+ status = DLADM_STATUS_BADARG;
+ break;
}
- if (status != DLADM_STATUS_OK || !cont)
- return (status);
+ return (status);
+}
- if (lsp->ls_op == process_linkprop_set) {
- /*
- * If the specified link is not found above, we add the
- * link and its properties to the configuration file.
- */
- (void) (*lsp->ls_op)(lsp, buf, NULL, &status);
- if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
- status = dladm_errno2status(errno);
- }
+/*ARGSUSED*/
+static int
+i_dladm_init_one_prop(datalink_id_t linkid, const char *prop_name, void *arg)
+{
+ char *buf, **propvals;
+ uint_t i, valcnt = DLADM_MAX_PROP_VALCNT;
- if (lsp->ls_op == process_linkprop_get)
- status = DLADM_STATUS_NOTFOUND;
+ if ((buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
+ DLADM_MAX_PROP_VALCNT)) == NULL) {
+ return (DLADM_WALK_CONTINUE);
+ }
- return (status);
-}
+ propvals = (char **)(void *)buf;
+ for (i = 0; i < valcnt; i++) {
+ propvals[i] = buf +
+ sizeof (char *) * DLADM_MAX_PROP_VALCNT +
+ i * DLADM_PROP_VAL_MAX;
+ }
-#define LINKPROP_RW_DB(statep, writeop) \
- (i_dladm_rw_db("/etc/dladm/linkprop.conf", \
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, process_linkprop_db, \
- (statep), (writeop)))
+ if (dladm_get_linkprop(linkid, DLADM_PROP_VAL_PERSISTENT, prop_name,
+ propvals, &valcnt) != DLADM_STATUS_OK) {
+ goto done;
+ }
-static dladm_status_t
-i_dladm_set_prop_db(const char *link, const char *prop_name,
- char **prop_val, uint_t val_cnt)
-{
- linkprop_db_state_t state;
+ (void) dladm_set_linkprop(linkid, prop_name, propvals, valcnt,
+ DLADM_OPT_ACTIVE);
- state.ls_op = process_linkprop_set;
- state.ls_link = link;
- state.ls_propname = prop_name;
- state.ls_propval = prop_val;
- state.ls_valcntp = &val_cnt;
+done:
+ if (buf != NULL)
+ free(buf);
- return (LINKPROP_RW_DB(&state, B_TRUE));
+ return (DLADM_WALK_CONTINUE);
}
-static dladm_status_t
-i_dladm_get_prop_db(const char *link, const char *prop_name,
- char **prop_val, uint_t *val_cntp)
+/*ARGSUSED*/
+static int
+i_dladm_init_linkprop(datalink_id_t linkid, void *arg)
{
- linkprop_db_state_t state;
-
- state.ls_op = process_linkprop_get;
- state.ls_link = link;
- state.ls_propname = prop_name;
- state.ls_propval = prop_val;
- state.ls_valcntp = val_cntp;
-
- return (LINKPROP_RW_DB(&state, B_FALSE));
+ (void) dladm_init_linkprop(linkid);
+ return (DLADM_WALK_CONTINUE);
}
dladm_status_t
-dladm_init_linkprop(void)
+dladm_init_linkprop(datalink_id_t linkid)
{
- linkprop_db_state_t state;
-
- state.ls_op = process_linkprop_init;
- state.ls_link = NULL;
- state.ls_propname = NULL;
- state.ls_propval = NULL;
- state.ls_valcntp = NULL;
-
- return (LINKPROP_RW_DB(&state, B_FALSE));
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_PERSIST);
+ } else {
+ (void) dladm_walk_linkprop(linkid, NULL, i_dladm_init_one_prop);
+ }
+ return (DLADM_STATUS_OK);
}
static dladm_status_t
-i_dladm_get_zoneid(const char *link, zoneid_t *zidp)
+do_get_zone(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
{
- int fd;
- dld_hold_vlan_t dhv;
+ char zone_name[ZONENAME_MAX];
+ zoneid_t zid;
+ dladm_status_t status;
- if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
- return (dladm_errno2status(errno));
+ status = dladm_getzid(linkid, &zid);
+ if (status != DLADM_STATUS_OK)
+ return (status);
- bzero(&dhv, sizeof (dld_hold_vlan_t));
- (void) strlcpy(dhv.dhv_name, link, IFNAMSIZ);
- dhv.dhv_zid = -1;
+ *val_cnt = 1;
+ if (zid != GLOBAL_ZONEID) {
+ if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
+ return (dladm_errno2status(errno));
- if (i_dladm_ioctl(fd, DLDIOCZIDGET, &dhv, sizeof (dhv)) < 0) {
- if (errno == ENOENT) {
- *zidp = GLOBAL_ZONEID;
- } else {
- dladm_status_t status = dladm_errno2status(errno);
- (void) close(fd);
- return (status);
- }
+ (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
} else {
- *zidp = dhv.dhv_zid;
+ *prop_val[0] = '\0';
}
- (void) close(fd);
return (DLADM_STATUS_OK);
}
@@ -785,12 +598,14 @@ i_dladm_get_zone_dev(char *zone_name, char *dev, size_t devlen)
}
static dladm_status_t
-i_dladm_add_deventry(zoneid_t zid, const char *link)
+i_dladm_update_deventry(zoneid_t zid, datalink_id_t linkid, boolean_t add)
{
char path[MAXPATHLEN];
+ char name[MAXLINKNAMELEN];
di_prof_t prof = NULL;
char zone_name[ZONENAME_MAX];
dladm_status_t status;
+ int ret;
if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
return (dladm_errno2status(errno));
@@ -799,40 +614,20 @@ i_dladm_add_deventry(zoneid_t zid, const char *link)
if (di_prof_init(path, &prof) != 0)
return (dladm_errno2status(errno));
- status = DLADM_STATUS_OK;
- if (di_prof_add_dev(prof, link) != 0) {
- status = dladm_errno2status(errno);
+ status = dladm_linkid2legacyname(linkid, name, MAXLINKNAMELEN);
+ if (status != DLADM_STATUS_OK)
goto cleanup;
- }
- if (di_prof_commit(prof) != 0)
- status = dladm_errno2status(errno);
-cleanup:
- if (prof)
- di_prof_fini(prof);
-
- return (status);
-}
-
-static dladm_status_t
-i_dladm_remove_deventry(zoneid_t zid, const char *link)
-{
- char path[MAXPATHLEN];
- di_prof_t prof = NULL;
- char zone_name[ZONENAME_MAX];
- dladm_status_t status;
- if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
- return (dladm_errno2status(errno));
- if (i_dladm_get_zone_dev(zone_name, path, sizeof (path)) != 0)
- return (dladm_errno2status(errno));
- if (di_prof_init(path, &prof) != 0)
- return (dladm_errno2status(errno));
+ if (add)
+ ret = di_prof_add_dev(prof, name);
+ else
+ ret = di_prof_add_exclude(prof, name);
- status = DLADM_STATUS_OK;
- if (di_prof_add_exclude(prof, link) != 0) {
+ if (ret != 0) {
status = dladm_errno2status(errno);
goto cleanup;
}
+
if (di_prof_commit(prof) != 0)
status = dladm_errno2status(errno);
cleanup:
@@ -843,102 +638,93 @@ cleanup:
}
static dladm_status_t
-do_get_zone(const char *link, char **prop_val, uint_t *val_cnt)
-{
- char zone_name[ZONENAME_MAX];
- zoneid_t zid;
- dladm_status_t status;
-
- status = i_dladm_get_zoneid(link, &zid);
- if (status != DLADM_STATUS_OK)
- return (status);
-
- *val_cnt = 1;
- if (zid != GLOBAL_ZONEID) {
- if (getzonenamebyid(zid, zone_name, sizeof (zone_name)) < 0)
- return (dladm_errno2status(errno));
-
- (void) strncpy(*prop_val, zone_name, DLADM_PROP_VAL_MAX);
- } else {
- *prop_val[0] = '\0';
- }
-
- return (DLADM_STATUS_OK);
-}
-
-static dladm_status_t
-do_set_zone(const char *link, val_desc_t *vdp, uint_t val_cnt)
+do_set_zone(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
{
dladm_status_t status;
zoneid_t zid_old, zid_new;
+ char link[MAXLINKNAMELEN];
if (val_cnt != 1)
return (DLADM_STATUS_BADVALCNT);
- status = i_dladm_get_zoneid(link, &zid_old);
+ status = dladm_getzid(linkid, &zid_old);
if (status != DLADM_STATUS_OK)
return (status);
/* Do nothing if setting to current value */
- zid_new = (intptr_t)(void *)vdp->vd_val;
+ zid_new = vdp->vd_val;
if (zid_new == zid_old)
return (DLADM_STATUS_OK);
- if (zid_old != GLOBAL_ZONEID) {
- if (dladm_rele_link(link, GLOBAL_ZONEID, B_TRUE) < 0)
- return (dladm_errno2status(errno));
+ if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL,
+ link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
+ return (status);
+ }
- if (zone_remove_datalink(zid_old, (char *)link) != 0 &&
+ if (zid_new != GLOBAL_ZONEID) {
+ /*
+ * If the new zoneid is the global zone, we could destroy
+ * the link (in the case of an implicitly-created VLAN) as a
+ * result of the dladm_setzid() operation. In that case,
+ * we defer the operation to the end of this function to avoid
+ * recreating the VLAN and getting a different linkid during
+ * the rollback if other operation fails.
+ *
+ * Otherwise, dladm_setzid() will hold a reference to the
+ * link and prevent a link renaming, so we need to do it
+ * before other operations.
+ */
+ status = dladm_setzid(link, zid_new);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+ }
+
+ if (zid_old != GLOBAL_ZONEID) {
+ if (zone_remove_datalink(zid_old, link) != 0 &&
errno != ENXIO) {
status = dladm_errno2status(errno);
goto rollback1;
}
- status = i_dladm_remove_deventry(zid_old, link);
- if (status != DLADM_STATUS_OK)
- goto rollback2;
+ /*
+ * It is okay to fail to update the /dev entry (some
+ * vanity-named links do not have a /dev entry).
+ */
+ (void) i_dladm_update_deventry(zid_old, linkid, B_FALSE);
}
if (zid_new != GLOBAL_ZONEID) {
- if (zone_add_datalink(zid_new, (char *)link) != 0) {
- status = dladm_errno2status(errno);
- goto rollback3;
- }
-
- if (dladm_hold_link(link, zid_new, B_TRUE) < 0) {
- (void) zone_remove_datalink(zid_new, (char *)link);
+ if (zone_add_datalink(zid_new, link) != 0) {
status = dladm_errno2status(errno);
- goto rollback3;
+ goto rollback2;
}
- status = i_dladm_add_deventry(zid_new, link);
- if (status != DLADM_STATUS_OK) {
- (void) dladm_rele_link(link, GLOBAL_ZONEID, B_FALSE);
- (void) zone_remove_datalink(zid_new, (char *)link);
- goto rollback3;
- }
+ (void) i_dladm_update_deventry(zid_new, linkid, B_TRUE);
+ } else {
+ status = dladm_setzid(link, zid_new);
+ if (status != DLADM_STATUS_OK)
+ goto rollback2;
}
+
return (DLADM_STATUS_OK);
-rollback3:
- if (zid_old != GLOBAL_ZONEID)
- (void) i_dladm_add_deventry(zid_old, link);
rollback2:
if (zid_old != GLOBAL_ZONEID)
- (void) zone_add_datalink(zid_old, (char *)link);
+ (void) i_dladm_update_deventry(zid_old, linkid, B_TRUE);
+ if (zid_old != GLOBAL_ZONEID)
+ (void) zone_add_datalink(zid_old, link);
rollback1:
- (void) dladm_hold_link(link, zid_old, B_FALSE);
-cleanexit:
+ if (zid_new != GLOBAL_ZONEID)
+ (void) dladm_setzid(link, zid_old);
return (status);
}
/* ARGSUSED */
static dladm_status_t
-do_check_zone(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
- val_desc_t **vdpp)
+do_check_zone(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
+ val_desc_t *vdp, boolean_t *needfreep)
{
- zoneid_t zid;
- val_desc_t *vdp = NULL;
+ zoneid_t zid;
if (val_cnt != 1)
return (DLADM_STATUS_BADVALCNT);
@@ -959,176 +745,563 @@ do_check_zone(prop_desc_t *pdp, char **prop_val, uint_t val_cnt,
}
}
- vdp = malloc(sizeof (val_desc_t));
- if (vdp == NULL)
- return (DLADM_STATUS_NOMEM);
-
- vdp->vd_val = (void *)(uintptr_t)zid;
- *vdpp = vdp;
+ vdp->vd_val = zid;
+ *needfreep = B_FALSE;
return (DLADM_STATUS_OK);
}
static dladm_status_t
-i_dladm_get_prop_temp(const char *link, dladm_prop_type_t type,
- const char *prop_name, char **prop_val, uint_t *val_cntp)
+do_get_autopush(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
{
- int i;
- dladm_status_t status;
- uint_t cnt;
- prop_desc_t *pdp;
+ dld_ioc_ap_t dia;
+ int fd, i, len;
- if (link == NULL || prop_name == NULL || prop_val == NULL ||
- val_cntp == NULL || *val_cntp == 0)
- return (DLADM_STATUS_BADARG);
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
- for (i = 0; i < MAX_PROPS; i++)
- if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
- break;
+ *val_cnt = 1;
+ dia.dia_linkid = linkid;
+ if (i_dladm_ioctl(fd, DLDIOC_GETAUTOPUSH, &dia, sizeof (dia)) < 0) {
+ (*prop_val)[0] = '\0';
+ goto done;
+ }
- if (i == MAX_PROPS)
- return (DLADM_STATUS_NOTFOUND);
+ for (i = 0, len = 0; i < dia.dia_npush; i++) {
+ if (i != 0) {
+ (void) snprintf(*prop_val + len,
+ DLADM_PROP_VAL_MAX - len, "%c", AP_DELIMITER);
+ len += 1;
+ }
+ (void) snprintf(*prop_val + len, DLADM_PROP_VAL_MAX - len,
+ "%s", dia.dia_aplist[i]);
+ len += strlen(dia.dia_aplist[i]);
+ if (dia.dia_anchor - 1 == i) {
+ (void) snprintf(*prop_val + len,
+ DLADM_PROP_VAL_MAX - len, "%c%s", AP_DELIMITER,
+ AP_ANCHOR);
+ len += (strlen(AP_ANCHOR) + 1);
+ }
+ }
- pdp = &prop_table[i];
- status = DLADM_STATUS_OK;
+done:
+ (void) close(fd);
+ return (DLADM_STATUS_OK);
+}
- switch (type) {
- case DLADM_PROP_VAL_CURRENT:
- status = pdp->pd_get(link, prop_val, val_cntp);
- break;
- case DLADM_PROP_VAL_DEFAULT:
- if (pdp->pd_defval.vd_name == NULL) {
- status = DLADM_STATUS_NOTSUP;
- break;
- }
- (void) strcpy(*prop_val, pdp->pd_defval.vd_name);
- *val_cntp = 1;
- break;
+static dladm_status_t
+do_set_autopush(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+{
+ dld_ioc_ap_t dia;
+ struct dlautopush *dlap = (struct dlautopush *)vdp->vd_val;
+ dladm_status_t status = DLADM_STATUS_OK;
+ int fd, i;
+ int ic_cmd;
- case DLADM_PROP_VAL_MODIFIABLE:
- if (pdp->pd_getmod != NULL) {
- status = pdp->pd_getmod(link, prop_val, val_cntp);
- break;
- }
- cnt = pdp->pd_nmodval;
- if (cnt == 0) {
- status = DLADM_STATUS_NOTSUP;
- } else if (cnt > *val_cntp) {
- status = DLADM_STATUS_TOOSMALL;
- } else {
- for (i = 0; i < cnt; i++) {
- (void) strcpy(prop_val[i],
- pdp->pd_modval[i].vd_name);
- }
- *val_cntp = cnt;
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (dladm_errno2status(errno));
+
+ dia.dia_linkid = linkid;
+ if (dlap != NULL) {
+ dia.dia_anchor = dlap->dap_anchor;
+ dia.dia_npush = dlap->dap_npush;
+ for (i = 0; i < dia.dia_npush; i++) {
+ (void) strlcpy(dia.dia_aplist[i], dlap->dap_aplist[i],
+ FMNAMESZ+1);
}
- break;
- default:
- status = DLADM_STATUS_BADARG;
- break;
+ ic_cmd = DLDIOC_SETAUTOPUSH;
+ } else {
+ ic_cmd = DLDIOC_CLRAUTOPUSH;
}
+ if (i_dladm_ioctl(fd, ic_cmd, &dia, sizeof (dia)) < 0)
+ status = dladm_errno2status(errno);
+
+ (void) close(fd);
return (status);
}
-static dladm_status_t
-i_dladm_set_one_prop_temp(const char *link, prop_desc_t *pdp, char **prop_val,
- uint_t val_cnt, uint_t flags)
+/*
+ * Add the specified module to the dlautopush structure; returns a
+ * DLADM_STATUS_* code.
+ */
+dladm_status_t
+i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
{
- dladm_status_t status;
- val_desc_t *vdp = NULL;
- uint_t cnt;
+ if ((strlen(module) == 0) || (strlen(module) > FMNAMESZ))
+ return (DLADM_STATUS_BADVAL);
- if (pdp->pd_temponly && (flags & DLADM_OPT_PERSIST) != 0)
- return (DLADM_STATUS_TEMPONLY);
+ if (strncasecmp(module, AP_ANCHOR, strlen(AP_ANCHOR)) == 0) {
+ /*
+ * We don't allow multiple anchors, and the anchor must
+ * be after at least one module.
+ */
+ if (dlap->dap_anchor != 0)
+ return (DLADM_STATUS_BADVAL);
+ if (dlap->dap_npush == 0)
+ return (DLADM_STATUS_BADVAL);
- if (pdp->pd_set == NULL)
- return (DLADM_STATUS_PROPRDONLY);
+ dlap->dap_anchor = dlap->dap_npush;
+ return (DLADM_STATUS_OK);
+ }
+ if (dlap->dap_npush > MAXAPUSH)
+ return (DLADM_STATUS_BADVALCNT);
- if (prop_val != NULL) {
- if (pdp->pd_check != NULL)
- status = pdp->pd_check(pdp, prop_val, val_cnt, &vdp);
- else
- status = DLADM_STATUS_BADARG;
+ (void) strlcpy(dlap->dap_aplist[dlap->dap_npush++], module,
+ FMNAMESZ + 1);
+
+ return (DLADM_STATUS_OK);
+}
+
+/*
+ * Currently, both '.' and ' '(space) can be used as the delimiters between
+ * autopush modules. The former is used in dladm set-linkprop, and the
+ * latter is used in the autopush(1M) file.
+ */
+/* ARGSUSED */
+static dladm_status_t
+do_check_autopush(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
+ val_desc_t *vdp, boolean_t *needfreep)
+{
+ char *module;
+ struct dlautopush *dlap;
+ dladm_status_t status;
+ char val[DLADM_PROP_VAL_MAX];
+ char delimiters[4];
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ dlap = malloc(sizeof (struct dlautopush));
+ if (dlap == NULL)
+ return (DLADM_STATUS_NOMEM);
+ (void) memset(dlap, 0, sizeof (struct dlautopush));
+ (void) snprintf(delimiters, 4, " %c\n", AP_DELIMITER);
+ bcopy(*prop_val, val, DLADM_PROP_VAL_MAX);
+ module = strtok(val, delimiters);
+ while (module != NULL) {
+ status = i_dladm_add_ap_module(module, dlap);
if (status != DLADM_STATUS_OK)
return (status);
+ module = strtok(NULL, delimiters);
+ }
- cnt = val_cnt;
- } else {
- if (pdp->pd_defval.vd_name == NULL)
- return (DLADM_STATUS_NOTSUP);
+ vdp->vd_val = (uintptr_t)dlap;
+ *needfreep = B_TRUE;
+ return (DLADM_STATUS_OK);
+}
- if ((vdp = malloc(sizeof (val_desc_t))) == NULL)
- return (DLADM_STATUS_NOMEM);
+static dladm_status_t
+do_get_rate_common(datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
+ uint_t id)
+{
+ wl_rates_t *wrp;
+ uint_t i;
+ wldp_t *gbuf = NULL;
+ dladm_status_t status = DLADM_STATUS_OK;
- (void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t));
- cnt = 1;
+ if ((gbuf = malloc(MAX_BUF_LEN)) == NULL) {
+ status = DLADM_STATUS_NOMEM;
+ goto done;
}
- status = pdp->pd_set(link, vdp, cnt);
+ status = i_dladm_wlan_get_ioctl(linkid, gbuf, id);
+ if (status != DLADM_STATUS_OK)
+ goto done;
- free(vdp);
+ wrp = (wl_rates_t *)gbuf->wldp_buf;
+ if (wrp->wl_rates_num > *val_cnt) {
+ status = DLADM_STATUS_TOOSMALL;
+ goto done;
+ }
+
+ if (wrp->wl_rates_rates[0] == 0) {
+ prop_val[0][0] = '\0';
+ *val_cnt = 1;
+ goto done;
+ }
+
+ for (i = 0; i < wrp->wl_rates_num; i++) {
+ (void) snprintf(prop_val[i], DLADM_STRSIZE, "%.*f",
+ wrp->wl_rates_rates[i] % 2,
+ (float)wrp->wl_rates_rates[i] / 2);
+ }
+ *val_cnt = wrp->wl_rates_num;
+
+done:
+ free(gbuf);
return (status);
}
static dladm_status_t
-i_dladm_set_prop_temp(const char *link, const char *prop_name, char **prop_val,
- uint_t val_cnt, uint_t flags, char **errprop)
+do_get_rate_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+{
+ return (do_get_rate_common(linkid, prop_val, val_cnt,
+ WL_DESIRED_RATES));
+}
+
+static dladm_status_t
+do_get_rate_mod(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+{
+ return (do_get_rate_common(linkid, prop_val, val_cnt,
+ WL_SUPPORTED_RATES));
+}
+
+static dladm_status_t
+do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates)
{
- int i;
+ int i;
+ uint_t len;
+ wldp_t *gbuf;
+ wl_rates_t *wrp;
dladm_status_t status = DLADM_STATUS_OK;
- boolean_t found = B_FALSE;
- for (i = 0; i < MAX_PROPS; i++) {
- prop_desc_t *pdp = &prop_table[i];
- dladm_status_t s;
+ if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
+ return (DLADM_STATUS_NOMEM);
- if (prop_name != NULL &&
- (strcasecmp(prop_name, pdp->pd_name) != 0))
- continue;
+ (void) memset(gbuf, 0, MAX_BUF_LEN);
- found = B_TRUE;
- s = i_dladm_set_one_prop_temp(link, pdp, prop_val, val_cnt,
- flags);
+ wrp = (wl_rates_t *)gbuf->wldp_buf;
+ for (i = 0; i < rates->wr_cnt; i++)
+ wrp->wl_rates_rates[i] = rates->wr_rates[i];
+ wrp->wl_rates_num = rates->wr_cnt;
- if (prop_name != NULL) {
- status = s;
+ 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);
+
+ free(gbuf);
+ return (status);
+}
+
+static dladm_status_t
+do_set_rate_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+{
+ dladm_wlan_rates_t rates;
+ dladm_status_t status;
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ rates.wr_cnt = 1;
+ rates.wr_rates[0] = vdp[0].vd_val;
+
+ status = do_set_rate(linkid, &rates);
+
+done:
+ return (status);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+do_check_rate(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
+ val_desc_t *vdp, boolean_t *needfreep)
+{
+ int i;
+ uint_t modval_cnt = MAX_SUPPORT_RATES;
+ char *buf, **modval;
+ dladm_status_t status;
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ buf = malloc((sizeof (char *) + DLADM_STRSIZE) *
+ MAX_SUPPORT_RATES);
+ if (buf == NULL) {
+ status = DLADM_STATUS_NOMEM;
+ goto done;
+ }
+
+ modval = (char **)(void *)buf;
+ for (i = 0; i < MAX_SUPPORT_RATES; i++) {
+ modval[i] = buf + sizeof (char *) * MAX_SUPPORT_RATES +
+ i * DLADM_STRSIZE;
+ }
+
+ status = do_get_rate_mod(linkid, modval, &modval_cnt);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ for (i = 0; i < modval_cnt; i++) {
+ if (strcasecmp(*prop_val, modval[i]) == 0) {
+ vdp->vd_val = (uint_t)(atof(*prop_val) * 2);
+ status = DLADM_STATUS_OK;
+
+ /*
+ * Does not need the caller to free the vdp->vd_val
+ */
+ *needfreep = B_FALSE;
break;
- } else {
- if (s != DLADM_STATUS_OK &&
- s != DLADM_STATUS_NOTSUP) {
- if (errprop != NULL)
- *errprop = pdp->pd_name;
- status = s;
- break;
- }
}
}
+ if (i == modval_cnt)
+ status = DLADM_STATUS_BADVAL;
+done:
+ free(buf);
+ return (status);
+}
- if (!found)
+static dladm_status_t
+do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf)
+{
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG));
+}
+
+static dladm_status_t
+do_get_channel_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+{
+ uint32_t channel;
+ wldp_t *gbuf;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ if ((status = do_get_phyconf(linkid, gbuf)) != DLADM_STATUS_OK)
+ goto done;
+
+ if (!i_dladm_wlan_convert_chan((wl_phy_conf_t *)gbuf->wldp_buf,
+ &channel)) {
status = DLADM_STATUS_NOTFOUND;
+ goto done;
+ }
+ (void) snprintf(*prop_val, DLADM_STRSIZE, "%u", channel);
+ *val_cnt = 1;
+
+done:
+ free(gbuf);
return (status);
}
-static boolean_t
-i_dladm_is_prop_temponly(const char *prop_name, char **errprop)
+static dladm_status_t
+do_get_powermode(datalink_id_t linkid, wldp_t *gbuf)
{
- int i;
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE));
+}
- for (i = 0; i < MAX_PROPS; i++) {
- prop_desc_t *pdp = &prop_table[i];
+static dladm_status_t
+do_get_powermode_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+{
+ wl_ps_mode_t *mode;
+ const char *s;
+ wldp_t *gbuf;
+ dladm_status_t status = DLADM_STATUS_OK;
- if (prop_name != NULL &&
- (strcasecmp(prop_name, pdp->pd_name) != 0))
- continue;
+ if ((gbuf = malloc(MAX_BUF_LEN)) == NULL)
+ return (DLADM_STATUS_NOMEM);
+
+ if ((status = do_get_powermode(linkid, gbuf)) != DLADM_STATUS_OK)
+ goto done;
+
+ mode = (wl_ps_mode_t *)(gbuf->wldp_buf);
+ switch (mode->wl_ps_mode) {
+ case WL_PM_AM:
+ s = "off";
+ break;
+ case WL_PM_MPS:
+ s = "max";
+ break;
+ case WL_PM_FAST:
+ s = "fast";
+ break;
+ default:
+ status = DLADM_STATUS_NOTFOUND;
+ goto done;
+ }
+ (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
+ *val_cnt = 1;
+
+done:
+ free(gbuf);
+ return (status);
+}
+
+static dladm_status_t
+do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm)
+{
+ wl_ps_mode_t ps_mode;
- if (errprop != NULL)
- *errprop = pdp->pd_name;
+ (void) memset(&ps_mode, 0xff, sizeof (ps_mode));
- if (pdp->pd_temponly)
- return (B_TRUE);
+ switch (*pm) {
+ case DLADM_WLAN_PM_OFF:
+ ps_mode.wl_ps_mode = WL_PM_AM;
+ break;
+ case DLADM_WLAN_PM_MAX:
+ ps_mode.wl_ps_mode = WL_PM_MPS;
+ break;
+ case DLADM_WLAN_PM_FAST:
+ ps_mode.wl_ps_mode = WL_PM_FAST;
+ break;
+ default:
+ return (DLADM_STATUS_NOTSUP);
}
+ return (i_dladm_wlan_set_ioctl(linkid, WL_POWER_MODE, &ps_mode,
+ sizeof (ps_mode)));
+}
- return (B_FALSE);
+/* ARGSUSED */
+static dladm_status_t
+do_set_powermode_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+{
+ dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
+ dladm_status_t status;
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ status = do_set_powermode(linkid, &powermode);
+
+ return (status);
+}
+
+static dladm_status_t
+do_get_radio(datalink_id_t linkid, wldp_t *gbuf)
+{
+ return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO));
+}
+
+static dladm_status_t
+do_get_radio_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+{
+ wl_radio_t radio;
+ const char *s;
+ wldp_t *gbuf;
+ 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)
+ goto done;
+
+ radio = *(wl_radio_t *)(gbuf->wldp_buf);
+ switch (radio) {
+ case B_TRUE:
+ s = "on";
+ break;
+ case B_FALSE:
+ s = "off";
+ break;
+ default:
+ status = DLADM_STATUS_NOTFOUND;
+ goto done;
+ }
+ (void) snprintf(*prop_val, DLADM_STRSIZE, "%s", s);
+ *val_cnt = 1;
+
+done:
+ free(gbuf);
+ return (status);
+}
+
+static dladm_status_t
+do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio)
+{
+ wl_radio_t r;
+
+ switch (*radio) {
+ case DLADM_WLAN_RADIO_ON:
+ r = B_TRUE;
+ break;
+ case DLADM_WLAN_RADIO_OFF:
+ r = B_FALSE;
+ break;
+ default:
+ return (DLADM_STATUS_NOTSUP);
+ }
+ return (i_dladm_wlan_set_ioctl(linkid, WL_RADIO, &r, sizeof (r)));
+}
+
+/* ARGSUSED */
+static dladm_status_t
+do_set_radio_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+{
+ dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
+ dladm_status_t status;
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVALCNT);
+
+ status = do_set_radio(linkid, &radio);
+
+ return (status);
+}
+
+static dladm_status_t
+i_dladm_set_linkprop_db(datalink_id_t linkid, const char *prop_name,
+ char **prop_val, uint_t val_cnt)
+{
+ char buf[MAXLINELEN];
+ int i;
+ dladm_conf_t conf;
+ dladm_status_t status;
+
+ status = dladm_read_conf(linkid, &conf);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ /*
+ * reset case.
+ */
+ if (val_cnt == 0) {
+ status = dladm_unset_conf_field(conf, prop_name);
+ if (status == DLADM_STATUS_OK)
+ status = dladm_write_conf(conf);
+ goto done;
+ }
+
+ buf[0] = '\0';
+ for (i = 0; i < val_cnt; i++) {
+ (void) strlcat(buf, prop_val[i], MAXLINELEN);
+ if (i != val_cnt - 1)
+ (void) strlcat(buf, ",", MAXLINELEN);
+ }
+
+ status = dladm_set_conf_field(conf, prop_name, DLADM_TYPE_STR, buf);
+ if (status == DLADM_STATUS_OK)
+ status = dladm_write_conf(conf);
+
+done:
+ dladm_destroy_conf(conf);
+ return (status);
+}
+
+static dladm_status_t
+i_dladm_get_linkprop_db(datalink_id_t linkid, const char *prop_name,
+ char **prop_val, uint_t *val_cntp)
+{
+ char buf[MAXLINELEN], *str;
+ uint_t cnt = 0;
+ dladm_conf_t conf;
+ dladm_status_t status;
+
+ status = dladm_read_conf(linkid, &conf);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ status = dladm_get_conf_field(conf, prop_name, buf, MAXLINELEN);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ str = strtok(buf, ",");
+ while (str != NULL) {
+ if (cnt == *val_cntp) {
+ status = DLADM_STATUS_TOOSMALL;
+ goto done;
+ }
+ (void) strlcpy(prop_val[cnt++], str, DLADM_PROP_VAL_MAX);
+ str = strtok(NULL, ",");
+ }
+
+ *val_cntp = cnt;
+
+done:
+ dladm_destroy_conf(conf);
+ return (status);
}
diff --git a/usr/src/lib/libdladm/common/llib-ldladm b/usr/src/lib/libdladm/common/llib-ldladm
index 467808e937..a6fc19b517 100644
--- a/usr/src/lib/libdladm/common/llib-ldladm
+++ b/usr/src/lib/libdladm/common/llib-ldladm
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -32,3 +32,5 @@
#include <libdlaggr.h>
#include <libdlwlan.h>
#include <libdlvnic.h>
+#include <libdlvlan.h>
+#include <libdlmgmt.h>
diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers
index 2672efc195..25ab048469 100644
--- a/usr/src/lib/libdladm/common/mapfile-vers
+++ b/usr/src/lib/libdladm/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -29,17 +29,18 @@ SUNWprivate_1.1 {
global:
dladm_info;
dladm_walk;
- dladm_hold_link;
- dladm_rele_link;
+ dladm_setzid;
+ dladm_getzid;
dladm_status2str;
dladm_linkstate2str;
dladm_linkduplex2str;
dladm_set_rootdir;
+ dladm_valid_linkname;
dladm_mac_walk;
dladm_init_linkprop;
- dladm_get_prop;
- dladm_set_prop;
- dladm_walk_prop;
+ dladm_get_linkprop;
+ dladm_set_linkprop;
+ dladm_walk_linkprop;
dladm_init_secobj;
dladm_get_secobj;
dladm_set_secobj;
@@ -47,9 +48,7 @@ SUNWprivate_1.1 {
dladm_walk_secobj;
dladm_secobjclass2str;
dladm_str2secobjclass;
- dladm_aggr_walk;
dladm_aggr_up;
- dladm_aggr_down;
dladm_aggr_add;
dladm_aggr_create;
dladm_aggr_delete;
@@ -64,15 +63,12 @@ SUNWprivate_1.1 {
dladm_aggr_str2lacptimer;
dladm_aggr_str2macaddr;
dladm_aggr_str2policy;
- dladm_wlan_walk;
+ dladm_aggr_info;
+ dladm_key2linkid;
dladm_wlan_scan;
dladm_wlan_connect;
dladm_wlan_disconnect;
dladm_wlan_get_linkattr;
- dladm_wlan_is_valid;
- dladm_wlan_set_prop;
- dladm_wlan_walk_prop;
- dladm_wlan_get_prop;
dladm_wlan_essid2str;
dladm_wlan_bssid2str;
dladm_wlan_secmode2str;
@@ -91,6 +87,32 @@ SUNWprivate_1.1 {
dladm_wlan_str2auth;
dladm_wlan_str2bsstype;
dladm_wlan_str2linkstatus;
+ dladm_vlan_create;
+ dladm_vlan_delete;
+ dladm_vlan_up;
+ dladm_vlan_info;
+ dladm_class2str;
+ dladm_media2str;
+ dladm_rename_link;
+ dladm_phys_info;
+ dladm_phys_delete;
+ dladm_dev2linkid;
+ dladm_linkid2legacyname;
+ dladm_create_datalink_id;
+ dladm_destroy_datalink_id;
+ dladm_remap_datalink_id;
+ dladm_up_datalink_id;
+ dladm_name2info;
+ dladm_datalink_id2info;
+ dladm_walk_datalink_id;
+ dladm_create_conf;
+ dladm_read_conf;
+ dladm_write_conf;
+ dladm_remove_conf;
+ dladm_destroy_conf;
+ dladm_get_conf_field;
+ dladm_set_conf_field;
+ dladm_unset_conf_field;
dladm_wlan_wpa_get_sr;
dladm_wlan_wpa_set_ie;
dladm_wlan_wpa_set_wpa;
@@ -100,8 +122,8 @@ SUNWprivate_1.1 {
dladm_vnic_create;
dladm_vnic_modify;
dladm_vnic_delete;
- dladm_vnic_walk_sys;
- dladm_vnic_mac_addr_str_to_type;
+ dladm_vnic_info;
+ dladm_vnic_str2macaddrtype;
local:
*;
diff --git a/usr/src/lib/libdladm/common/secobj.c b/usr/src/lib/libdladm/common/secobj.c
index 61a1cd72e5..7f17a38e4e 100644
--- a/usr/src/lib/libdladm/common/secobj.c
+++ b/usr/src/lib/libdladm/common/secobj.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -136,7 +136,7 @@ dladm_set_secobj(const char *obj_name, dladm_secobj_class_t class,
obj_val == NULL || obj_len == 0 || obj_len > DLD_SECOBJ_VAL_MAX)
return (DLADM_STATUS_BADARG);
- if ((flags & DLADM_OPT_TEMP) == 0)
+ if ((flags & DLADM_OPT_ACTIVE) == 0)
goto persist;
bzero(&secobj_set, sizeof (secobj_set));
@@ -154,7 +154,7 @@ dladm_set_secobj(const char *obj_name, dladm_secobj_class_t class,
if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
return (dladm_errno2status(errno));
- if (i_dladm_ioctl(fd, DLDIOCSECOBJSET, &secobj_set,
+ if (i_dladm_ioctl(fd, DLDIOC_SECOBJ_SET, &secobj_set,
sizeof (secobj_set)) < 0) {
status = dladm_errno2status(errno);
}
@@ -198,7 +198,7 @@ dladm_get_secobj(const char *obj_name, dladm_secobj_class_t *classp,
if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
return (dladm_errno2status(errno));
- if (i_dladm_ioctl(fd, DLDIOCSECOBJGET, &secobj_get,
+ if (i_dladm_ioctl(fd, DLDIOC_SECOBJ_GET, &secobj_get,
sizeof (secobj_get)) < 0)
status = dladm_errno2status(errno);
@@ -225,7 +225,7 @@ dladm_unset_secobj(const char *obj_name, uint_t flags)
flags == 0)
return (DLADM_STATUS_BADARG);
- if ((flags & DLADM_OPT_TEMP) == 0)
+ if ((flags & DLADM_OPT_ACTIVE) == 0)
goto persist;
bzero(&secobj_unset, sizeof (secobj_unset));
@@ -233,7 +233,7 @@ dladm_unset_secobj(const char *obj_name, uint_t flags)
if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
return (dladm_errno2status(errno));
- if (i_dladm_ioctl(fd, DLDIOCSECOBJUNSET, &secobj_unset,
+ if (i_dladm_ioctl(fd, DLDIOC_SECOBJ_UNSET, &secobj_unset,
sizeof (secobj_unset)) < 0)
status = dladm_errno2status(errno);
@@ -269,7 +269,7 @@ dladm_walk_secobj(void *arg, boolean_t (*func)(void *, const char *),
status = dladm_errno2status(errno);
goto done;
}
- if (i_dladm_ioctl(fd, DLDIOCSECOBJGET, secobj_getp,
+ if (i_dladm_ioctl(fd, DLDIOC_SECOBJ_GET, secobj_getp,
SECOBJ_BUFSZ) < 0) {
status = dladm_errno2status(errno);
goto done;
@@ -400,7 +400,7 @@ process_secobj_init(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
dladm_status_t *statusp)
{
*statusp = dladm_set_secobj(sip->si_name, *sip->si_classp, sip->si_val,
- *sip->si_lenp, DLADM_OPT_TEMP | DLADM_OPT_CREATE);
+ *sip->si_lenp, DLADM_OPT_ACTIVE | DLADM_OPT_CREATE);
return (B_TRUE);
}