diff options
| author | Cathy Zhou <Cathy.Zhou@Sun.COM> | 2009-11-17 09:17:48 -0800 |
|---|---|---|
| committer | Cathy Zhou <Cathy.Zhou@Sun.COM> | 2009-11-17 09:17:48 -0800 |
| commit | 1cb875ae88fb9463b368e725c2444776595895cb (patch) | |
| tree | c64970d43307210909e61a5fa2feec47f8548bf9 /usr/src/lib | |
| parent | fbe8965ded6a59e25279fffdb551ebe087980927 (diff) | |
| download | illumos-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')
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) |
