summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorCathy Zhou <Cathy.Zhou@Sun.COM>2009-11-17 09:17:48 -0800
committerCathy Zhou <Cathy.Zhou@Sun.COM>2009-11-17 09:17:48 -0800
commit1cb875ae88fb9463b368e725c2444776595895cb (patch)
treec64970d43307210909e61a5fa2feec47f8548bf9 /usr/src/lib
parentfbe8965ded6a59e25279fffdb551ebe087980927 (diff)
downloadillumos-joyent-1cb875ae88fb9463b368e725c2444776595895cb.tar.gz
PSARC/2008/693 VRRP
PSARC/2009/388 VRRP Update 6288572 RFE: VRRP implementation desired for Solaris
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/Makefile5
-rw-r--r--usr/src/lib/libdladm/common/libdladm_impl.h2
-rw-r--r--usr/src/lib/libdladm/common/libdlvlan.c7
-rw-r--r--usr/src/lib/libdladm/common/libdlvnic.c158
-rw-r--r--usr/src/lib/libdladm/common/libdlvnic.h9
-rw-r--r--usr/src/lib/libsecdb/auth_attr.txt1
-rw-r--r--usr/src/lib/libsecdb/help/auths/Makefile1
-rw-r--r--usr/src/lib/libsecdb/help/auths/NetworkVRRP.html41
-rw-r--r--usr/src/lib/libsecdb/help/profiles/Makefile1
-rw-r--r--usr/src/lib/libsecdb/help/profiles/RtNetVRRP.html36
-rw-r--r--usr/src/lib/libsecdb/prof_attr.txt3
-rw-r--r--usr/src/lib/libvrrpadm/Makefile63
-rw-r--r--usr/src/lib/libvrrpadm/Makefile.com52
-rw-r--r--usr/src/lib/libvrrpadm/amd64/Makefile29
-rw-r--r--usr/src/lib/libvrrpadm/common/libvrrpadm.c635
-rw-r--r--usr/src/lib/libvrrpadm/common/libvrrpadm.h355
-rw-r--r--usr/src/lib/libvrrpadm/common/llib-lvrrpadm30
-rw-r--r--usr/src/lib/libvrrpadm/common/mapfile-vers58
-rw-r--r--usr/src/lib/libvrrpadm/common/netinet/vrrp.h77
-rw-r--r--usr/src/lib/libvrrpadm/i386/Makefile28
-rw-r--r--usr/src/lib/libvrrpadm/libvrrpadm.xcl31
-rw-r--r--usr/src/lib/libvrrpadm/sparc/Makefile28
-rw-r--r--usr/src/lib/libvrrpadm/sparcv9/Makefile29
23 files changed, 1637 insertions, 42 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 12860d0ff9..0303dc7260 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -22,7 +22,6 @@
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#
include ../Makefile.master
@@ -252,6 +251,7 @@ SUBDIRS += \
libadutils \
libipmi \
libexacct/demo \
+ libvrrpadm \
libvscan \
libgrubmgmt \
smbsrv \
@@ -352,6 +352,7 @@ MSGSUBDIRS= \
libsum \
libtsol \
libuutil \
+ libvrrpadm \
libvscan \
libwanboot \
libwanbootutil \
@@ -464,6 +465,7 @@ HDRSUBDIRS= \
libtnfprobe \
libtsnet \
libtsol \
+ libvrrpadm \
libvolmgt \
libumem \
libunistat \
@@ -639,6 +641,7 @@ libexacct/demo: libexacct libproject libsocket libnsl
libtsalarm: libpcp
smbsrv: libsocket libnsl libmd libxnet libpthread librt \
libshare libidmap pkcs11 libsqlite
+libvrrpadm: libsocket libdladm
libvscan: libscf
scsi: libnvpair
mpapi: libpthread libdevinfo libsysevent libnvpair
diff --git a/usr/src/lib/libdladm/common/libdladm_impl.h b/usr/src/lib/libdladm/common/libdladm_impl.h
index f11ba5edd3..88d695a3c7 100644
--- a/usr/src/lib/libdladm/common/libdladm_impl.h
+++ b/usr/src/lib/libdladm/common/libdladm_impl.h
@@ -93,6 +93,8 @@ extern void dladm_free_args(dladm_arg_list_t *);
#define FMADDRSLOT "maddrslot" /* uint64_t */
#define FMADDRPREFIXLEN "maddrpreflen" /* uint64_t */
#define FHWRINGS "hwrings" /* boolean_t */
+#define FVRID "vrid" /* uint64_t */
+#define FVRAF "vraf" /* uint64_t */
/*
* Set for simlinks only
diff --git a/usr/src/lib/libdladm/common/libdlvlan.c b/usr/src/lib/libdladm/common/libdlvlan.c
index 0e21c235fa..943728dc03 100644
--- a/usr/src/lib/libdladm/common/libdlvlan.c
+++ b/usr/src/lib/libdladm/common/libdlvlan.c
@@ -19,12 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <libdlvlan.h>
#include <libdlvnic.h>
+#include <libvrrpadm.h>
/*
* VLAN Administration Library.
@@ -62,8 +63,8 @@ dladm_vlan_create(dladm_handle_t handle, const char *vlan, datalink_id_t linkid,
datalink_id_t *vlan_id_out)
{
return (dladm_vnic_create(handle, vlan, linkid,
- VNIC_MAC_ADDR_TYPE_PRIMARY, NULL, 0, NULL, 0, vid, vlan_id_out,
- proplist, flags | DLADM_OPT_VLAN));
+ VNIC_MAC_ADDR_TYPE_PRIMARY, NULL, 0, NULL, 0, vid, VRRP_VRID_NONE,
+ AF_UNSPEC, vlan_id_out, proplist, flags | DLADM_OPT_VLAN));
}
/*
diff --git a/usr/src/lib/libdladm/common/libdlvnic.c b/usr/src/lib/libdladm/common/libdlvnic.c
index 74a4339c45..a49f51a6ca 100644
--- a/usr/src/lib/libdladm/common/libdlvnic.c
+++ b/usr/src/lib/libdladm/common/libdlvnic.c
@@ -38,6 +38,7 @@
#include <net/if_dl.h>
#include <sys/dld.h>
#include <libdladm_impl.h>
+#include <libvrrpadm.h>
#include <libdllink.h>
#include <libdlbridge.h>
#include <libdlvnic.h>
@@ -64,8 +65,8 @@ static dladm_status_t
dladm_vnic_diag2status(vnic_ioc_diag_t ioc_diag)
{
switch (ioc_diag) {
- case VNIC_IOC_DIAG_MACADDR_INVALID:
- return (DLADM_STATUS_INVALIDMACADDR);
+ case VNIC_IOC_DIAG_NONE:
+ return (DLADM_STATUS_OK);
case VNIC_IOC_DIAG_MACADDRLEN_INVALID:
return (DLADM_STATUS_INVALIDMACADDRLEN);
case VNIC_IOC_DIAG_MACADDR_NIC:
@@ -88,8 +89,11 @@ dladm_vnic_diag2status(vnic_ioc_diag_t ioc_diag)
return (DLADM_STATUS_INVALID_MACMARGIN);
case VNIC_IOC_DIAG_NO_HWRINGS:
return (DLADM_STATUS_NO_HWRINGS);
+ case VNIC_IOC_DIAG_MACADDR_INVALID:
+ return (DLADM_STATUS_INVALIDMACADDR);
+ default:
+ return (DLADM_STATUS_FAILED);
}
- return (DLADM_STATUS_OK);
}
/*
@@ -110,6 +114,8 @@ i_dladm_vnic_create_sys(dladm_handle_t handle, dladm_vnic_attr_t *attr)
ioc.vc_mac_slot = attr->va_mac_slot;
ioc.vc_mac_prefix_len = attr->va_mac_prefix_len;
ioc.vc_vid = attr->va_vid;
+ ioc.vc_vrid = attr->va_vrid;
+ ioc.vc_af = attr->va_af;
ioc.vc_flags = attr->va_force ? VNIC_IOC_CREATE_FORCE : 0;
ioc.vc_flags |= attr->va_hwrings ? VNIC_IOC_CREATE_REQ_HWRINGS : 0;
@@ -174,6 +180,8 @@ i_dladm_vnic_info_active(dladm_handle_t handle, datalink_id_t linkid,
attrp->va_mac_slot = vnic->vn_mac_slot;
attrp->va_mac_prefix_len = vnic->vn_mac_prefix_len;
attrp->va_vid = vnic->vn_vid;
+ attrp->va_vrid = vnic->vn_vrid;
+ attrp->va_af = vnic->vn_af;
attrp->va_force = vnic->vn_force;
bail:
@@ -237,6 +245,20 @@ i_dladm_vnic_info_persist(dladm_handle_t handle, datalink_id_t linkid,
attrp->va_mac_addr_type = (vnic_mac_addr_type_t)u64;
+ if ((status = dladm_get_conf_field(handle, conf, FVRID,
+ &u64, sizeof (u64))) != DLADM_STATUS_OK) {
+ attrp->va_vrid = VRRP_VRID_NONE;
+ } else {
+ attrp->va_vrid = (vrid_t)u64;
+ }
+
+ if ((status = dladm_get_conf_field(handle, conf, FVRAF,
+ &u64, sizeof (u64))) != DLADM_STATUS_OK) {
+ attrp->va_af = AF_UNSPEC;
+ } else {
+ attrp->va_af = (int)u64;
+ }
+
status = dladm_get_conf_field(handle, conf, FMADDRLEN, &u64,
sizeof (u64));
attrp->va_mac_len = ((status == DLADM_STATUS_OK) ?
@@ -318,7 +340,8 @@ static dladm_vnic_addr_type_t addr_types[] = {
{"random", VNIC_MAC_ADDR_TYPE_RANDOM},
{"factory", VNIC_MAC_ADDR_TYPE_FACTORY},
{"auto", VNIC_MAC_ADDR_TYPE_AUTO},
- {"fixed", VNIC_MAC_ADDR_TYPE_PRIMARY}
+ {"fixed", VNIC_MAC_ADDR_TYPE_PRIMARY},
+ {"vrrp", VNIC_MAC_ADDR_TYPE_VRID}
};
#define NADDR_TYPES (sizeof (addr_types) / sizeof (dladm_vnic_addr_type_t))
@@ -352,13 +375,40 @@ dladm_vnic_str2macaddrtype(const char *str, vnic_mac_addr_type_t *val)
}
/*
+ * Based on the VRRP specification, the virtual router MAC address associated
+ * with a virtual router is an IEEE 802 MAC address in the following format:
+ *
+ * IPv4 case: 00-00-5E-00-01-{VRID} (in hex in internet standard bit-order)
+ *
+ * IPv6 case: 00-00-5E-00-02-{VRID} (in hex in internet standard bit-order)
+ */
+static dladm_status_t
+i_dladm_vnic_vrrp_mac(vrid_t vrid, int af, uint8_t *mac, uint_t maclen)
+{
+ if (maclen < ETHERADDRL || vrid < VRRP_VRID_MIN ||
+ vrid > VRRP_VRID_MAX || (af != AF_INET && af != AF_INET6)) {
+ return (DLADM_STATUS_BADARG);
+ }
+
+ mac[0] = mac[1] = mac[3] = 0x0;
+ mac[2] = 0x5e;
+ mac[4] = (af == AF_INET) ? 0x01 : 0x02;
+ mac[5] = vrid;
+ return (DLADM_STATUS_OK);
+}
+
+/*
* Create a new VNIC / VLAN. Update the configuration file and bring it up.
+ * The "vrid" and "af" arguments are only required if the mac_addr_type is
+ * VNIC_MAC_ADDR_TYPE_VRID. In that case, the MAC address will be caculated
+ * based on the above algorithm.
*/
dladm_status_t
dladm_vnic_create(dladm_handle_t handle, const char *vnic, datalink_id_t linkid,
- vnic_mac_addr_type_t mac_addr_type, uchar_t *mac_addr, int mac_len,
- int *mac_slot, uint_t mac_prefix_len, uint16_t vid,
- datalink_id_t *vnic_id_out, dladm_arg_list_t *proplist, uint32_t flags)
+ vnic_mac_addr_type_t mac_addr_type, uchar_t *mac_addr, uint_t mac_len,
+ int *mac_slot, uint_t mac_prefix_len, uint16_t vid, vrid_t vrid,
+ int af, datalink_id_t *vnic_id_out, dladm_arg_list_t *proplist,
+ uint32_t flags)
{
dladm_vnic_attr_t attr;
datalink_id_t vnic_id;
@@ -385,12 +435,31 @@ dladm_vnic_create(dladm_handle_t handle, const char *vnic, datalink_id_t linkid,
is_etherstub = (linkid == DATALINK_INVALID_LINKID);
- if (mac_len > MAXMACADDRLEN)
- return (DLADM_STATUS_INVALIDMACADDRLEN);
-
if (!dladm_vnic_macaddrtype2str(mac_addr_type))
return (DLADM_STATUS_INVALIDMACADDRTYPE);
+ if ((flags & DLADM_OPT_ANCHOR) == 0) {
+ if ((status = dladm_datalink_id2info(handle, linkid, NULL,
+ &class, &media, NULL, 0)) != DLADM_STATUS_OK)
+ return (status);
+
+ if (class == DATALINK_CLASS_VNIC ||
+ class == DATALINK_CLASS_VLAN)
+ return (DLADM_STATUS_BADARG);
+ } else {
+ /* it's an anchor VNIC */
+ if (linkid != DATALINK_INVALID_LINKID || vid != 0)
+ return (DLADM_STATUS_BADARG);
+ }
+
+ /*
+ * Only VRRP VNIC need VRID and address family specified.
+ */
+ if (mac_addr_type != VNIC_MAC_ADDR_TYPE_VRID &&
+ (af != AF_UNSPEC || vrid != VRRP_VRID_NONE)) {
+ return (DLADM_STATUS_BADARG);
+ }
+
/*
* If a random address might be generated, but no prefix
* was specified by the caller, use the default MAC address
@@ -404,20 +473,31 @@ dladm_vnic_create(dladm_handle_t handle, const char *vnic, datalink_id_t linkid,
bcopy(dladm_vnic_def_prefix, mac_addr, mac_prefix_len);
}
- if ((flags & DLADM_OPT_ANCHOR) == 0) {
- if ((status = dladm_datalink_id2info(handle, linkid, NULL,
- &class, &media, NULL, 0)) != DLADM_STATUS_OK)
- return (status);
-
- if (class == DATALINK_CLASS_VNIC ||
- class == DATALINK_CLASS_VLAN)
- return (DLADM_STATUS_BADARG);
- } else {
- /* it's an anchor VNIC */
- if (linkid != DATALINK_INVALID_LINKID || vid != 0)
+ /*
+ * If this is a VRRP VNIC, generate its MAC address using the given
+ * VRID and address family.
+ */
+ if (mac_addr_type == VNIC_MAC_ADDR_TYPE_VRID) {
+ /*
+ * VRRP VNICs must be created over ethernet data-links.
+ */
+ if (vrid < VRRP_VRID_MIN || vrid > VRRP_VRID_MAX ||
+ (af != AF_INET && af != AF_INET6) || mac_addr != NULL ||
+ mac_len != 0 || mac_prefix_len != 0 ||
+ (mac_slot != NULL && *mac_slot != -1) || is_etherstub ||
+ media != DL_ETHER) {
return (DLADM_STATUS_BADARG);
+ }
+ mac_len = ETHERADDRL;
+ mac_addr = tmp_addr;
+ status = i_dladm_vnic_vrrp_mac(vrid, af, mac_addr, mac_len);
+ if (status != DLADM_STATUS_OK)
+ return (status);
}
+ if (mac_len > MAXMACADDRLEN)
+ return (DLADM_STATUS_INVALIDMACADDRLEN);
+
if (vnic == NULL) {
flags |= DLADM_OPT_PREFIX;
(void) strlcpy(name, "vnic", sizeof (name));
@@ -458,6 +538,8 @@ dladm_vnic_create(dladm_handle_t handle, const char *vnic, datalink_id_t linkid,
bcopy(mac_addr, attr.va_mac_addr, mac_prefix_len);
attr.va_mac_prefix_len = mac_prefix_len;
attr.va_vid = vid;
+ attr.va_vrid = vrid;
+ attr.va_af = af;
attr.va_force = (flags & DLADM_OPT_FORCE) != 0;
attr.va_hwrings = (flags & DLADM_OPT_HWRINGS) != 0;
@@ -619,6 +701,18 @@ dladm_vnic_persist_conf(dladm_handle_t handle, const char *name,
if (status != DLADM_STATUS_OK)
goto done;
+ u64 = attrp->va_vrid;
+ status = dladm_set_conf_field(handle, conf, FVRID,
+ DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ u64 = attrp->va_af;
+ status = dladm_set_conf_field(handle, conf, FVRAF,
+ DLADM_TYPE_UINT64, &u64);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
if (attrp->va_mac_len != ETHERADDRL) {
u64 = attrp->va_mac_len;
status = dladm_set_conf_field(handle, conf, FMADDRLEN,
@@ -626,21 +720,11 @@ dladm_vnic_persist_conf(dladm_handle_t handle, const char *name,
if (status != DLADM_STATUS_OK)
goto done;
}
- }
-
- if (attrp->va_hwrings) {
- boolean_t hwrings = attrp->va_hwrings;
- status = dladm_set_conf_field(handle, conf, FHWRINGS,
- DLADM_TYPE_BOOLEAN, &hwrings);
- if (status != DLADM_STATUS_OK)
- goto done;
- }
- if (class != DATALINK_CLASS_VLAN) {
if (attrp->va_mac_slot != -1) {
u64 = attrp->va_mac_slot;
- status = dladm_set_conf_field(handle, conf, FMADDRSLOT,
- DLADM_TYPE_UINT64, &u64);
+ status = dladm_set_conf_field(handle, conf,
+ FMADDRSLOT, DLADM_TYPE_UINT64, &u64);
if (status != DLADM_STATUS_OK)
goto done;
}
@@ -661,6 +745,14 @@ dladm_vnic_persist_conf(dladm_handle_t handle, const char *name,
goto done;
}
+ if (attrp->va_hwrings) {
+ boolean_t hwrings = attrp->va_hwrings;
+ status = dladm_set_conf_field(handle, conf, FHWRINGS,
+ DLADM_TYPE_BOOLEAN, &hwrings);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ }
+
if (attrp->va_vid != 0) {
u64 = attrp->va_vid;
status = dladm_set_conf_field(handle, conf, FVLANID,
diff --git a/usr/src/lib/libdladm/common/libdlvnic.h b/usr/src/lib/libdladm/common/libdlvnic.h
index 9c93ceae3a..8b859f9e04 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 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -48,13 +48,15 @@ typedef struct dladm_vnic_attr {
uint16_t va_vid;
boolean_t va_force;
boolean_t va_hwrings;
+ vrid_t va_vrid;
+ int va_af;
mac_resource_props_t va_resource_props;
} dladm_vnic_attr_t;
extern dladm_status_t dladm_vnic_create(dladm_handle_t, const char *,
datalink_id_t, vnic_mac_addr_type_t, uchar_t *,
- int, int *, uint_t, uint16_t, datalink_id_t *,
- dladm_arg_list_t *, uint32_t);
+ uint_t, int *, uint_t, uint16_t, vrid_t, int,
+ datalink_id_t *, dladm_arg_list_t *, uint32_t);
extern dladm_status_t dladm_vnic_delete(dladm_handle_t, datalink_id_t,
uint32_t);
@@ -64,7 +66,6 @@ extern dladm_status_t dladm_vnic_info(dladm_handle_t, datalink_id_t,
extern dladm_status_t dladm_vnic_up(dladm_handle_t, datalink_id_t, uint32_t);
extern dladm_status_t dladm_vnic_str2macaddrtype(const char *,
vnic_mac_addr_type_t *);
-
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libsecdb/auth_attr.txt b/usr/src/lib/libsecdb/auth_attr.txt
index 8929f8a694..70ae120dab 100644
--- a/usr/src/lib/libsecdb/auth_attr.txt
+++ b/usr/src/lib/libsecdb/auth_attr.txt
@@ -97,6 +97,7 @@ solaris.network.ilb.enable:::Network ILB Enable Configuration::help=NetworkILBen
solaris.network.link.security:::Link Security::help=LinkSecurity.html
solaris.network.wifi.config:::Wifi Config::help=WifiConfig.html
solaris.network.wifi.wep:::Wifi Wep::help=WifiWep.html
+solaris.network.vrrp:::Administer VRRP::help=NetworkVRRP.html
#
solaris.print.:::Printer Management::help=PrintHeader.html
solaris.print.admin:::Administer Printer::help=PrintAdmin.html
diff --git a/usr/src/lib/libsecdb/help/auths/Makefile b/usr/src/lib/libsecdb/help/auths/Makefile
index 4c30de414d..d8d45feb77 100644
--- a/usr/src/lib/libsecdb/help/auths/Makefile
+++ b/usr/src/lib/libsecdb/help/auths/Makefile
@@ -124,6 +124,7 @@ HTMLENTS = \
NetworkILBconf.html \
NetworkILBenable.html \
NetworkHeader.html \
+ NetworkVRRP.html \
WifiConfig.html \
WifiWep.html \
LinkSecurity.html \
diff --git a/usr/src/lib/libsecdb/help/auths/NetworkVRRP.html b/usr/src/lib/libsecdb/help/auths/NetworkVRRP.html
new file mode 100644
index 0000000000..e641c0c9d8
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/auths/NetworkVRRP.html
@@ -0,0 +1,41 @@
+<html>
+
+<!--
+ Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License (the "License").
+ You may not use this file except in compliance with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+-->
+
+<head>
+<!--
+meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"
+-->
+</head>
+<body>
+When Administer VRRP is in the Authorizations Included column, it grants
+authorization to administrate the VRRP service, which is provided by the
+vrrpd(1M) daemon. In particularly, the user is allowed to create, delete,
+modify, disable, re-enable VRRP routers using the vrrpadm(1M) command.
+<p>
+Note, querying configuration and state information of a VRRP router using
+vrrpadm(1M) doesn't require the Administer VRRP authorization.
+</body>
+</html>
diff --git a/usr/src/lib/libsecdb/help/profiles/Makefile b/usr/src/lib/libsecdb/help/profiles/Makefile
index 654138efd6..1b71e02237 100644
--- a/usr/src/lib/libsecdb/help/profiles/Makefile
+++ b/usr/src/lib/libsecdb/help/profiles/Makefile
@@ -68,6 +68,7 @@ HTMLENTS = \
RtNetWifiMngmnt.html \
RtNetWifiSecure.html \
RtNetLinkSecure.html \
+ RtNetVRRP.html \
RtObAccessMngmnt.html \
RtPrntAdmin.html \
RtProcManagement.html \
diff --git a/usr/src/lib/libsecdb/help/profiles/RtNetVRRP.html b/usr/src/lib/libsecdb/help/profiles/RtNetVRRP.html
new file mode 100644
index 0000000000..18c94e178e
--- /dev/null
+++ b/usr/src/lib/libsecdb/help/profiles/RtNetVRRP.html
@@ -0,0 +1,36 @@
+<HTML>
+<!--
+ 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 2009 Sun Microsystems, Inc. All rights reserved.
+-- Use is subject to license terms.
+-->
+<head>
+<title></title>
+</head>
+<body>
+When Network VRRP is in the Rights Included column, it grants the
+right to administer the VRRP routers using the vrrpadm(1M) command.
+<p>
+If Network VRRP is grayed, then you are not entitled to Add or
+Remove this right.
+<p>
+</body>
+</html>
diff --git a/usr/src/lib/libsecdb/prof_attr.txt b/usr/src/lib/libsecdb/prof_attr.txt
index c20338c570..2aa812eb25 100644
--- a/usr/src/lib/libsecdb/prof_attr.txt
+++ b/usr/src/lib/libsecdb/prof_attr.txt
@@ -63,7 +63,8 @@ MMS User:::MMS Tape User:auths=solaris.mms.io.*;help=RtMMSUser.html
NDMP Management:::Manage the NDMP service:auths=solaris.smf.manage.ndmp,solaris.smf.value.ndmp,solaris.smf.read.ndmp;help=RtNdmpMngmnt.html
Network Autoconf:::Manage network auto-magic configuration via nwamd:auths=solaris.network.autoconf;help=RtNetAutoconf.html
Network ILB:::Manage ILB configuration via ilbadm:auths=solaris.network.ilb.config,solaris.network.ilb.enable;help=RtNetILB.html
-Network Management:::Manage the host and network configuration:auths=solaris.smf.manage.name-service-cache,solaris.smf.manage.bind,solaris.smf.value.routing,solaris.smf.manage.routing,solaris.smf.value.nwam,solaris.smf.manage.nwam,solaris.smf.manage.tnd,solaris.smf.manage.tnctl,solaris.smf.manage.wpa,solaris.smf.value.mdns,solaris.smf.manage.mdns,solaris.smf.manage.ilb;profiles=Network Wifi Management,Inetd Management,Network Autoconf,Network Observability;help=RtNetMngmnt.html
+Network VRRP:::Manage VRRP instances:auths=solaris.network.vrrp;help=RtNetVRRP.html
+Network Management:::Manage the host and network configuration:auths=solaris.smf.manage.name-service-cache,solaris.smf.manage.bind,solaris.smf.value.routing,solaris.smf.manage.routing,solaris.smf.value.nwam,solaris.smf.manage.nwam,solaris.smf.manage.tnd,solaris.smf.manage.tnctl,solaris.smf.manage.wpa,solaris.smf.value.mdns,solaris.smf.manage.mdns,solaris.smf.manage.ilb;profiles=Network Wifi Management,Inetd Management,Network Autoconf,Network VRRP,Network Observability;help=RtNetMngmnt.html
Network Observability:::Allow access to observability devices:privs=net_observability;help=RtNetObservability.html
Network Security:::Manage network and host security:auths=solaris.smf.manage.ssh,solaris.smf.value.tnd;profiles=Network Wifi Security,Network Link Security,Network IPsec Management;help=RtNetSecure.html
Network Wifi Management:::Manage wifi network configuration:auths=solaris.network.wifi.config;help=RtNetWifiMngmnt.html
diff --git a/usr/src/lib/libvrrpadm/Makefile b/usr/src/lib/libvrrpadm/Makefile
new file mode 100644
index 0000000000..03b80fa465
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/Makefile
@@ -0,0 +1,63 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include $(SRC)/lib/Makefile.lib
+
+HDRS = netinet/vrrp.h libvrrpadm.h
+HDRDIR = common
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+POFILE = libvrrpadm.po
+MSGFILES = common/libvrrpadm.c
+
+XGETFLAGS = -a -x libvrrpadm.xcl
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+install := TARGET = install
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRS)
+
+$(POFILE): pofile_MSGFILES
+
+_msg: $(MSGDOMAINPOFILE)
+
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/Makefile.msg.targ
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/libvrrpadm/Makefile.com b/usr/src/lib/libvrrpadm/Makefile.com
new file mode 100644
index 0000000000..db7f53a510
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/Makefile.com
@@ -0,0 +1,52 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+LIBRARY = libvrrpadm.a
+VERS = .1
+OBJECTS = libvrrpadm.o
+
+include ../../Makefile.lib
+
+# install this library in the root filesystem
+#include ../../Makefile.rootfs
+
+LIBS = $(DYNLIB) $(LINTLIB)
+LDLIBS += -lc -lsocket -ldladm
+
+SRCDIR = ../common
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I$(SRCDIR) -D_REENTRANT
+
+C99MODE = $(C99_ENABLE)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/lib/libvrrpadm/amd64/Makefile b/usr/src/lib/libvrrpadm/amd64/Makefile
new file mode 100644
index 0000000000..8680082937
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/amd64/Makefile
@@ -0,0 +1,29 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libvrrpadm/common/libvrrpadm.c b/usr/src/lib/libvrrpadm/common/libvrrpadm.c
new file mode 100644
index 0000000000..b2ca3f49c7
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/common/libvrrpadm.c
@@ -0,0 +1,635 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+#include <sys/varargs.h>
+#include <sys/vlan.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h> /* LIFNAMSIZ */
+#include <netinet/vrrp.h>
+#include <libdladm.h>
+#include <libdlvnic.h>
+#include <libdlvlan.h>
+#include <libdllink.h>
+#include <libintl.h>
+#include <libvrrpadm.h>
+
+typedef vrrp_err_t vrrp_cmd_func_t(int, void *);
+
+static vrrp_err_t
+vrrp_cmd_request(void *cmd, size_t csize, vrrp_cmd_func_t func, void *arg)
+{
+ struct sockaddr_un to;
+ int sock, flags;
+ size_t len, cur_size = 0;
+ vrrp_ret_t ret;
+ vrrp_err_t err;
+
+ if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ return (VRRP_ECMD);
+
+ /*
+ * Set it to be non-blocking.
+ */
+ flags = fcntl(sock, F_GETFL, 0);
+ (void) fcntl(sock, F_SETFL, (flags | O_NONBLOCK));
+
+ (void) memset(&to, 0, sizeof (to));
+ to.sun_family = AF_UNIX;
+ (void) strlcpy(to.sun_path, VRRPD_SOCKET, sizeof (to.sun_path));
+
+ /*
+ * Connect to vrrpd
+ */
+ if (connect(sock, (const struct sockaddr *)&to, sizeof (to)) < 0) {
+ (void) close(sock);
+ return (VRRP_ECMD);
+ }
+
+ /*
+ * Send the request
+ */
+ while (cur_size < csize) {
+ len = write(sock, (char *)cmd + cur_size, csize - cur_size);
+ if (len == (size_t)-1 && errno == EAGAIN) {
+ continue;
+ } else if (len > 0) {
+ cur_size += len;
+ continue;
+ }
+ (void) close(sock);
+ return (VRRP_ECMD);
+ }
+
+ /*
+ * Expect the ack, first get the error code.
+ */
+ cur_size = 0;
+ while (cur_size < sizeof (vrrp_err_t)) {
+ len = read(sock, (char *)&ret + cur_size,
+ sizeof (vrrp_err_t) - cur_size);
+
+ if (len == (size_t)-1 && errno == EAGAIN) {
+ continue;
+ } else if (len > 0) {
+ cur_size += len;
+ continue;
+ }
+ (void) close(sock);
+ return (VRRP_ECMD);
+ }
+
+ if ((err = ret.vr_err) != VRRP_SUCCESS)
+ goto done;
+
+ /*
+ * The specific callback gets the rest of the information.
+ */
+ if (func != NULL)
+ err = func(sock, arg);
+
+done:
+ (void) close(sock);
+ return (err);
+}
+
+/*
+ * public APIs
+ */
+const char *
+vrrp_err2str(vrrp_err_t err)
+{
+ switch (err) {
+ case VRRP_SUCCESS:
+ return (dgettext(TEXT_DOMAIN, "success"));
+ case VRRP_ENOMEM:
+ return (dgettext(TEXT_DOMAIN, "not enough memory"));
+ case VRRP_EINVALVRNAME:
+ return (dgettext(TEXT_DOMAIN, "invalid router name"));
+ case VRRP_ENOPRIM:
+ return (dgettext(TEXT_DOMAIN, "no primary IP"));
+ case VRRP_EEXIST:
+ return (dgettext(TEXT_DOMAIN, "already exists"));
+ case VRRP_ENOVIRT:
+ return (dgettext(TEXT_DOMAIN, "no virtual IPs"));
+ case VRRP_EIPADM:
+ return (dgettext(TEXT_DOMAIN, "ip configuration failure"));
+ case VRRP_EDLADM:
+ return (dgettext(TEXT_DOMAIN, "data-link configuration "
+ "failure"));
+ case VRRP_EDB:
+ return (dgettext(TEXT_DOMAIN, "configuration update error"));
+ case VRRP_EBADSTATE:
+ return (dgettext(TEXT_DOMAIN, "invalid state"));
+ case VRRP_EVREXIST:
+ return (dgettext(TEXT_DOMAIN, "VRRP router already exists"));
+ case VRRP_ETOOSMALL:
+ return (dgettext(TEXT_DOMAIN, "not enough space"));
+ case VRRP_EINSTEXIST:
+ return (dgettext(TEXT_DOMAIN, "router name already exists"));
+ case VRRP_ENOTFOUND:
+ return (dgettext(TEXT_DOMAIN, "VRRP router not found"));
+ case VRRP_ECMD:
+ return (dgettext(TEXT_DOMAIN, "failed to communicate to "
+ "vrrpd"));
+ case VRRP_EINVALADDR:
+ return (dgettext(TEXT_DOMAIN, "invalid IP address"));
+ case VRRP_EINVALAF:
+ return (dgettext(TEXT_DOMAIN, "invalid IP address family"));
+ case VRRP_EINVALLINK:
+ return (dgettext(TEXT_DOMAIN, "invalid data-link"));
+ case VRRP_EPERM:
+ return (dgettext(TEXT_DOMAIN, "permission denied"));
+ case VRRP_ESYS:
+ return (dgettext(TEXT_DOMAIN, "system error"));
+ case VRRP_EAGAIN:
+ return (dgettext(TEXT_DOMAIN, "try again"));
+ case VRRP_EALREADY:
+ return (dgettext(TEXT_DOMAIN, "operation already in progress"));
+ case VRRP_ENOVNIC:
+ return (dgettext(TEXT_DOMAIN, "VRRP VNIC has not been "
+ "created"));
+ case VRRP_ENOLINK:
+ return (dgettext(TEXT_DOMAIN, "the data-link does not exist"));
+ case VRRP_EINVAL:
+ default:
+ return (dgettext(TEXT_DOMAIN, "invalid argument"));
+ }
+}
+
+const char *
+vrrp_state2str(vrrp_state_t state)
+{
+ switch (state) {
+ case VRRP_STATE_NONE:
+ return (dgettext(TEXT_DOMAIN, "NONE"));
+ case VRRP_STATE_INIT:
+ return (dgettext(TEXT_DOMAIN, "INIT"));
+ case VRRP_STATE_MASTER:
+ return (dgettext(TEXT_DOMAIN, "MASTER"));
+ case VRRP_STATE_BACKUP:
+ return (dgettext(TEXT_DOMAIN, "BACKUP"));
+ default:
+ return (dgettext(TEXT_DOMAIN, "INVALID"));
+ }
+}
+
+vrrp_err_t
+vrrp_open(vrrp_handle_t *vh)
+{
+ dladm_handle_t dh;
+
+ if (dladm_open(&dh) != DLADM_STATUS_OK)
+ return (VRRP_EDLADM);
+
+ if ((*vh = malloc(sizeof (struct vrrp_handle))) == NULL) {
+ dladm_close(dh);
+ return (VRRP_ENOMEM);
+ }
+ (*vh)->vh_dh = dh;
+ return (VRRP_SUCCESS);
+}
+
+void
+vrrp_close(vrrp_handle_t vh)
+{
+ if (vh != NULL) {
+ dladm_close(vh->vh_dh);
+ free(vh);
+ }
+}
+
+boolean_t
+vrrp_valid_name(const char *name)
+{
+ const char *c;
+
+ /*
+ * The legal characters in a valid router name are:
+ * alphanumeric (a-z, A-Z, 0-9), underscore ('_'), and '.'.
+ */
+ for (c = name; *c != '\0'; c++) {
+ if ((isalnum(*c) == 0) && (*c != '_'))
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+/*ARGSUSED*/
+vrrp_err_t
+vrrp_create(vrrp_handle_t vh, vrrp_vr_conf_t *conf)
+{
+ vrrp_cmd_create_t cmd;
+ vrrp_err_t err;
+
+ cmd.vcc_cmd = VRRP_CMD_CREATE;
+ (void) memcpy(&cmd.vcc_conf, conf, sizeof (vrrp_vr_conf_t));
+
+ err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL);
+ return (err);
+}
+
+/*ARGSUSED*/
+vrrp_err_t
+vrrp_delete(vrrp_handle_t vh, const char *vn)
+{
+ vrrp_cmd_delete_t cmd;
+ vrrp_err_t err;
+
+ cmd.vcd_cmd = VRRP_CMD_DELETE;
+ if (strlcpy(cmd.vcd_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX)
+ return (VRRP_EINVAL);
+
+ err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL);
+ return (err);
+}
+
+/*ARGSUSED*/
+vrrp_err_t
+vrrp_enable(vrrp_handle_t vh, const char *vn)
+{
+ vrrp_cmd_enable_t cmd;
+ vrrp_err_t err;
+
+ cmd.vcs_cmd = VRRP_CMD_ENABLE;
+ if (strlcpy(cmd.vcs_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX)
+ return (VRRP_EINVAL);
+
+ err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL);
+ return (err);
+}
+
+/*ARGSUSED*/
+vrrp_err_t
+vrrp_disable(vrrp_handle_t vh, const char *vn)
+{
+ vrrp_cmd_disable_t cmd;
+ vrrp_err_t err;
+
+ cmd.vcx_cmd = VRRP_CMD_DISABLE;
+ if (strlcpy(cmd.vcx_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX)
+ return (VRRP_EINVAL);
+
+ err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL);
+ return (err);
+}
+
+/*ARGSUSED*/
+vrrp_err_t
+vrrp_modify(vrrp_handle_t vh, vrrp_vr_conf_t *conf, uint32_t mask)
+{
+ vrrp_cmd_modify_t cmd;
+ vrrp_err_t err;
+
+ cmd.vcm_cmd = VRRP_CMD_MODIFY;
+ cmd.vcm_mask = mask;
+ (void) memcpy(&cmd.vcm_conf, conf, sizeof (vrrp_vr_conf_t));
+
+ err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL);
+ return (err);
+}
+
+typedef struct vrrp_cmd_list_arg {
+ uint32_t *vfl_cnt;
+ char *vfl_names;
+} vrrp_cmd_list_arg_t;
+
+static vrrp_err_t
+vrrp_list_func(int sock, void *arg)
+{
+ vrrp_cmd_list_arg_t *list_arg = arg;
+ uint32_t in_cnt = *(list_arg->vfl_cnt);
+ uint32_t out_cnt;
+ vrrp_ret_list_t ret;
+ size_t len, cur_size = 0;
+
+ /*
+ * Get the rest of vrrp_ret_list_t besides the error code.
+ */
+ cur_size = sizeof (vrrp_err_t);
+ while (cur_size < sizeof (vrrp_ret_list_t)) {
+ len = read(sock, (char *)&ret + cur_size,
+ sizeof (vrrp_ret_list_t) - cur_size);
+
+ if (len == (size_t)-1 && errno == EAGAIN) {
+ continue;
+ } else if (len > 0) {
+ cur_size += len;
+ continue;
+ }
+ return (VRRP_ECMD);
+ }
+
+ *(list_arg->vfl_cnt) = out_cnt = ret.vrl_cnt;
+ out_cnt = (in_cnt <= out_cnt) ? in_cnt : out_cnt;
+ cur_size = 0;
+
+ while (cur_size < VRRP_NAME_MAX * out_cnt) {
+ len = read(sock, (char *)list_arg->vfl_names + cur_size,
+ VRRP_NAME_MAX * out_cnt - cur_size);
+
+ if (len == (size_t)-1 && errno == EAGAIN) {
+ continue;
+ } else if (len > 0) {
+ cur_size += len;
+ continue;
+ }
+ return (VRRP_ECMD);
+ }
+ return (VRRP_SUCCESS);
+}
+
+/*
+ * Looks up the vrrp instances that matches the given variable.
+ *
+ * If the given cnt is 0, names should be set to NULL. In this case, only
+ * the count of the matched instances is returned.
+ *
+ * If the given cnt is non-zero, caller must allocate "names" whose size
+ * is (cnt * VRRP_NAME_MAX).
+ *
+ * Return value: the current count of matched instances, and names will be
+ * points to the list of the current vrrp instances names. Note that
+ * only MIN(in_cnt, out_cnt) number of names will be returned.
+ */
+/*ARGSUSED*/
+vrrp_err_t
+vrrp_list(vrrp_handle_t vh, vrid_t vrid, const char *intf, int af,
+ uint32_t *cnt, char *names)
+{
+ vrrp_cmd_list_t cmd;
+ vrrp_err_t err;
+ vrrp_cmd_list_arg_t list_arg;
+
+ if ((cnt == NULL) || (*cnt != 0 && names == NULL))
+ return (VRRP_EINVAL);
+
+ cmd.vcl_ifname[0] = '\0';
+ if (intf != NULL && (strlcpy(cmd.vcl_ifname, intf,
+ LIFNAMSIZ) >= LIFNAMSIZ)) {
+ return (VRRP_EINVAL);
+ }
+
+ cmd.vcl_cmd = VRRP_CMD_LIST;
+ cmd.vcl_vrid = vrid;
+ cmd.vcl_af = af;
+
+ list_arg.vfl_cnt = cnt;
+ list_arg.vfl_names = names;
+
+ err = vrrp_cmd_request(&cmd, sizeof (cmd), vrrp_list_func, &list_arg);
+ return (err);
+}
+
+static vrrp_err_t
+vrrp_query_func(int sock, void *arg)
+{
+ vrrp_queryinfo_t *qinfo = arg;
+ size_t len, cur_size = 0, total;
+ uint32_t in_cnt = qinfo->show_va.va_vipcnt;
+ uint32_t out_cnt;
+
+ /*
+ * Expect the ack, first get the vrrp_ret_t.
+ */
+ total = sizeof (vrrp_queryinfo_t);
+ while (cur_size < total) {
+ len = read(sock, (char *)qinfo + cur_size, total - cur_size);
+ if (len == (size_t)-1 && errno == EAGAIN) {
+ continue;
+ } else if (len > 0) {
+ cur_size += len;
+ continue;
+ }
+ return (VRRP_ECMD);
+ }
+
+ out_cnt = qinfo->show_va.va_vipcnt;
+
+ /*
+ * Even if there is no IP virtual IP address, there is always
+ * space in the vrrp_queryinfo_t structure for one virtual
+ * IP address.
+ */
+ out_cnt = (out_cnt == 0) ? 1 : out_cnt;
+ out_cnt = (in_cnt < out_cnt ? in_cnt : out_cnt) - 1;
+ total += out_cnt * sizeof (vrrp_addr_t);
+
+ while (cur_size < total) {
+ len = read(sock, (char *)qinfo + cur_size, total - cur_size);
+ if (len == (size_t)-1 && errno == EAGAIN) {
+ continue;
+ } else if (len > 0) {
+ cur_size += len;
+ continue;
+ }
+ return (VRRP_ECMD);
+ }
+ return (VRRP_SUCCESS);
+}
+
+/*
+ * *vqp is allocated inside this function and must be freed by the caller.
+ */
+/*ARGSUSED*/
+vrrp_err_t
+vrrp_query(vrrp_handle_t vh, const char *vn, vrrp_queryinfo_t **vqp)
+{
+ vrrp_cmd_query_t cmd;
+ vrrp_queryinfo_t *qinfo;
+ vrrp_err_t err;
+ size_t size;
+ uint32_t vipcnt = 1;
+
+ if (strlcpy(cmd.vcq_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX)
+ return (VRRP_EINVAL);
+
+ cmd.vcq_cmd = VRRP_CMD_QUERY;
+
+ /*
+ * Allocate enough room for virtual IPs.
+ */
+again:
+ size = sizeof (vrrp_queryinfo_t);
+ size += (vipcnt == 0) ? 0 : (vipcnt - 1) * sizeof (vrrp_addr_t);
+ if ((qinfo = malloc(size)) == NULL) {
+ err = VRRP_ENOMEM;
+ goto done;
+ }
+
+ qinfo->show_va.va_vipcnt = vipcnt;
+ err = vrrp_cmd_request(&cmd, sizeof (cmd), vrrp_query_func, qinfo);
+ if (err != VRRP_SUCCESS) {
+ free(qinfo);
+ goto done;
+ }
+
+ /*
+ * If the returned number of virtual IPs is greater than we expected,
+ * allocate more room and try again.
+ */
+ if (qinfo->show_va.va_vipcnt > vipcnt) {
+ vipcnt = qinfo->show_va.va_vipcnt;
+ free(qinfo);
+ goto again;
+ }
+
+ *vqp = qinfo;
+
+done:
+ return (err);
+}
+
+struct lookup_vnic_arg {
+ vrid_t lva_vrid;
+ datalink_id_t lva_linkid;
+ int lva_af;
+ uint16_t lva_vid;
+ vrrp_handle_t lva_vh;
+ char lva_vnic[MAXLINKNAMELEN];
+};
+
+/*
+ * Is this a special VNIC interface created for VRRP? If so, return
+ * the linkid the VNIC was created on, the VRRP ID and address family.
+ */
+boolean_t
+vrrp_is_vrrp_vnic(vrrp_handle_t vh, datalink_id_t vnicid,
+ datalink_id_t *linkidp, uint16_t *vidp, vrid_t *vridp, int *afp)
+{
+ dladm_vnic_attr_t vattr;
+
+ if (dladm_vnic_info(vh->vh_dh, vnicid, &vattr, DLADM_OPT_ACTIVE) !=
+ DLADM_STATUS_OK) {
+ return (B_FALSE);
+ }
+
+ *vridp = vattr.va_vrid;
+ *vidp = vattr.va_vid;
+ *afp = vattr.va_af;
+ *linkidp = vattr.va_link_id;
+ return (vattr.va_vrid != VRRP_VRID_NONE);
+}
+
+static int
+lookup_vnic(dladm_handle_t dh, datalink_id_t vnicid, void *arg)
+{
+ vrid_t vrid;
+ uint16_t vid;
+ datalink_id_t linkid;
+ int af;
+ struct lookup_vnic_arg *lva = arg;
+
+ if (vrrp_is_vrrp_vnic(lva->lva_vh, vnicid, &linkid, &vid, &vrid,
+ &af) && lva->lva_vrid == vrid && lva->lva_linkid == linkid &&
+ lva->lva_vid == vid && lva->lva_af == af) {
+ if (dladm_datalink_id2info(dh, vnicid, NULL, NULL, NULL,
+ lva->lva_vnic, sizeof (lva->lva_vnic)) == DLADM_STATUS_OK) {
+ return (DLADM_WALK_TERMINATE);
+ }
+ }
+ return (DLADM_WALK_CONTINUE);
+}
+
+/*
+ * Given the primary link name, find the assoicated VRRP vnic name, if
+ * the vnic does not exist yet, return the linkid, vid of the primary link.
+ */
+vrrp_err_t
+vrrp_get_vnicname(vrrp_handle_t vh, vrid_t vrid, int af, char *link,
+ datalink_id_t *linkidp, uint16_t *vidp, char *vnic, size_t len)
+{
+ datalink_id_t linkid;
+ uint32_t flags;
+ uint16_t vid = VLAN_ID_NONE;
+ datalink_class_t class;
+ dladm_vlan_attr_t vlan_attr;
+ struct lookup_vnic_arg lva;
+ uint32_t media;
+
+ if ((strlen(link) == 0) || dladm_name2info(vh->vh_dh,
+ link, &linkid, &flags, &class, &media) !=
+ DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) {
+ return (VRRP_EINVAL);
+ }
+
+ if (class == DATALINK_CLASS_VLAN) {
+ if (dladm_vlan_info(vh->vh_dh, linkid, &vlan_attr,
+ DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) {
+ return (VRRP_EINVAL);
+ }
+ linkid = vlan_attr.dv_linkid;
+ vid = vlan_attr.dv_vid;
+ if ((dladm_datalink_id2info(vh->vh_dh, linkid, NULL,
+ &class, &media, NULL, 0)) != DLADM_STATUS_OK) {
+ return (VRRP_EINVAL);
+ }
+ }
+
+ /*
+ * For now, Only VRRP over aggr and physical ethernet links is supported
+ */
+ if ((class != DATALINK_CLASS_PHYS && class != DATALINK_CLASS_AGGR) ||
+ media != DL_ETHER) {
+ return (VRRP_EINVAL);
+ }
+
+ if (linkidp != NULL)
+ *linkidp = linkid;
+ if (vidp != NULL)
+ *vidp = vid;
+
+ /*
+ * Find the assoicated vnic with the given vrid/vid/af/linkid
+ */
+ lva.lva_vrid = vrid;
+ lva.lva_vid = vid;
+ lva.lva_af = af;
+ lva.lva_linkid = linkid;
+ lva.lva_vh = vh;
+ lva.lva_vnic[0] = '\0';
+
+ (void) dladm_walk_datalink_id(lookup_vnic, vh->vh_dh, &lva,
+ DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
+ if (strlen(lva.lva_vnic) != 0) {
+ (void) strlcpy(vnic, lva.lva_vnic, len);
+ return (VRRP_SUCCESS);
+ }
+
+ return (VRRP_ENOVNIC);
+}
diff --git a/usr/src/lib/libvrrpadm/common/libvrrpadm.h b/usr/src/lib/libvrrpadm/common/libvrrpadm.h
new file mode 100644
index 0000000000..9137de645d
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/common/libvrrpadm.h
@@ -0,0 +1,355 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBVRRPADM_H
+#define _LIBVRRPADM_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h> /* in(6)_addr_t */
+#include <arpa/inet.h>
+#include <net/if.h> /* LIFNAMSIZ */
+#include <limits.h>
+#include <netinet/vrrp.h>
+#include <syslog.h>
+#include <libdladm.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VRRP_NAME_MAX 32
+#define VRRPD_SOCKET "/var/run/vrrpd.socket"
+
+/*
+ * to store the IP addresses
+ */
+typedef struct vrrp_addr {
+ union {
+ struct sockaddr_in a4;
+ struct sockaddr_in6 a6;
+ } in;
+#define in4 in.a4
+#define in6 in.a6
+} vrrp_addr_t;
+
+/*
+ * VRRP instance (configuration information).
+ * Passed to vrrp_create(), returned by vrrp_query().
+ */
+typedef struct vrrp_vr_conf_s {
+ char vvc_name[VRRP_NAME_MAX]; /* VRRP router name */
+ char vvc_link[MAXLINKNAMELEN]; /* data-link name */
+ vrid_t vvc_vrid; /* VRID */
+ int vvc_af; /* IPv4/IPv6 */
+ int vvc_pri;
+ uint32_t vvc_adver_int; /* in ms */
+ boolean_t vvc_preempt;
+ boolean_t vvc_accept;
+ boolean_t vvc_enabled;
+} vrrp_vr_conf_t;
+
+/*
+ * VRRP state machine
+ */
+typedef enum {
+ VRRP_STATE_NONE = -1,
+ VRRP_STATE_INIT,
+ VRRP_STATE_MASTER,
+ VRRP_STATE_BACKUP
+} vrrp_state_t;
+
+/*
+ * VRRP status structure
+ * Returned by vrrp_query() as part of vrrp_queryinfo_t.
+ */
+typedef struct vrrp_statusinfo_s {
+ vrrp_state_t vs_state;
+ vrrp_state_t vs_prev_state;
+ struct timeval vs_st_time; /* timestamp of last state trans */
+} vrrp_stateinfo_t;
+
+/*
+ * The information obtained from peer's advertisements
+ * Returned by vrrp_query() as part of vrrp_queryinfo_t.
+ */
+typedef struct vrrp_peer_s {
+ vrrp_addr_t vp_addr; /* source IP addr of the message */
+ int vp_prio; /* priority in adv message */
+ struct timeval vp_time; /* timestamp of the adv message */
+ int vp_adver_int; /* adv interval in adv message */
+} vrrp_peer_t;
+
+/*
+ * Useful timer information, in ms
+ */
+typedef struct vrrp_timeinfo_s {
+ int vt_since_last_tran; /* time since last state transition */
+ int vt_since_last_adv; /* time since last advertisement */
+ int vt_master_down_intv; /* timer interval for backup to */
+ /* declare master down */
+} vrrp_timerinfo_t;
+
+/*
+ * Address information
+ */
+typedef struct vrrp_addrinfo_s {
+ char va_vnic[MAXLINKNAMELEN];
+ vrrp_addr_t va_primary;
+ uint32_t va_vipcnt;
+ vrrp_addr_t va_vips[1];
+} vrrp_addrinfo_t;
+
+/*
+ * VRRP instance configuration and run-time states information
+ * Returned by vrrp_query().
+ */
+typedef struct vrrp_queryinfo {
+ vrrp_vr_conf_t show_vi;
+ vrrp_stateinfo_t show_vs;
+ vrrp_peer_t show_vp;
+ vrrp_timerinfo_t show_vt;
+ vrrp_addrinfo_t show_va;
+} vrrp_queryinfo_t;
+
+/*
+ * flags sent with the VRRP_CMD_MODIFY command. Used in vrrp_setprop().
+ */
+#define VRRP_CONF_PRIORITY 0x01
+#define VRRP_CONF_INTERVAL 0x02
+#define VRRP_CONF_PREEMPT 0x04
+#define VRRP_CONF_ACCEPT 0x08
+
+/*
+ * Errors
+ */
+typedef enum {
+ VRRP_SUCCESS = 0,
+ VRRP_EINVAL, /* invalid parameter */
+ VRRP_EINVALVRNAME, /* invalid router name */
+ VRRP_ENOMEM, /* no memory */
+ VRRP_ENOVIRT, /* no virtual IP addresses */
+ VRRP_ENOPRIM, /* no primary IP address */
+ VRRP_ENOVNIC, /* no vnic created */
+ VRRP_ENOLINK, /* the link does not exist */
+ VRRP_EINVALLINK, /* invalid link */
+ VRRP_EINVALADDR, /* invalid IP address */
+ VRRP_EINVALAF, /* invalid IP address familty */
+ VRRP_EDB, /* configuration error */
+ VRRP_EPERM, /* permission denied */
+ VRRP_EBADSTATE, /* VRRP router in bad state */
+ VRRP_EVREXIST, /* <vrid, intf, af> three-tuple exists */
+ VRRP_EINSTEXIST, /* router name already exists */
+ VRRP_EEXIST, /* already exists */
+ VRRP_ENOTFOUND, /* vrrp router not found */
+ VRRP_ETOOSMALL, /* too small space */
+ VRRP_EAGAIN, /* Try again */
+ VRRP_EALREADY, /* already */
+ VRRP_EDLADM, /* dladm failure */
+ VRRP_EIPADM, /* ipadm failure */
+ VRRP_ESYS, /* system error */
+ VRRP_ECMD /* command request error */
+} vrrp_err_t;
+
+/*
+ * Internal commands used between vrrpadm and vrrpd.
+ */
+typedef enum {
+ VRRP_CMD_RETURN = 0,
+ VRRP_CMD_CREATE,
+ VRRP_CMD_DELETE,
+ VRRP_CMD_ENABLE,
+ VRRP_CMD_DISABLE,
+ VRRP_CMD_MODIFY,
+ VRRP_CMD_LIST,
+ VRRP_CMD_QUERY
+} vrrp_cmd_type_t;
+
+#define addr_len(af) ((af) == AF_INET ? sizeof (in_addr_t): sizeof (in6_addr_t))
+
+#define VRRPADDR_UNSPECIFIED(af, addr) \
+ (((af) == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED( \
+ &(addr)->in6.sin6_addr)) || ((af) == AF_INET && \
+ ((addr)->in4.sin_addr.s_addr == INADDR_ANY)))
+
+#define VRRPADDR2STR(af, addr, abuf, size, append) { \
+ char ap[INET6_ADDRSTRLEN]; \
+ \
+ if (VRRPADDR_UNSPECIFIED(af, addr)) { \
+ (void) strlcpy(ap, "--", INET6_ADDRSTRLEN); \
+ } else if ((af) == AF_INET) { \
+ (void) inet_ntop((af), &(addr)->in4.sin_addr, ap, \
+ INET6_ADDRSTRLEN); \
+ } else { \
+ (void) inet_ntop((af), &(addr)->in6.sin6_addr, ap, \
+ INET6_ADDRSTRLEN); \
+ } \
+ if (append) \
+ (void) strlcat(abuf, ap, size); \
+ else \
+ (void) strlcpy(abuf, ap, size); \
+}
+
+typedef struct vrrp_cmd_create_s {
+ uint32_t vcc_cmd;
+ vrrp_vr_conf_t vcc_conf;
+} vrrp_cmd_create_t;
+
+typedef struct vrrp_ret_create_s {
+ vrrp_err_t vrc_err;
+} vrrp_ret_create_t;
+
+typedef struct vrrp_cmd_delete_s {
+ uint32_t vcd_cmd;
+ char vcd_name[VRRP_NAME_MAX];
+} vrrp_cmd_delete_t;
+
+typedef struct vrrp_ret_delete_s {
+ vrrp_err_t vrd_err;
+} vrrp_ret_delete_t;
+
+typedef struct vrrp_cmd_enable_s {
+ uint32_t vcs_cmd;
+ char vcs_name[VRRP_NAME_MAX];
+} vrrp_cmd_enable_t;
+
+typedef struct vrrp_ret_enable_s {
+ vrrp_err_t vrs_err;
+} vrrp_ret_enable_t;
+
+typedef struct vrrp_cmd_disable_s {
+ uint32_t vcx_cmd;
+ char vcx_name[VRRP_NAME_MAX];
+} vrrp_cmd_disable_t;
+
+typedef struct vrrp_ret_disable_s {
+ vrrp_err_t vrx_err;
+} vrrp_ret_disable_t;
+
+typedef struct vrrp_cmd_modify_s {
+ uint32_t vcm_cmd;
+ uint32_t vcm_mask;
+ vrrp_vr_conf_t vcm_conf;
+} vrrp_cmd_modify_t;
+
+typedef struct vrrp_ret_modify_s {
+ vrrp_err_t vrm_err;
+} vrrp_ret_modify_t;
+
+typedef struct vrrp_cmd_list_s {
+ uint32_t vcl_cmd;
+ vrid_t vcl_vrid;
+ char vcl_ifname[LIFNAMSIZ];
+ int vcl_af;
+} vrrp_cmd_list_t;
+
+typedef struct vrrp_ret_list_s {
+ vrrp_err_t vrl_err;
+ uint32_t vrl_cnt;
+ /*
+ * When vrl_cnt is non-zero, the return structure will be followed
+ * by the list of router names, separated by '\0'. Its size will
+ * be vrl_cnt * VRRP_NAME_MAX.
+ */
+} vrrp_ret_list_t;
+
+typedef struct vrrp_cmd_query_s {
+ uint32_t vcq_cmd;
+ char vcq_name[VRRP_NAME_MAX];
+} vrrp_cmd_query_t;
+
+typedef struct vrrp_ret_query_s {
+ vrrp_err_t vrq_err;
+ vrrp_queryinfo_t vrq_qinfo;
+} vrrp_ret_query_t;
+
+/*
+ * Union of all VRRP commands
+ */
+typedef union vrrp_cmd_s {
+ uint32_t vc_cmd;
+ vrrp_cmd_create_t vc_cmd_create;
+ vrrp_cmd_delete_t vc_cmd_delete;
+ vrrp_cmd_enable_t vc_cmd_enable;
+ vrrp_cmd_disable_t vc_cmd_disable;
+ vrrp_cmd_modify_t vc_cmd_modify;
+ vrrp_cmd_list_t vc_cmd_list;
+} vrrp_cmd_t;
+
+/*
+ * Union of all VRRP replies of the VRRP commands
+ */
+typedef union vrrp_ret_s {
+ vrrp_err_t vr_err;
+ vrrp_ret_create_t vr_ret_create;
+ vrrp_ret_delete_t vr_ret_delete;
+ vrrp_ret_enable_t vr_ret_enable;
+ vrrp_ret_disable_t vr_ret_disable;
+ vrrp_ret_modify_t vr_ret_modify;
+ vrrp_ret_list_t vr_ret_list;
+ vrrp_ret_query_t vr_ret_query;
+} vrrp_ret_t;
+
+/*
+ * Public APIs
+ */
+struct vrrp_handle {
+ dladm_handle_t vh_dh;
+};
+typedef struct vrrp_handle *vrrp_handle_t;
+
+const char *vrrp_err2str(vrrp_err_t);
+const char *vrrp_state2str(vrrp_state_t);
+
+vrrp_err_t vrrp_open(vrrp_handle_t *);
+void vrrp_close(vrrp_handle_t);
+
+boolean_t vrrp_valid_name(const char *);
+
+vrrp_err_t vrrp_create(vrrp_handle_t, vrrp_vr_conf_t *);
+vrrp_err_t vrrp_delete(vrrp_handle_t, const char *);
+
+vrrp_err_t vrrp_enable(vrrp_handle_t, const char *);
+vrrp_err_t vrrp_disable(vrrp_handle_t, const char *);
+
+vrrp_err_t vrrp_modify(vrrp_handle_t, vrrp_vr_conf_t *, uint32_t);
+
+vrrp_err_t vrrp_query(vrrp_handle_t, const char *, vrrp_queryinfo_t **);
+
+vrrp_err_t vrrp_list(vrrp_handle_t, vrid_t, const char *, int,
+ uint32_t *, char *);
+
+boolean_t vrrp_is_vrrp_vnic(vrrp_handle_t, datalink_id_t,
+ datalink_id_t *, uint16_t *, vrid_t *, int *);
+
+vrrp_err_t vrrp_get_vnicname(vrrp_handle_t, vrid_t, int, char *,
+ datalink_id_t *, uint16_t *, char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBVRRPADM_H */
diff --git a/usr/src/lib/libvrrpadm/common/llib-lvrrpadm b/usr/src/lib/libvrrpadm/common/llib-lvrrpadm
new file mode 100644
index 0000000000..2e56d8a8ef
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/common/llib-lvrrpadm
@@ -0,0 +1,30 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <libvrrpadm.h>
+#include <netinet/vrrp.h>
diff --git a/usr/src/lib/libvrrpadm/common/mapfile-vers b/usr/src/lib/libvrrpadm/common/mapfile-vers
new file mode 100644
index 0000000000..b7acfccbb6
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/common/mapfile-vers
@@ -0,0 +1,58 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+SUNWprivate_1.1 {
+ global:
+ vrrp_close;
+ vrrp_create;
+ vrrp_delete;
+ vrrp_disable;
+ vrrp_enable;
+ vrrp_err2str;
+ vrrp_get_vnicname;
+ vrrp_is_vrrp_vnic;
+ vrrp_list;
+ vrrp_modify;
+ vrrp_open;
+ vrrp_query;
+ vrrp_state2str;
+ vrrp_valid_name;
+
+ local:
+ *;
+};
diff --git a/usr/src/lib/libvrrpadm/common/netinet/vrrp.h b/usr/src/lib/libvrrpadm/common/netinet/vrrp.h
new file mode 100644
index 0000000000..30cb8eeee5
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/common/netinet/vrrp.h
@@ -0,0 +1,77 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _VRRP_H
+#define _VRRP_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct vrrp_pkt_s {
+ uint8_t vp_vers_type;
+ uint8_t vp_vrid;
+ uint8_t vp_prio;
+ uint8_t vp_ipnum;
+ uint16_t vp_rsvd_adver_int;
+ uint16_t vp_chksum;
+ /* then follows <vp_ipnum> IPvX addresses */
+ /* then follows NO authentification data */
+} vrrp_pkt_t;
+
+#define IPPROTO_VRRP 112 /* IP protocol number */
+#define VRRP_AUTH_LEN 0 /* XXX length of a chunk of Auth Data */
+
+#define VRRP_IP_TTL 255 /* IPv4 TTL, IPv6 hop limit */
+#define VRRP_VERSION 3 /* current version */
+#define VRRP_PKT_ADVERT 1 /* packet type */
+#define VRRP_VER_MASK 0xf0 /* version mask */
+#define VRRP_TYPE_MASK 0x0f /* packet type mask */
+
+#define VRRP_PRI_OWNER 255 /* priority of IP address owner */
+#define VRRP_PRI_MIN 1 /* minimum priority */
+#define VRRP_PRIO_ZERO 0 /* stop participating VRRP */
+#define VRRP_PRI_DEFAULT VRRP_PRI_OWNER /* default priority */
+
+#define VRRP_VRID_NONE 0
+#define VRRP_VRID_MIN 1
+#define VRRP_VRID_MAX 255
+
+#define CENTISEC2MSEC(centisec) ((centisec) * 10)
+#define MSEC2CENTISEC(msec) ((msec) / 10)
+
+/* Max advertisement interval, in msec */
+#define VRRP_MAX_ADVER_INT_MIN CENTISEC2MSEC(1)
+#define VRRP_MAX_ADVER_INT_MAX CENTISEC2MSEC(4095) /* (2^12 -1) */
+#define VRRP_MAX_ADVER_INT_DFLT CENTISEC2MSEC(100) /* 1 sec */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VRRP_H */
diff --git a/usr/src/lib/libvrrpadm/i386/Makefile b/usr/src/lib/libvrrpadm/i386/Makefile
new file mode 100644
index 0000000000..c86be4377c
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/i386/Makefile
@@ -0,0 +1,28 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libvrrpadm/libvrrpadm.xcl b/usr/src/lib/libvrrpadm/libvrrpadm.xcl
new file mode 100644
index 0000000000..7df2efdf1c
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/libvrrpadm.xcl
@@ -0,0 +1,31 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+msgid "VRRP"
+msgid "vrrpd"
+msgid "VNIC"
+msgid "NONE"
+msgid "INIT"
+msgid "MASTER"
+msgid "BACKUP"
diff --git a/usr/src/lib/libvrrpadm/sparc/Makefile b/usr/src/lib/libvrrpadm/sparc/Makefile
new file mode 100644
index 0000000000..c86be4377c
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/sparc/Makefile
@@ -0,0 +1,28 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libvrrpadm/sparcv9/Makefile b/usr/src/lib/libvrrpadm/sparcv9/Makefile
new file mode 100644
index 0000000000..8680082937
--- /dev/null
+++ b/usr/src/lib/libvrrpadm/sparcv9/Makefile
@@ -0,0 +1,29 @@
+#
+# 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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)