ipadm_addr.c revision 8b88711aa8fd0a7b5c9ea1947bc568831e46190c
/*
* 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
*/
/*
*/
/*
* This file contains functions for address management such as creating
* an address, deleting an address, enabling an address, disabling an
* on an address object and listing address information
* for all addresses in active as well as persistent configuration.
*/
#include <netdb.h>
#include <string.h>
#include <strings.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <stropts.h>
#include <zone.h>
#include <fcntl.h>
#include <ctype.h>
#include <dhcpagent_util.h>
#include <dhcpagent_ipc.h>
#include <ipadm_ndpd.h>
#include <libdladm.h>
#include <libdllink.h>
#include <libdliptun.h>
#include <ifaddrs.h>
#include "libipadm_impl.h"
#define SIN6(a) ((struct sockaddr_in6 *)a)
#define SIN(a) ((struct sockaddr_in *)a)
uint32_t);
uint32_t);
const char *, nvlist_t **);
int *);
uint32_t);
uint32_t *);
static boolean_t i_ipadm_is_user_aobjname_valid(const char *);
/*
* Callback functions to retrieve property values from the kernel. These
* functions, when required, translate the values from the kernel to a format
* suitable for printing. They also retrieve DEFAULT, PERM and POSSIBLE values
* for a given property.
*/
/*
* Callback functions to set property values. These functions translate the
* values to a format suitable for kernel consumption, allocate the necessary
* ioctl buffers and then invoke ioctl().
*/
/* address properties description table */
};
/*
* Helper function that initializes the `ipadm_ifname', `ipadm_aobjname', and
* `ipadm_atype' fields of the given `ipaddr'.
*/
void
{
sizeof (ipaddr->ipadm_ifname));
sizeof (ipaddr->ipadm_aobjname));
}
/*
* Determine the permission of the property depending on whether it has a
*/
static ipadm_status_t
{
perm = 0;
/* insufficient buffer space */
return (IPADM_NO_BUFS);
}
return (IPADM_SUCCESS);
}
/*
* Given an addrobj with `ipadm_aobjname' filled in, i_ipadm_get_addrobj()
* retrieves the information necessary for any operation on the object,
* such as delete-addr, enable-addr, disable-addr, up-addr, down-addr,
* refresh-addr, get-addrprop or set-addrprop. The information include
* the logical interface number, address type, address family,
* the interface id (if the address type is IPADM_ADDR_IPV6_ADDRCONF) and
* the ipadm_flags that indicate if the address is present in
* active configuration or persistent configuration or both. If the address
* is not found, IPADM_NOTSUP is returned.
*/
{
int err = 0;
/* populate the door_call argument structure */
sizeof (larg.ia_aobjname));
if (err != 0)
return (ipadm_errno2status(err));
sizeof (ipaddr->ipadm_ifname));
sizeof (ipaddr->ipadm_intfid));
}
return (IPADM_SUCCESS);
}
/*
* Retrieves the static address (IPv4 or IPv6) for the given address object
* in `ipaddr' from persistent DB.
*/
static ipadm_status_t
{
char *name;
char *sname;
/*
* Get the address line in the nvlist `onvl' from ipmgmtd daemon.
*/
if (status != IPADM_SUCCESS)
return (status);
/*
* Walk through the nvlist `onvl' to extract the IPADM_NVP_IPV4ADDR
* or the IPADM_NVP_IPV6ADDR name-value pair.
*/
continue;
break;
}
goto fail;
break;
break;
}
}
goto fail;
}
return (IPADM_SUCCESS);
fail:
return (IPADM_NOTFOUND);
}
/*
* For the given `addrobj->ipadm_lifnum' and `addrobj->ipadm_af', this function
* fills in the address objname, the address type and the ipadm_flags.
*/
{
int err;
if (err != 0)
return (ipadm_errno2status(err));
sizeof (addrobj->ipadm_aobjname));
return (IPADM_SUCCESS);
}
/*
* Adds an addrobj to ipmgmtd daemon's aobjmap (active configuration).
* with the given name and logical interface number.
* This API is called by in.ndpd to add addrobjs when new prefixes or
* dhcpv6 addresses are configured.
*/
{
int err;
return (ipadm_errno2status(err));
}
/*
* Deletes an address object with given name and logical number from ipmgmtd
* daemon's aobjmap (active configuration). This API is called by in.ndpd to
* remove addrobjs when auto-configured prefixes or dhcpv6 addresses are
* removed.
*/
{
struct ipadm_addrobj_s aobj;
}
/*
* Gets all the addresses from active configuration and populates the
* address information in `addrinfo'.
*/
static ipadm_status_t
{
int sock;
struct sockaddr_in6 *sin6;
struct ipadm_addrobj_s ipaddr;
char *sep;
int lnum;
/* Get all the configured addresses */
return (ipadm_errno2status(errno));
/* Return if there is nothing to process. */
return (IPADM_SUCCESS);
lnum = 0;
*sep++ = '\0';
}
continue;
if (!(ipadm_flags & IPADM_OPT_ZEROADDR)) {
/*
* Do not list it if it is zero, unless
* it is under DHCP or has a non-zero
* destination address.
*/
continue;
}
}
/* Allocate and populate the current node in the list. */
goto fail;
/* Link to the list in `addrinfo'. */
else
goto fail;
goto fail;
goto fail;
sizeof (struct sockaddr_storage));
goto fail;
sizeof (struct sockaddr_storage));
goto fail;
}
/* Get the addrobj name stored for this logical interface. */
sizeof (ipaddr.ipadm_ifname));
/*
* Find address type from ifa_flags, if we could not get it
* from daemon.
*/
if (status == IPADM_SUCCESS) {
sizeof (curr->ia_aobjname));
} else if (flags & IFF_ADDRCONF) {
} else {
}
/*
* Populate the flags for the active configuration from the
* `ifa_flags'.
*/
if (flags & IFF_DUPLICATE)
else
} else {
if (flags & IFF_RUNNING) {
goto retry;
}
goto fail;
}
else
} else {
}
}
if (flags & IFF_UNNUMBERED)
if (flags & IFF_PRIVATE)
if (flags & IFF_TEMPORARY)
if (flags & IFF_DEPRECATED)
}
return (IPADM_SUCCESS);
fail:
/* On error, cleanup everything and return. */
return (ipadm_errno2status(errno));
}
/*
* From the given `name', i_ipadm_name2atype() deduces the address type
* and address family. If the `name' implies an address, it returns B_TRUE.
* Else, returns B_FALSE and leaves the output parameters unchanged.
*/
{
*type = IPADM_ADDR_DHCP;
} else {
}
return (is_addr);
}
/*
* Parses the given nvlist `nvl' for an address or an address property.
* The input nvlist must contain either an address or an address property.
* `ainfo' is an input as well as output parameter. When an address or an
* address property is found, `ainfo' is updated with the information found.
* Some of the fields may be already filled in by the calling function.
*
* `ia_sname' and `ia_dname'. Values for `ia_pflags' are obtained if the `nvl'
* contains an address property. `ia_sname', `ia_dname', and `ia_pflags' are
* obtained if `nvl' contains an address.
*/
static ipadm_status_t
{
char *name;
int err;
} else if (IPADM_PRIV_NVP(name)) {
continue;
} else {
}
if (err != 0)
return (ipadm_errno2status(err));
}
if (is_addr) {
/*
* We got an address from the nvlist `nvl'.
* Parse `nvladdr' and populate relevant information
* in `ainfo'.
*/
switch (atype) {
case IPADM_ADDR_STATIC:
}
/*
* For static addresses, we need to get the hostnames.
*/
if (err != 0)
return (ipadm_errno2status(err));
if (err == 0) {
}
break;
case IPADM_ADDR_DHCP:
case IPADM_ADDR_IPV6_ADDRCONF:
/*
* dhcp and addrconf address objects are always
* marked up when re-enabled.
*/
break;
default:
return (IPADM_FAILURE);
}
} else {
/*
* We got an address property from `nvl'. Parse the
* name and the property value. Update the `ainfo->ia_pflags'
* for the flags.
*/
}
}
return (IPADM_SUCCESS);
}
/*
* Parses the given nvlist `nvl' for an address or an address property.
* The input nvlist must contain either an address or an address property.
* `ainfo' is an input as well as output parameter. When an address or an
* address property is found, `ainfo' is updated with the information found.
* Some of the fields may be already filled in by the calling function,
* because of previous calls to i_ipadm_nvl2ainfo_active().
*
* Since the address object in `nvl' is also in the active configuration, the
* `ia_sname' and `ia_dname'.
*
* If this function returns an error, the calling function will take
* care of freeing the fields in `ainfo'.
*/
static ipadm_status_t
{
}
/*
* Parses the given nvlist `nvl' for an address or an address property.
* The input nvlist must contain either an address or an address property.
* `ainfo' is an input as well as output parameter. When an address or an
* address property is found, `ainfo' is updated with the information found.
* Some of the fields may be already filled in by the calling function,
* because of previous calls to i_ipadm_nvl2ainfo_persist().
*
* All the relevant fields in `ainfo' will be filled by this function based
* on what we find in `nvl'.
*
* If this function returns an error, the calling function will take
* care of freeing the fields in `ainfo'.
*/
static ipadm_status_t
{
char *name;
struct sockaddr_in6 *sin6;
int err;
if (status != IPADM_SUCCESS)
return (status);
} else {
}
if (err != 0)
return (ipadm_errno2status(err));
}
sizeof (ainfo->ia_aobjname));
return (IPADM_NO_MEMORY);
if (is_addr) {
/*
* We got an address from the nvlist `nvl'.
* Parse `nvladdr' and populate `ifa->ifa_addr'.
*/
return (IPADM_NO_MEMORY);
switch (atype) {
case IPADM_ADDR_STATIC:
break;
case IPADM_ADDR_DHCP:
break;
case IPADM_ADDR_IPV6_ADDRCONF:
return (IPADM_NO_MEMORY);
&plen);
if (err != 0)
return (ipadm_errno2status(err));
return (IPADM_NO_MEMORY);
return (ipadm_errno2status(err));
break;
default:
return (IPADM_FAILURE);
}
} else {
/*
* If a prefixlen was found, update the
* `ainfo->ia_ifa.ifa_netmask'.
*/
return (IPADM_NO_MEMORY);
/*
* Address property lines always follow the address
* line itself in the persistent db. We must have
* found a valid `ainfo->ia_ifa.ifa_addr' by now.
*/
ifa->ifa_netmask);
if (err != 0)
return (ipadm_errno2status(err));
}
}
return (IPADM_SUCCESS);
}
/*
* Retrieves all addresses from active config and appends to it the
* addresses that are found only in persistent config. In addition,
* it updates the persistent fields for each address from information
* found in persistent config. The output parameter `addrinfo' contains
* complete information regarding all addresses in active as well as
* persistent config.
*/
static ipadm_status_t
{
char *aobjname;
/* Get all addresses from active config. */
if (status != IPADM_SUCCESS)
goto fail;
/* Get all addresses from persistent config. */
/*
* If no address was found in persistent config, just
* return what we found in active config.
*/
if (status == IPADM_NOTFOUND) {
/*
* If nothing was found neither active nor persistent
* config, this means that the interface does not exist,
* if one was provided in `ifname'.
*/
return (IPADM_ENXIO);
return (IPADM_SUCCESS);
}
/* In case of any other error, cleanup and return. */
if (status != IPADM_SUCCESS)
goto fail;
/* we append to make sure, loopback addresses are first */
;
}
/*
* `onvl' will contain all the address lines from the db. Each line
* could contain the address itself or an address property. Addresses
* and address properties are found in separate lines.
*
* If an address A was found in active, we will already have `ainfo',
* and it is present in persistent configuration as well, we need to
* update `ainfo' with persistent information (`ia_pflags).
* For each address B found only in persistent configuration,
* append the address to the list with the address info for B from
* `onvl'.
*/
continue;
&aobjname) != 0)
continue;
break;
}
/*
* We did not find this address object in `ainfo'.
* This means that the address object exists only
* in the persistent configuration. Get its
* details and append to `ainfo'.
*/
goto fail;
else
}
/*
* Fill relevant fields of `curr' from the persistent info
* in `nvladdr'. Call the appropriate function based on the
* `ia_state' value.
*/
else
if (status != IPADM_SUCCESS)
goto fail;
}
return (status);
fail:
/* On error, cleanup and return. */
return (status);
}
/*
* Callback function that sets the property `prefixlen' on the address
* object in `arg' to the value in `pval'.
*/
/* ARGSUSED */
static ipadm_status_t
{
struct sockaddr_storage netmask;
int err, s;
char *end;
return (IPADM_NOTSUP);
errno = 0;
return (IPADM_INVALID_ARG);
return (IPADM_INVALID_ARG);
return (ipadm_errno2status(err));
return (ipadm_errno2status(errno));
/* now, change the broadcast address to reflect the prefixlen */
/*
* get the interface address and set it, this should reset
* the broadcast address.
*/
}
return (IPADM_SUCCESS);
}
/*
* Callback function that sets the given value `pval' to one of the
* properties among `deprecated', `private', and `transmit' as defined in
* `pdp', on the address object in `arg'.
*/
/* ARGSUSED */
static ipadm_status_t
{
return (IPADM_NOTSUP);
else
return (IPADM_INVALID_ARG);
if (on)
else
if (on)
else
if (on)
else
} else {
return (IPADM_PROP_UNKNOWN);
}
}
/*
* Callback function that sets the property `zone' on the address
* object in `arg' to the value in `pval'.
*/
/* ARGSUSED */
static ipadm_status_t
{
int s;
/*
* To modify the zone assignment such that it persists across
* reboots, zonecfg(1M) must be used.
*/
if (flags & IPADM_OPT_PERSIST) {
return (IPADM_NOTSUP);
} else if (flags & IPADM_OPT_ACTIVE) {
/* put logical interface into all zones */
} else {
/* zone must be ready or running */
return (ipadm_errno2status(errno));
}
} else {
return (IPADM_INVALID_ARG);
}
return (ipadm_errno2status(errno));
return (IPADM_SUCCESS);
}
/*
* Callback function that gets the property `broadcast' for the address
* object in `arg'.
*/
/* ARGSUSED */
static ipadm_status_t
{
struct sockaddr_in *sin;
if (status != IPADM_SUCCESS)
return (status);
if (!(ifflags & IFF_BROADCAST)) {
buf[0] = '\0';
return (IPADM_SUCCESS);
}
}
switch (valtype) {
case MOD_PROP_DEFAULT: {
struct sockaddr_storage mask;
char val[MAXPROPVALLEN];
int err;
struct sockaddr_in *sin;
/*
* Since the address is unknown we cannot
* obtain default prefixlen
*/
buf[0] = '\0';
return (IPADM_SUCCESS);
}
/*
* For the static address, we get the address from the
* persistent db.
*/
if (status != IPADM_SUCCESS)
return (status);
} else {
/*
* If the address object is active, we retrieve the
* address from kernel.
*/
return (ipadm_errno2status(errno));
}
/*
* For default broadcast address, get the address and the
* default prefixlen for that address and then compute the
* broadcast address.
*/
if (status != IPADM_SUCCESS)
return (status);
return (ipadm_errno2status(err));
break;
}
case MOD_PROP_ACTIVE:
return (ipadm_errno2status(errno));
} else {
}
break;
default:
return (IPADM_INVALID_ARG);
}
/* insufficient buffer space */
return (IPADM_NO_BUFS);
}
return (IPADM_SUCCESS);
}
/*
* Callback function that retrieves the value of the property `prefixlen'
* for the address object in `arg'.
*/
/* ARGSUSED */
static ipadm_status_t
{
int s;
if (status != IPADM_SUCCESS) {
return (status);
} else if (lifflags & IFF_POINTOPOINT) {
buf[0] = '\0';
return (status);
}
}
switch (valtype) {
case MOD_PROP_POSSIBLE:
else
break;
case MOD_PROP_DEFAULT:
/*
* For static addresses, we retrieve the address
* from kernel if it is active.
*/
return (ipadm_errno2status(errno));
if (status != IPADM_SUCCESS)
return (status);
/*
* Since the address is unknown we cannot
* obtain default prefixlen
*/
buf[0] = '\0';
return (IPADM_SUCCESS);
} else {
/*
* If not in active config, we use the address
* from persistent store.
*/
if (status != IPADM_SUCCESS)
return (status);
if (status != IPADM_SUCCESS)
return (status);
}
break;
case MOD_PROP_ACTIVE:
return (ipadm_errno2status(errno));
break;
default:
return (IPADM_INVALID_ARG);
}
/* insufficient buffer space */
return (IPADM_NO_BUFS);
}
return (IPADM_SUCCESS);
}
/*
* Callback function that retrieves the value of one of the properties
* among `deprecated', `private', and `transmit' for the address object
* in `arg'.
*/
/* ARGSUSED */
static ipadm_status_t
{
switch (valtype) {
case MOD_PROP_DEFAULT:
} else {
return (IPADM_PROP_UNKNOWN);
}
break;
case MOD_PROP_ACTIVE:
/*
* If the address is present in active configuration, we
* retrieve it from kernel to get the property value.
* Else, there is no value to return.
*/
if (status != IPADM_SUCCESS)
return (status);
break;
default:
return (IPADM_INVALID_ARG);
}
/* insufficient buffer space */
}
return (status);
}
/*
* Callback function that retrieves the value of the property `zone'
* for the address object in `arg'.
*/
/* ARGSUSED */
static ipadm_status_t
{
char zone_name[ZONENAME_MAX];
int s;
if (getzoneid() != GLOBAL_ZONEID) {
buf[0] = '\0';
return (IPADM_SUCCESS);
}
/*
* we are in global zone. See if the lifname is assigned to shared-ip
* zone or global zone.
*/
switch (valtype) {
case MOD_PROP_DEFAULT:
sizeof (zone_name)) > 0)
else
return (ipadm_errno2status(errno));
break;
case MOD_PROP_ACTIVE:
return (ipadm_errno2status(errno));
sizeof (zone_name)) < 0) {
return (ipadm_errno2status(errno));
} else {
}
break;
default:
return (IPADM_INVALID_ARG);
}
/* insufficient buffer space */
return (IPADM_NO_BUFS);
}
return (IPADM_SUCCESS);
}
static ipadm_prop_desc_t *
i_ipadm_getpropdesc(const char *pname)
{
int i;
return (&ipadm_addrprop_table[i]);
}
return (NULL);
}
/*
* Gets the value of the given address property `pname' for the address
* object with name `aobjname'.
*/
{
struct ipadm_addrobj_s ipaddr;
return (IPADM_INVALID_ARG);
}
/* find the property in the property description table */
return (IPADM_PROP_UNKNOWN);
/*
* For the given aobjname, get the addrobj it represents and
* retrieve the property value for that object.
*/
return (status);
return (IPADM_NOTSUP);
/*
* Call the appropriate callback function to based on the field
* that was asked for.
*/
switch (valtype) {
case IPADM_OPT_PERM:
break;
case IPADM_OPT_ACTIVE:
buf[0] = '\0';
} else {
}
break;
case IPADM_OPT_DEFAULT:
break;
case IPADM_OPT_POSSIBLE:
break;
}
buf[0] = '\0';
break;
case IPADM_OPT_PERSIST:
&ipaddr);
break;
default:
break;
}
return (status);
}
/*
* Sets the value of the given address property `pname' to `pval' for the
* address object with name `aobjname'.
*/
{
struct ipadm_addrobj_s ipaddr;
char defbuf[MAXPROPVALLEN];
/* Check for solaris.network.interface.config authorization */
if (!ipadm_check_auth())
return (IPADM_EAUTH);
pflags == IPADM_OPT_PERSIST ||
return (IPADM_INVALID_ARG);
}
/* find the property in the property description table */
return (IPADM_PROP_UNKNOWN);
return (IPADM_NOTSUP);
return (IPADM_INVALID_ARG);
}
/*
* For the given aobjname, get the addrobj it represents and
* set the property value for that object.
*/
return (status);
return (IPADM_OP_DISABLE_OBJ);
/* Persistent operation not allowed on a temporary object. */
if ((pflags & IPADM_OPT_PERSIST) &&
return (IPADM_TEMPORARY_OBJ);
/*
* Currently, setting an address property on an address object of type
* IPADM_ADDR_IPV6_ADDRCONF is not supported. Supporting it involves
* in.ndpd retrieving the address properties from ipmgmtd for given
* address object and then setting them on auto-configured addresses,
* whenever in.ndpd gets a new prefix. This will be supported in
* future releases.
*/
return (IPADM_NOTSUP);
/*
* Setting an address property on an address object that is
* not present in active configuration is not supported.
*/
return (IPADM_NOTSUP);
if (reset) {
/*
* If we were asked to reset the value, we need to fetch
* the default value and set the default value.
*/
if (status != IPADM_SUCCESS)
return (status);
}
/* set the user provided or default property value */
if (status != IPADM_SUCCESS)
return (status);
/*
* If IPADM_OPT_PERSIST was set in `flags', we need to store
* property and its value in persistent DB.
*/
if (pflags & IPADM_OPT_PERSIST) {
pflags);
}
return (status);
}
/*
* Remove the address specified by the address object in `addr'
* from kernel. If the address is on a non-zero logical interface, we do a
* SIOCLIFREMOVEIF, otherwise we set the address to INADDR_ANY for IPv4 or
* :: for IPv6.
*/
{
int sock;
if (addr->ipadm_lifnum == 0) {
/*
* Fake the deletion of the 0'th address by
* clearing IFF_UP and setting it to as 0.0.0.0 or ::.
*/
if (status != IPADM_SUCCESS)
return (status);
return (ipadm_errno2status(errno));
return (ipadm_errno2status(errno));
return (ipadm_errno2status(errno));
}
return (IPADM_SUCCESS);
}
/*
* Extracts the IPv6 address from the nvlist in `nvl'.
*/
{
uint_t n;
return (IPADM_NOTFOUND);
assert(n == 16);
return (IPADM_SUCCESS);
}
/*
* Used to validate the given addrobj name string. Length of `aobjname'
* cannot exceed IPADM_AOBJ_USTRSIZ. `aobjname' should start with an
* alphabetic character and it can only contain alphanumeric characters.
*/
static boolean_t
i_ipadm_is_user_aobjname_valid(const char *aobjname)
{
const char *cp;
return (B_FALSE);
}
;
return (*cp == '\0');
}
/*
* Computes the prefixlen for the given `addr' based on the netmask found using
* the order specified in /etc/nsswitch.conf. If not found, then the
* prefixlen is computed using the Classful subnetting semantics defined
* in RFC 791 for IPv4 and RFC 4291 for IPv6.
*/
static ipadm_status_t
{
struct sockaddr_storage mask;
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin;
switch (af) {
case AF_INET:
m->sin_family = AF_INET;
break;
case AF_INET6:
prefixlen = 10;
else
prefixlen = 64;
break;
default:
return (IPADM_INVALID_ARG);
}
return (IPADM_SUCCESS);
}
static ipadm_status_t
struct sockaddr_storage *ss)
{
int rc;
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin;
if (rc != 0) {
if (rc == EAI_NONAME)
return (IPADM_BAD_ADDR);
else
return (IPADM_FAILURE);
}
/* maps to more than one hostname */
return (IPADM_BAD_HOSTNAME);
}
/* LINTED E_BAD_PTR_CAST_ALIGN */
if (is_mapped) {
/* LINTED E_BAD_PTR_CAST_ALIGN */
} else {
}
return (IPADM_SUCCESS);
}
/*
* This takes a static address string <addr>[/<mask>] or a hostname
* and maps it to a single numeric IP address, consulting DNS if
* hostname was provided. If a specific address family was requested,
* an error is returned if the given hostname does not map to an address
* of the given family. Note that this function returns failure
* if the name maps to more than one IP address.
*/
{
char *prefixlenstr;
char *endp;
/*
* We use (NI_MAXHOST + 5) because the longest possible
* astr will have (NI_MAXHOST + '/' + {a maximum of 32 for IPv4
* or a maximum of 128 for IPv6 + '\0') chars
*/
*prefixlenstr++ = '\0';
errno = 0;
return (IPADM_INVALID_ARG);
return (IPADM_INVALID_ARG);
}
if (status == IPADM_SUCCESS) {
sizeof (ipaddr->ipadm_static_aname));
}
return (status);
}
/*
* Set up tunnel destination address in ipaddr by contacting DNS.
* The function works similar to ipadm_set_addr().
* The dst_addr must resolve to exactly one address. IPADM_BAD_ADDR is returned
* if dst_addr resolves to more than one address. The caller has to verify
* that ipadm_static_addr and ipadm_static_dst_addr have the same ss_family
*/
{
/* mask lengths are not meaningful for point-to-point interfaces. */
return (IPADM_BAD_ADDR);
if (status == IPADM_SUCCESS) {
sizeof (ipaddr->ipadm_static_dname));
}
return (status);
}
/*
* Sets the interface ID in the address object `ipaddr' with the address
* in the string `interface_id'. This interface ID will be used when
* ipadm_create_addr() is called with `ipaddr' with address type
* set to IPADM_ADDR_IPV6_ADDRCONF.
*/
{
struct sockaddr_in6 *sin6;
char *end;
char *cp;
return (IPADM_INVALID_ARG);
return (IPADM_INVALID_ARG);
*cp++ = '\0';
errno = 0;
return (IPADM_INVALID_ARG);
return (IPADM_SUCCESS);
}
return (IPADM_INVALID_ARG);
}
/*
* Sets the value for the field `ipadm_stateless' in address object `ipaddr'.
*/
{
return (IPADM_INVALID_ARG);
return (IPADM_SUCCESS);
}
/*
* Sets the value for the field `ipadm_stateful' in address object `ipaddr'.
*/
{
return (IPADM_INVALID_ARG);
return (IPADM_SUCCESS);
}
/*
* Sets the dhcp parameter `ipadm_primary' in the address object `ipaddr'.
* The field is used during the address creation with address
* type IPADM_ADDR_DHCP. It specifies if the interface should be set
* as a primary interface for getting dhcp global options from the DHCP server.
*/
{
return (IPADM_INVALID_ARG);
return (IPADM_SUCCESS);
}
/*
* Sets the dhcp parameter `ipadm_wait' in the address object `ipaddr'.
* This field is used during the address creation with address type
* IPADM_ADDR_DHCP. It specifies how long the API ipadm_create_addr()
* should wait before returning while the dhcp address is being acquired
* by the dhcpagent.
* Possible values:
* - IPADM_DHCP_WAIT_FOREVER : Do not return until dhcpagent returns.
* - IPADM_DHCP_WAIT_DEFAULT : Wait a default amount of time before returning.
* - <integer> : Wait the specified number of seconds before returning.
*/
{
return (IPADM_INVALID_ARG);
return (IPADM_SUCCESS);
}
/*
* Creates a placeholder for the `ipadm_aobjname' in the ipmgmtd `aobjmap'.
* If the `aobjname' already exists in the daemon's `aobjmap' then
* IPADM_ADDROBJ_EXISTS will be returned.
*
* If the libipadm consumer set `ipaddr.ipadm_aobjname[0]' to `\0', then the
* daemon will generate an `aobjname' for the given `ipaddr'.
*/
{
int err;
sizeof (larg.ia_aobjname));
/* copy the daemon generated `aobjname' into `ipadddr' */
sizeof (ipaddr->ipadm_aobjname));
}
return (IPADM_ADDROBJ_EXISTS);
return (ipadm_errno2status(err));
}
/*
* Creates the IPv4 or IPv6 address in the nvlist `nvl' on the interface
* `ifname'. If a hostname is present, it is resolved before the address
* is created.
*/
{
char *prefixlenstr = NULL;
struct ipadm_addrobj_s ipaddr;
char *cidraddr;
char *name;
int err = 0;
/* retrieve the address information */
}
if (err != 0)
return (ipadm_errno2status(err));
}
if (err != 0)
return (ipadm_errno2status(err));
}
flags |= IPADM_OPT_UP;
/* build the address object from the above information */
return (IPADM_NO_MEMORY);
} else {
}
if (status != IPADM_SUCCESS)
return (status);
if (status != IPADM_SUCCESS)
return (status);
}
}
/*
* Creates a dhcp address on the interface `ifname' based on the
* IPADM_ADDR_DHCP address object parameters from the nvlist `nvl'.
*/
{
char *name;
struct ipadm_addrobj_s ipaddr;
char *aobjname;
int err = 0;
/* Extract the dhcp parameters */
if (err != 0)
return (ipadm_errno2status(err));
}
if (err != 0)
return (ipadm_errno2status(err));
}
/* Build the address object */
ipaddr.ipadm_wait = 0;
else
}
/*
* Creates auto-configured addresses on the interface `ifname' based on
* the IPADM_ADDR_IPV6_ADDRCONF address object parameters from the nvlist `nvl'.
*/
{
struct ipadm_addrobj_s ipaddr;
uint_t n;
char *aobjname;
char *name;
int err = 0;
/* Extract the parameters */
if (err != 0)
return (ipadm_errno2status(err));
}
if (err != 0)
return (ipadm_errno2status(err));
}
/* Build the address object. */
if (intfidlen > 0) {
}
}
/*
* Allocates `ipadm_addrobj_t' and populates the relevant member fields based on
* the provided `type'. `aobjname' represents the address object name, which
* is of the form `<ifname>/<addressname>'.
*
* The caller has to minimally provide <ifname>. If <addressname> is not
* provided, then a default one will be generated by the API.
*/
{
char ifname[IPADM_AOBJSIZ];
return (IPADM_INVALID_ARG);
return (IPADM_INVALID_ARG);
return (IPADM_INVALID_ARG);
*aname++ = '\0';
/* Check if the interface name is valid. */
return (IPADM_INVALID_ARG);
/* Check if the given addrobj name is valid. */
return (IPADM_INVALID_ARG);
return (IPADM_NO_MEMORY);
/*
* If the ifname has logical interface number, extract it and assign
* it to `ipadm_lifnum'. Only applications with IPH_LEGACY set will do
* this today. We will check for the validity later in
* i_ipadm_validate_create_addr().
*/
if (ifsp.ifsp_lunvalid) {
*cp = '\0';
}
sizeof (newaddr->ipadm_ifname));
}
switch (type) {
case IPADM_ADDR_IPV6_ADDRCONF:
newaddr->ipadm_intfidlen = 0;
break;
case IPADM_ADDR_DHCP:
break;
case IPADM_ADDR_STATIC:
break;
default:
goto fail;
}
return (IPADM_SUCCESS);
fail:
return (status);
}
/*
* Frees the address object in `ipaddr'.
*/
void
{
}
/*
* Retrieves the logical interface name from `ipaddr' and stores the
* string in `lifname'.
*/
void
{
if (ipaddr->ipadm_lifnum != 0) {
} else {
}
}
/*
* Checks if a non-zero static address is present on the 0th logical interface
* of the given IPv4 or IPv6 physical interface. For an IPv4 interface, it
* also checks if the interface is under DHCP control. If the condition is true,
* the output argument `exists' will be set to B_TRUE. Otherwise, `exists'
* is set to B_FALSE.
*/
static ipadm_status_t
{
int sock;
/* For IPH_LEGACY, a new logical interface will never be added. */
return (IPADM_SUCCESS);
}
return (ipadm_errno2status(errno));
return (IPADM_SUCCESS);
}
} else {
}
return (ipadm_errno2status(errno));
return (IPADM_SUCCESS);
}
/*
* Reads all the address lines from the persistent DB into the nvlist `onvl',
* when both `ifname' and `aobjname' are NULL. If an `ifname' is provided,
* it returns all the addresses for the given interface `ifname'.
* If an `aobjname' is specified, then the address line corresponding to
* that name will be returned.
*/
static ipadm_status_t
{
int err;
char *nvlbuf;
/* Populate the door_call argument structure */
sizeof (garg.ia_aobjname));
if (err == 0) {
}
return (ipadm_errno2status(err));
}
/*
* Adds the IP address contained in the 'ipaddr' argument to the physical
* interface represented by 'ifname' after doing the required validation.
* If the interface does not exist, it is created before the address is
* added.
*
* If IPH_LEGACY is set in iph_flags, flags has to be IPADM_OPT_ACTIVE
* and a default addrobj name will be generated. Input `addr->ipadm_aobjname',
* if provided, will be ignored and replaced with the newly generated name.
* The interface name provided has to be a logical interface name that
* already exists. No new logical interface will be added in this function.
*/
{
/* check for solaris.network.interface.config authorization */
if (!ipadm_check_auth())
return (IPADM_EAUTH);
/* Validate the addrobj. This also fills in addr->ipadm_ifname. */
if (status != IPADM_SUCCESS)
return (status);
/*
* For Legacy case, check if an addrobj already exists for the
* given logical interface name. If one does not exist,
* a default name will be generated and added to the daemon's
* aobjmap.
*/
if (legacy) {
struct ipadm_addrobj_s ipaddr;
if (status == IPADM_SUCCESS) {
/*
* With IPH_LEGACY, modifying an address that is not
* a static address will return with an error.
*/
return (IPADM_NOTSUP);
/*
* we found the addrobj in daemon, copy over the
* aobjname to `addr'.
*/
} else if (status == IPADM_NOTFOUND) {
} else {
return (status);
}
}
/*
* Create a placeholder for this address object in the daemon.
* Skip this step for IPH_LEGACY case if the addrobj already
* exists.
*/
if (status != IPADM_SUCCESS)
return (status);
}
/* Plumb the IP interfaces if necessary */
return (status);
}
if (status == IPADM_SUCCESS)
created_af = B_TRUE;
return (status);
}
if (status == IPADM_SUCCESS)
}
/* Validate static addresses for IFF_POINTOPOINT interfaces. */
if (status != IPADM_SUCCESS)
goto fail;
if (ifflags & IFF_POINTOPOINT) {
if (is_6to4) {
goto fail;
}
} else {
goto fail;
}
/* Check for a valid dst address. */
if (!legacy && sockaddrunspec(
&addr->ipadm_static_dst_addr)) {
goto fail;
}
}
} else {
/*
* Disallow setting of dstaddr when the link is not
* a point-to-point link.
*/
return (IPADM_INVALID_ARG);
}
}
/*
* For 6to4 interfaces, kernel configures a default link-local
* address. We need to replace it, if the caller has provided
* an address that is different from the default link-local.
*/
goto fail;
}
return (IPADM_SUCCESS);
}
/* Create the address. */
switch (type) {
case IPADM_ADDR_STATIC:
break;
case IPADM_ADDR_DHCP:
break;
case IPADM_ADDR_IPV6_ADDRCONF:
break;
default:
break;
}
/*
* If address was not created successfully, unplumb the interface
* if it was plumbed implicitly in this function and remove the
* addrobj created by the ipmgmtd daemon as a placeholder.
* If IPH_LEGACY is set, then remove the addrobj only if it was
* created in this function.
*/
fail:
if (status != IPADM_DHCP_IPC_TIMEOUT &&
status != IPADM_SUCCESS) {
if (!legacy) {
if (created_af || created_other_af) {
if (created_af) {
}
if (created_other_af) {
}
} else {
}
} else if (!aobjfound) {
}
}
return (status);
}
/*
* Creates the static address in `ipaddr' in kernel. After successfully
* creating it, it updates the ipmgmtd daemon's aobjmap with the logical
* interface information.
*/
static ipadm_status_t
{
int sock;
struct sockaddr_storage m, *mask = &m;
struct ipadm_addrobj_s legacy_addr;
/* If prefixlen was not provided, get default prefixlen */
if (ipaddr->ipadm_static_prefixlen == 0) {
/* prefixlen was not provided, get default prefixlen */
if (status != IPADM_SUCCESS)
return (status);
}
/*
* Check if the interface already has a non-zero address on 0th lif.
* It it does, we create a new logical interface and add the address
* on the new logical interface. If not, we replace the zero address
* on 0th logical interface with the given address.
*/
&addif);
if (status != IPADM_SUCCESS)
return (status);
/*
* This is a "hack" to get around the problem of SIOCLIFADDIF. The
* problem is that this ioctl does not include the netmask when adding
* a logical interface.
*
* To get around this problem, we first add the logical interface with
* a 0 address. After that, we set the netmask if provided. Finally
* we set the interface address.
*/
if (addif) {
return (ipadm_errno2status(errno));
} else if (!legacy) {
/*
* If IPH_LEGACY is specified, the input logical interface
* number is already available in ipadm_lifnum.
*/
ipaddr->ipadm_lifnum = 0;
}
goto ret;
}
goto ret;
}
/* Set the destination address, if one is given. */
goto ret;
}
}
if (flags & IPADM_OPT_UP) {
/*
* IPADM_DAD_FOUND is a soft-error for create-addr.
* No need to tear down the address.
*/
if (status == IPADM_DAD_FOUND)
}
if (status == IPADM_SUCCESS) {
/*
* For IPH_LEGACY, we might be modifying the address on
* an address object that already exists e.g. by doing
* "ifconfig bge0:1 <addr>; ifconfig bge0:1 <newaddr>"
* So, we need to store the object only if it does not
* already exist in ipmgmtd.
*/
if (legacy) {
sizeof (legacy_addr.ipadm_aobjname));
if (status == IPADM_SUCCESS &&
legacy_addr.ipadm_lifnum >= 0) {
return (status);
}
}
flags);
}
ret:
return (status);
}
/*
* Removes the address object identified by `aobjname' from both active and
* persistent configuration. The address object will be removed from only
* active configuration if IPH_LEGACY is set in `iph->iph_flags'.
*
* If the address type is IPADM_ADDR_STATIC or IPADM_ADDR_DHCP, the address
* in the address object will be removed from the physical interface.
* If the address type is IPADM_ADDR_DHCP, the flag IPADM_OPT_RELEASE specifies
* whether the lease should be released. If IPADM_OPT_RELEASE is not
* specified, the lease will be dropped. This option is ignored
* for other address types.
*
* If the address type is IPADM_ADDR_IPV6_ADDRCONF, the link-local address and
* all the autoconfigured addresses will be removed.
* Finally, the address object is also removed from ipmgmtd's aobjmap and from
* the persistent DB.
*/
{
struct ipadm_addrobj_s ipaddr;
/* check for solaris.network.interface.config authorization */
if (!ipadm_check_auth())
return (IPADM_EAUTH);
/* validate input */
!(flags & IPADM_OPT_ACTIVE)) ||
return (IPADM_INVALID_ARG);
}
IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
return (IPADM_INVALID_ARG);
}
/* Retrieve the address object information from ipmgmtd. */
if (status != IPADM_SUCCESS)
return (status);
return (IPADM_NOTSUP);
/*
* If requested to delete just from active config but the address
* is not in active config, return error.
*/
return (IPADM_NOTFOUND);
}
/*
* If address is present in active config, remove it from
* kernel.
*/
switch (ipaddr.ipadm_atype) {
case IPADM_ADDR_STATIC:
break;
case IPADM_ADDR_DHCP:
break;
case IPADM_ADDR_IPV6_ADDRCONF:
break;
default:
/*
* This is the case of address object name residing in
* daemon's aobjmap (added by ADDROBJ_LOOKUPADD). Fall
* through and delete that address object.
*/
break;
}
/*
* If the address was previously deleted from the active
* config, we will get a IPADM_ENXIO from kernel.
* We will still proceed and purge the address information
* in the DB.
*/
if (status == IPADM_ENXIO)
else if (status != IPADM_SUCCESS)
return (status);
}
(flags & IPADM_OPT_PERSIST)) {
flags &= ~IPADM_OPT_PERSIST;
}
if (status == IPADM_NOTFOUND)
return (status);
return (IPADM_SUCCESS);
}
/*
* Starts the dhcpagent and sends it the message DHCP_START to start
* configuring a dhcp address on the given interface in `addr'.
* After making the dhcpagent request, it also updates the
* address object information in ipmgmtd's aobjmap and creates an
* entry in persistent DB if IPADM_OPT_PERSIST is set in `flags'.
*/
static ipadm_status_t
{
return (IPADM_DHCP_START_ERROR);
/*
* Check if a new logical interface has to be created.
*/
addr->ipadm_lifnum = 0;
&addif);
if (status != IPADM_SUCCESS)
return (status);
if (addif) {
/*
* If there is an address on 0th logical interface,
* add a new logical interface.
*/
return (ipadm_errno2status(errno));
}
/* Send DHCP_START to the dhcpagent. */
/*
* We do not undo the create-addr operation for IPADM_DHCP_IPC_TIMEOUT
* since it is only a soft error to indicate the caller that the lease
* might be required after the function returns.
*/
goto fail;
/* Persist the address object information in ipmgmtd. */
if (status != IPADM_SUCCESS)
goto fail;
return (dh_status);
fail:
/* In case of error, delete the dhcp address */
return (status);
}
/*
* object `addr'. If `release' is set to B_FALSE, the lease will be dropped.
*/
static ipadm_status_t
{
int dherr;
/* Send DHCP_RELEASE or DHCP_DROP to the dhcpagent */
if (release) {
/*
* If no lease was obtained on the object, we should
* drop the dhcp control on the interface.
*/
} else {
}
if (status != IPADM_SUCCESS)
return (status);
/* Delete the logical interface */
if (addr->ipadm_lifnum != 0) {
return (ipadm_errno2status(errno));
}
return (IPADM_SUCCESS);
}
/*
* Communicates with the dhcpagent to send a dhcp message of type `type'.
* It returns the dhcp error in `dhcperror' if a non-null pointer is provided
* in `dhcperror'.
*/
static ipadm_status_t
{
int error;
int dhcp_timeout;
/* Construct a message to the dhcpagent. */
if (addr->ipadm_primary)
type |= DHCP_PRIMARY;
return (IPADM_NO_MEMORY);
else
/* Send the message to dhcpagent. */
if (error == 0) {
}
if (error != 0) {
if (error != DHCP_IPC_E_TIMEOUT)
return (IPADM_DHCP_IPC_ERROR);
else if (dhcp_timeout != 0)
return (IPADM_DHCP_IPC_TIMEOUT);
}
return (IPADM_SUCCESS);
}
/*
* Returns the IP addresses of the specified interface in both the
* active and the persistent configuration. If no
* interface is specified, it returns all non-zero IP addresses
* configured on all interfaces in active and persistent
* configurations.
* `addrinfo' will contain addresses that are
* (1) in both active and persistent configuration (created persistently)
* (2) only in active configuration (created temporarily)
* (3) only in persistent configuration (disabled addresses)
*
* Address list that is returned by this function must be freed
* using the ipadm_freeaddr_info() function.
*/
{
return (IPADM_INVALID_ARG);
return (IPADM_INVALID_ARG);
}
flags, lifc_flags));
}
/*
* Frees the structure allocated by ipadm_addr_info().
*/
void
{
}
/*
* Makes a door call to ipmgmtd to update its `aobjmap' with the address
* object in `ipaddr'. This door call also updates the persistent DB to
* remember address object to be recreated on next reboot or on an
* ipadm_enable_addr()/ipadm_enable_if() call.
*/
{
int err = 0;
char pval[MAXPROPVALLEN];
/*
* Construct the nvl to send to the door.
*/
return (IPADM_NO_MEMORY);
ipaddr->ipadm_ifname)) != 0 ||
ipaddr->ipadm_lifnum)) != 0) {
goto ret;
}
switch (ipaddr->ipadm_atype) {
case IPADM_ADDR_STATIC:
if (status != IPADM_SUCCESS)
goto ret;
if (flags & IPADM_OPT_UP)
else
break;
case IPADM_ADDR_DHCP:
ipaddr->ipadm_wait);
break;
case IPADM_ADDR_IPV6_ADDRCONF:
break;
}
if (status != IPADM_SUCCESS)
goto ret;
/*
* IPMGMT_INIT tells the ipmgmtd to set both IPMGMT_ACTIVE and
* IPMGMT_PERSIST on the address object in its `aobjmap'.
* For the callers ipadm_enable_if() and ipadm_enable_addr(),
* IPADM_OPT_PERSIST is not set in their flags. They send
* IPH_INIT in iph_flags, so that the address object will be
* set as both IPMGMT_ACTIVE and IPMGMT_PERSIST.
*/
pflags |= IPMGMT_INIT;
} else {
if (flags & IPADM_OPT_ACTIVE)
pflags |= IPMGMT_ACTIVE;
if (flags & IPADM_OPT_PERSIST)
pflags |= IPMGMT_PERSIST;
}
/*
* prefixlen is stored in a separate line in the DB and not along
* with the address itself, since it is also an address property and
* all address properties are stored in separate lines. We need to
* persist the prefixlen by calling the function that persists
* address properties.
*/
(flags & IPADM_OPT_PERSIST)) {
break;
}
}
ret:
return (status);
}
/*
* Makes the door call to ipmgmtd to store the address object in the
* nvlist `nvl'.
*/
static ipadm_status_t
{
int err;
if (err != 0)
return (ipadm_errno2status(err));
return (ipadm_errno2status(err));
}
/*
* Makes a door call to ipmgmtd to remove the address object in `ipaddr'
* from its `aobjmap'. This door call also removes the address object and all
* its properties from the persistent DB if IPADM_OPT_PERSIST is set in
* `flags', so that the object will not be recreated on next reboot or on an
* ipadm_enable_addr()/ipadm_enable_if() call.
*/
{
int err;
if (flags & IPADM_OPT_ACTIVE)
if (flags & IPADM_OPT_PERSIST)
sizeof (arg.ia_aobjname));
return (ipadm_errno2status(err));
}
/*
* Retrieves the address object corresponding to `aobjname' from ipmgmtd
* and retrieves the address flags for that object from kernel.
* The arguments `ipaddr' and `ifflags' must be allocated by the caller.
*/
static ipadm_status_t
{
/* check for solaris.network.interface.config authorization */
if (!ipadm_check_auth())
return (IPADM_EAUTH);
/* validate input */
IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
return (IPADM_INVALID_ARG);
}
/* Retrieve the address object information. */
if (status != IPADM_SUCCESS)
return (status);
return (IPADM_OP_DISABLE_OBJ);
if ((ipadm_flags & IPADM_OPT_PERSIST) &&
return (IPADM_TEMPORARY_OBJ);
(ipadm_flags & IPADM_OPT_PERSIST)))
return (IPADM_NOTSUP);
}
/*
* Marks the address in the address object `aobjname' up. This operation is
* not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF.
* For an address object of type IPADM_ADDR_DHCP, this operation can
* only be temporary and no updates will be made to the persistent DB.
*/
{
struct ipadm_addrobj_s ipaddr;
&flags);
if (status != IPADM_SUCCESS)
return (status);
goto persist;
/*
* If the address is already a duplicate, then refresh-addr
* should be used to mark it up.
*/
if (flags & IFF_DUPLICATE)
return (IPADM_DAD_FOUND);
if (status != IPADM_SUCCESS)
return (status);
/* Update persistent DB. */
if (ipadm_flags & IPADM_OPT_PERSIST) {
"yes", &ipaddr, 0);
}
return (status);
}
/*
* Marks the address in the address object `aobjname' down. This operation is
* not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF.
* For an address object of type IPADM_ADDR_DHCP, this operation can
* only be temporary and no updates will be made to the persistent DB.
*/
{
struct ipadm_addrobj_s ipaddr;
&flags);
if (status != IPADM_SUCCESS)
return (status);
if (status != IPADM_SUCCESS)
return (status);
} else if (flags & IFF_DUPLICATE) {
/*
* Clear the IFF_DUPLICATE flag.
*/
return (ipadm_errno2status(errno));
return (ipadm_errno2status(errno));
}
/* Update persistent DB */
if (ipadm_flags & IPADM_OPT_PERSIST) {
"no", &ipaddr, 0);
}
return (status);
}
/*
* Refreshes the address in the address object `aobjname'. If the address object
* is of type IPADM_ADDR_STATIC, DAD is re-initiated on the address. If
* `ipadm_flags' has IPADM_OPT_INFORM set, a DHCP_INFORM message is sent to the
* dhcpagent for this static address. If the address object is of type
* IPADM_ADDR_DHCP, a DHCP_EXTEND message is sent to the dhcpagent.
* If a dhcp address has not yet been acquired, a DHCP_START is sent to the
* dhcpagent. This operation is not supported for an address object of
* type IPADM_ADDR_IPV6_ADDRCONF.
*/
{
struct ipadm_addrobj_s ipaddr;
((ipadm_flags & IPADM_OPT_INFORM) != 0);
int dherr;
/* check for solaris.network.interface.config authorization */
if (!ipadm_check_auth())
return (IPADM_EAUTH);
/* validate input */
IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
return (IPADM_INVALID_ARG);
}
/* Retrieve the address object information. */
if (status != IPADM_SUCCESS)
return (status);
return (IPADM_OP_DISABLE_OBJ);
return (IPADM_NOTSUP);
return (IPADM_INVALID_ARG);
if (status != IPADM_SUCCESS)
return (status);
if (inform) {
}
if (!(flags & IFF_DUPLICATE))
return (IPADM_SUCCESS);
/*
* Restart the dhcp address negotiation with server if no
* address has been acquired yet.
*/
}
} else {
}
return (status);
}
/*
* This is called from ipadm_create_addr() to validate the address parameters.
* It does the following steps:
* 1. Validates the interface name.
* 2. Verifies that the interface is not an IPMP meta-interface or an
* underlying interface.
* 3. In case of a persistent operation, verifies that the interface
* is persistent. Returns error if interface is not enabled but
* is in persistent config.
* 4. Verifies that the destination address is not set or the address type is
* not DHCP or ADDRCONF when the interface is a loopback interface.
* 5. Verifies that the address type is not DHCP or ADDRCONF when the interface
* has IFF_VRRP interface flag set.
*/
static ipadm_status_t
{
char *ifname;
return (IPADM_INVALID_ARG);
}
return (IPADM_BAD_ADDR);
return (IPADM_INVALID_ARG);
return (IPADM_NOTSUP);
return (IPADM_NOTSUP);
/*
* For legacy case, interfaces are not implicitly plumbed. We need to
* check if the interface exists in the active configuration.
*/
return (IPADM_ENXIO);
/*
* Check if one of the v4 or the v6 interfaces exists in the
* active configuration. An interface is considered disabled only
* if both v4 and v6 are not active.
*/
/* Check if interface exists in the persistent configuration. */
if (status != IPADM_SUCCESS)
return (status);
return (IPADM_OP_DISABLE_OBJ);
/*
* If address has to be created persistently,
* and the interface does not exist in the persistent
* store but in active config, fail.
*/
return (IPADM_TEMPORARY_OBJ);
}
if (af_exists) {
if (status != IPADM_SUCCESS)
return (status);
}
/* Perform validation steps (4) and (5) */
switch (ipaddr->ipadm_atype) {
case IPADM_ADDR_STATIC:
return (IPADM_INVALID_ARG);
/* Check for a valid src address */
return (IPADM_BAD_ADDR);
break;
case IPADM_ADDR_DHCP:
return (IPADM_NOTSUP);
break;
case IPADM_ADDR_IPV6_ADDRCONF:
return (IPADM_NOTSUP);
}
break;
default:
return (IPADM_INVALID_ARG);
}
return (IPADM_SUCCESS);
}
const char *aobjname)
{
char *aname;
int err;
/* prefixlen exists for given address object */
&prefixnvp);
if (err == 0) {
nvpair_type(nvp));
}
return (ipadm_errno2status(err));
}
}
return (IPADM_SUCCESS);
}
/*
* Re-enables the address object `aobjname' based on the saved
* configuration for `aobjname'.
*/
{
struct ipadm_addrobj_s ipaddr;
/* check for solaris.network.interface.config authorization */
if (!ipadm_check_auth())
return (IPADM_EAUTH);
/* validate input */
if (flags & IPADM_OPT_PERSIST)
return (IPADM_NOTSUP);
IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) {
return (IPADM_INVALID_ARG);
}
/* Retrieve the address object information. */
if (status != IPADM_SUCCESS)
return (status);
return (IPADM_ADDROBJ_EXISTS);
if (status != IPADM_SUCCESS)
return (status);
continue;
aobjname);
if (status != IPADM_SUCCESS)
continue;
}
if (status != IPADM_SUCCESS)
break;
}
return (status);
}
/*
* Disables the address object in `aobjname' from the active configuration.
* Error code return values follow the model in ipadm_delete_addr().
*/
{
/* validate input */
if (flags & IPADM_OPT_PERSIST)
return (IPADM_NOTSUP);
}