/*
* 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
* 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
*/
/*
*/
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libdladm.h>
#include <libdlvnic.h>
#include <libdlvlan.h>
#include <libdllink.h>
#include <libintl.h>
#include <libnetcfg.h>
#include <libscf.h>
#include <libvrrpadm.h>
static boolean_t
{
char *s;
if (strcmp(s, SCF_STATE_STRING_ONLINE) == 0)
free(s);
}
return (isonline);
}
static vrrp_err_t
{
int i;
return (VRRP_SUCCESS);
if (scf_error() == SCF_ERROR_PERMISSION_DENIED)
return (VRRP_EPERM);
else
return (VRRP_ENOSVC);
}
/*
* Wait up to MAX_WAIT_TIME seconds for the VRRP service being brought
* up online
*/
for (i = 0; i < MAX_WAIT_TIME; i++) {
break;
(void) sleep(1);
}
if (i == MAX_WAIT_TIME)
return (VRRP_ENOSVC);
return (VRRP_SUCCESS);
}
/*
* Disable the VRRP service if there is no VRRP router left.
*/
static void
{
/*
* Get the number of the existing routers. If there is no routers
* left, disable the service.
*/
(void) smf_disable_instance(VRRP_SERVICE, 0);
}
}
static vrrp_err_t
{
return (VRRP_ESYS);
/*
* Set it to be non-blocking.
*/
/*
* Connect to vrrpd
*/
return (VRRP_ENOSVC);
}
/*
* Send the request
*/
continue;
} else if (len > 0) {
continue;
}
return (VRRP_ENOSVC);
}
/*
* Expect the ack, first get the error code.
*/
cur_size = 0;
while (cur_size < sizeof (vrrp_err_t)) {
sizeof (vrrp_err_t) - cur_size);
continue;
} else if (len > 0) {
continue;
}
return (VRRP_ESYS);
}
goto done;
/*
* The specific callback gets the rest of the information.
*/
done:
return (err);
}
/*
* public APIs
*/
const char *
{
switch (err) {
case VRRP_SUCCESS:
case VRRP_ENOMEM:
case VRRP_EINVALVRNAME:
case VRRP_ENOPRIM:
case VRRP_EEXIST:
case VRRP_ENOVIRT:
case VRRP_EIPADM:
case VRRP_EDLADM:
"failure"));
case VRRP_EDB:
case VRRP_EBADSTATE:
case VRRP_EVREXIST:
case VRRP_ETOOSMALL:
case VRRP_EINSTEXIST:
case VRRP_ENOTFOUND:
case VRRP_EINVALADDR:
case VRRP_EINVALAF:
case VRRP_EINVALLINK:
case VRRP_EPERM:
case VRRP_ESYS:
case VRRP_EAGAIN:
case VRRP_EALREADY:
case VRRP_ENOVNIC:
"created"));
case VRRP_ENOLINK:
case VRRP_ENOSVC:
"be enabled"));
case VRRP_EINVAL:
default:
}
}
const char *
{
switch (state) {
case VRRP_STATE_NONE:
case VRRP_STATE_INIT:
case VRRP_STATE_MASTER:
case VRRP_STATE_BACKUP:
default:
}
}
{
return (VRRP_EDLADM);
return (VRRP_ENOMEM);
}
return (VRRP_SUCCESS);
}
void
{
}
}
{
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*/
{
/*
* Enable the VRRP service if it is not already enabled.
*/
return (err);
if (err == VRRP_ENOSVC) {
/*
* This may be due to another process is deleting the last
* router and disabled the VRRP service, try again.
*/
goto again;
} else if (err != VRRP_SUCCESS) {
/*
* If router cannot be created, check if the VRRP service
* should be disabled, and disable if needed.
*/
}
return (err);
}
/*ARGSUSED*/
{
/*
* If the VRRP service is not enabled, we assume there is no router
* configured.
*/
if (!vrrp_svc_isonline(VRRP_SERVICE))
return (VRRP_ENOTFOUND);
return (VRRP_EINVAL);
if (err == VRRP_SUCCESS)
return (err);
}
/*ARGSUSED*/
{
/*
* If the VRRP service is not enabled, we assume there is no router
* configured.
*/
if (!vrrp_svc_isonline(VRRP_SERVICE))
return (VRRP_ENOTFOUND);
return (VRRP_EINVAL);
return (err);
}
/*ARGSUSED*/
{
/*
* If the VRRP service is not enabled, we assume there is no router
* configured.
*/
if (!vrrp_svc_isonline(VRRP_SERVICE))
return (VRRP_ENOTFOUND);
return (VRRP_EINVAL);
return (err);
}
/*ARGSUSED*/
{
/*
* If the VRRP service is not enabled, we assume there is no router
* configured.
*/
if (!vrrp_svc_isonline(VRRP_SERVICE))
return (VRRP_ENOTFOUND);
return (err);
}
typedef struct vrrp_cmd_list_arg {
char *vfl_names;
static vrrp_err_t
{
/*
* 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)) {
sizeof (vrrp_ret_list_t) - cur_size);
continue;
} else if (len > 0) {
continue;
}
return (VRRP_ESYS);
}
cur_size = 0;
continue;
} else if (len > 0) {
continue;
}
return (VRRP_ESYS);
}
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*/
{
return (VRRP_EINVAL);
return (VRRP_EINVAL);
}
/*
* If the service is not online, we assume there is no router
* configured.
*/
if (!vrrp_svc_isonline(VRRP_SERVICE)) {
*cnt = 0;
return (VRRP_SUCCESS);
}
return (err);
}
static vrrp_err_t
{
/*
* Expect the ack, first get the vrrp_ret_t.
*/
total = sizeof (vrrp_queryinfo_t);
continue;
} else if (len > 0) {
continue;
}
return (VRRP_ESYS);
}
/*
* Even if there is no IP virtual IP address, there is always
* space in the vrrp_queryinfo_t structure for one virtual
* IP address.
*/
continue;
} else if (len > 0) {
continue;
}
return (VRRP_ESYS);
}
return (VRRP_SUCCESS);
}
/*
* *vqp is allocated inside this function and must be freed by the caller.
*/
/*ARGSUSED*/
{
return (VRRP_EINVAL);
/*
* If the service is not online, we assume there is no router
* configured.
*/
if (!vrrp_svc_isonline(VRRP_SERVICE))
return (VRRP_ENOTFOUND);
/*
* Allocate enough room for virtual IPs.
*/
size = sizeof (vrrp_queryinfo_t);
err = VRRP_ENOMEM;
goto done;
}
if (err != VRRP_SUCCESS) {
goto done;
}
/*
* If the returned number of virtual IPs is greater than we expected,
* allocate more room and try again.
*/
goto again;
}
done:
return (err);
}
struct lookup_vnic_arg {
int lva_af;
};
/*
* 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.
*/
{
return (B_FALSE);
}
}
static int
{
int af;
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.
*/
{
return (VRRP_EINVAL);
}
if (class == DATALINK_CLASS_VLAN) {
DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) {
return (VRRP_EINVAL);
}
return (VRRP_EINVAL);
}
}
/*
* For now, Only VRRP over aggr and physical ethernet links is supported
*/
return (VRRP_EINVAL);
}
/*
*/
return (VRRP_SUCCESS);
}
return (VRRP_ENOVNIC);
}