6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * CDDL HEADER START
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * The contents of this file are subject to the terms of the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Common Development and Distribution License (the "License").
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * You may not use this file except in compliance with the License.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * or http://www.opensolaris.org/os/licensing.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * See the License for the specific language governing permissions
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and limitations under the License.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * When distributing Covered Code, include this CDDL HEADER in each
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If applicable, add the following below this CDDL HEADER, with the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * fields enclosed by brackets "[]" replaced with your own identifying
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * information: Portions Copyright [yyyy] [name of copyright owner]
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * CDDL HEADER END
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <errno.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/sockio.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <string.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <assert.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <unistd.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <stropts.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <strings.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <libdlpi.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <libdllink.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <libinetutil.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <inet/ip.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <limits.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <zone.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <ipadm_ndpd.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include "libipadm_impl.h"
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t i_ipadm_slifname_arp(char *, uint64_t, int);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t i_ipadm_slifname(ipadm_handle_t, char *, char *,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint64_t, int, uint32_t);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t i_ipadm_create_ipmp_peer(ipadm_handle_t, char *,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sa_family_t);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t i_ipadm_persist_if(ipadm_handle_t, const char *,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sa_family_t);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Returns B_FALSE if the interface in `ifname' has at least one address that is
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IFF_UP in the addresses in `ifa'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic boolean_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_is_if_down(char *ifname, struct ifaddrs *ifa)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct ifaddrs *ifap;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char cifname[LIFNAMSIZ];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *sep;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(cifname, ifap->ifa_name, sizeof (cifname));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((sep = strrchr(cifname, IPADM_LOGICAL_SEP)) != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *sep = '\0';
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If this condition is true, there is at least one
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * address that is IFF_UP. So, we need to return B_FALSE.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strcmp(cifname, ifname) == 0 &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (ifap->ifa_flags & IFF_UP)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (B_FALSE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* We did not find any IFF_UP addresses. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (B_TRUE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Retrieves the information for the interface `ifname' from active
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * config if `ifname' is specified and returns the result in the list `if_info'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Otherwise, it retrieves the information for all the interfaces in
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the active config and returns the result in the list `if_info'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_active_if_info(ipadm_handle_t iph, const char *ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t **if_info, int64_t lifc_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq *buf;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq *lifrp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifrl;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *last = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *ifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int s;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int n;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int numifs;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Get information for all interfaces.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (getallifs(iph->iph_sock, 0, &buf, &numifs, lifc_flags) != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(errno));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifrp = buf;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (n = 0; n < numifs; n++, lifrp++) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Skip interfaces with logical num != 0 */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (i_ipadm_get_lnum(lifrp->lifr_name) != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Skip the current interface if a specific `ifname' has
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * been requested and current interface does not match
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * `ifname'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifname != NULL && strcmp(lifrp->lifr_name, ifname) != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Check if the interface already exists in our list.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If it already exists, we need to update its flags.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (ifp = *if_info; ifp != NULL; ifp = ifp->ifi_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strcmp(lifrp->lifr_name, ifp->ifi_name) == 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifp == NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp = calloc(1, sizeof (ipadm_if_info_t));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifp == NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(ifp->ifi_name, lifrp->lifr_name,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (ifp->ifi_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Update the `ifi_next' pointer for this new node */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (*if_info == NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = ifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail last->ifi_next = ifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail last = ifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Retrieve the flags for the interface by doing a
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * SIOCGLIFFLAGS to populate the `ifi_cflags' field.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifrl.lifr_name,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifrp->lifr_name, sizeof (lifrl.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail s = (lifrp->lifr_addr.ss_family == AF_INET) ?
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail iph->iph_sock : iph->iph_sock6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_BROADCAST)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_BROADCAST;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_MULTICAST)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_MULTICAST;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_POINTOPOINT)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_POINTOPOINT;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_VIRTUAL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_VIRTUAL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_IPMP)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_IPMP;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_STANDBY)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_STANDBY;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_INACTIVE)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_INACTIVE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_VRRP)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_VRRP;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_NOACCEPT)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_NOACCEPT;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_IPV4)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_IPV4;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_IPV6)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp->ifi_cflags |= IFIF_IPV6;
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan if (lifrl.lifr_flags & IFF_L3PROTECT)
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan ifp->ifi_cflags |= IFIF_L3PROTECT;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail free(buf);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailfail:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail free(buf);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_free_if_info(*if_info);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Returns the interface information for `ifname' in `if_info' from persistent
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * config if `ifname' is non-null. Otherwise, it returns all the interfaces
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * from persistent config in `if_info'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_persist_if_info(ipadm_handle_t iph, const char *ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t **if_info)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipmgmt_getif_arg_t getif;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipmgmt_getif_rval_t *rvalp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *ifp, *curr, *prev = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int i = 0, err = 0;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&getif, sizeof (getif));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifname != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(getif.ia_ifname, ifname, LIFNAMSIZ);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail getif.ia_cmd = IPMGMT_CMD_GETIF;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((rvalp = malloc(sizeof (ipmgmt_getif_rval_t))) == NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(errno));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = ipadm_door_call(iph, &getif, sizeof (getif), (void **)&rvalp,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (*rvalp), B_TRUE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (err == ENOENT) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail free(rvalp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifname != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(err));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else if (err != 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail free(rvalp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(err));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp = rvalp->ir_ifinfo;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (i = 0; i < rvalp->ir_ifcnt; i++) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifp = rvalp->ir_ifinfo + i;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((curr = malloc(sizeof (*curr))) == NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_free_if_info(prev);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) bcopy(ifp, curr, sizeof (*curr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail curr->ifi_next = prev;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail prev = curr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = curr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail free(rvalp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Collects information for `ifname' if one is specified from both
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * active and persistent config in `if_info'. If no `ifname' is specified,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * this returns all the interfaces in active and persistent config in
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * `if_info'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_get_all_if_info(ipadm_handle_t iph, const char *ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t **if_info, int64_t lifc_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *aifinfo = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *pifinfo = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *aifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *pifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *last = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct ifaddrs *ifa;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct ifaddrs *ifap;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Retrive the information for the requested `ifname' or all
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interfaces from active configuration.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailretry:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_active_if_info(iph, ifname, &aifinfo, lifc_flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Get the interface state for each interface in `aifinfo'. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (aifinfo != NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* We need all addresses to get the interface state */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (getallifaddrs(AF_UNSPEC, &ifa, (LIFC_NOXMIT|LIFC_TEMPORARY|
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail LIFC_ALLZONES|LIFC_UNDER_IPMP)) != 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (aifp = aifinfo; aifp != NULL; aifp = aifp->ifi_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Find the `ifaddrs' structure from `ifa'
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for this interface. We need the IFF_* flags
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * to find the interface state.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strcmp(ifap->ifa_name, aifp->ifi_name) == 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifap == NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * The interface might have been removed
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * from kernel. Retry getting all the active
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interfaces.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail freeifaddrs(ifa);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_free_if_info(aifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifinfo = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto retry;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!(ifap->ifa_flags & IFF_RUNNING) ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (ifap->ifa_flags & IFF_FAILED))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp->ifi_state = IFIS_FAILED;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else if (ifap->ifa_flags & IFF_OFFLINE)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp->ifi_state = IFIS_OFFLINE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else if (i_ipadm_is_if_down(aifp->ifi_name, ifa))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp->ifi_state = IFIS_DOWN;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp->ifi_state = IFIS_OK;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (aifp->ifi_next == NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail last = aifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail freeifaddrs(ifa);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Get the persistent interface information in `pifinfo'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_persist_if_info(iph, ifname, &pifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status == IPADM_NOTFOUND) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = aifinfo;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If a persistent interface is also found in `aifinfo', update
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * its entry in `aifinfo' with the persistent information from
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * `pifinfo'. If an interface is found in `pifinfo', but not in
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * `aifinfo', it means that this interface was disabled. We should
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * add this interface to `aifinfo' and set it state to IFIF_DISABLED.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (pifp = pifinfo; pifp != NULL; pifp = pifp->ifi_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (aifp = aifinfo; aifp != NULL; aifp = aifp->ifi_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strcmp(aifp->ifi_name, pifp->ifi_name) == 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp->ifi_pflags = pifp->ifi_pflags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (aifp == NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp = malloc(sizeof (ipadm_if_info_t));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (aifp == NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *aifp = *pifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp->ifi_next = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifp->ifi_state = IFIS_DISABLED;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (last != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail last->ifi_next = aifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail aifinfo = aifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail last = aifp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = aifinfo;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_free_if_info(pifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailfail:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *if_info = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_free_if_info(aifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_free_if_info(pifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_get_lnum(const char *ifname)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *num = strrchr(ifname, IPADM_LOGICAL_SEP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (num == NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (atoi(++num));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Sets the output argument `exists' to true or false based on whether
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * any persistent configuration is available for `ifname' and returns
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IPADM_SUCCESS as status. If the persistent information cannot be retrieved,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * `exists' is unmodified and an error status is returned.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_if_pexists(ipadm_handle_t iph, const char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t *exists)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *ifinfo;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan /*
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan * if IPH_IPMGMTD is set, we know that the caller (ipmgmtd) already
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan * knows about persistent configuration in the first place, so we
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan * just return success.
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan */
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan if (iph->iph_flags & IPH_IPMGMTD) {
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan *exists = B_FALSE;
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan return (IPADM_SUCCESS);
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_persist_if_info(iph, ifname, &ifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *exists = ((af == AF_INET &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (ifinfo->ifi_pflags & IFIF_IPV4)) ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (af == AF_INET6 &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (ifinfo->ifi_pflags & IFIF_IPV6)));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail free(ifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else if (status == IPADM_NOTFOUND) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *exists = B_FALSE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Open "/dev/udp{,6}" for use as a multiplexor to PLINK the interface stream
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * under. We use "/dev/udp" instead of "/dev/ip" since STREAMS will not let
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * you PLINK a driver under itself, and "/dev/ip" is typically the driver at
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the bottom of the stream for tunneling interfaces.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_open_arp_on_udp(const char *udp_dev_name, int *fd)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((*fd = open(udp_dev_name, O_RDWR)) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(errno));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Pop off all undesired modules (note that the user may have
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * configured autopush to add modules above udp), and push the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * arp module onto the resulting stream. This is used to make
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IP+ARP be able to atomically track the muxid for the I_PLINKed
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * STREAMS, thus it isn't related to ARP running the ARP protocol.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail while (ioctl(*fd, I_POP, 0) != -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (errno == EINVAL && ioctl(*fd, I_PUSH, ARP_MOD_NAME) != -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = errno;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) close(*fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(err));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * i_ipadm_create_ipmp() is called from i_ipadm_create_ipmp_peer() when an
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * underlying interface in an ipmp group G is plumbed for an address family,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * but the meta-interface for the other address family `af' does not exist
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * yet for the group G. If `af' is IPv6, we need to bring up the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * link-local address.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_create_ipmp(ipadm_handle_t iph, char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail const char *grname, uint32_t ipadm_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int sock;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail assert(ipadm_flags & IPADM_OPT_IPMP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Create the ipmp underlying interface */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_create_if(iph, ifname, af, ipadm_flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * To preserve backward-compatibility, always bring up the link-local
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * address for implicitly-created IPv6 IPMP interfaces.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET6)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_set_flags(iph, ifname, AF_INET6, IFF_UP, 0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sock = (af == AF_INET ? iph->iph_sock : iph->iph_sock6);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If the caller requested a different group name, issue a
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * SIOCSLIFGROUPNAME on the new IPMP interface.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr, sizeof (lifr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strcmp(lifr.lifr_name, grname) != 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_groupname, grname, LIFGRNAMSIZ);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(sock, SIOCSLIFGROUPNAME, &lifr) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = errno;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Remove the interface we created. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_delete_if(iph, ifname, af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(err));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Checks if `ifname' is plumbed and in an IPMP group on its "other" address
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * family. If so, create a matching IPMP group for address family `af'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_create_ipmp_peer(ipadm_handle_t iph, char *ifname, sa_family_t af)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifgroupinfo_t lifgr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int other_af_sock;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail assert(af == AF_INET || af == AF_INET6);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail other_af_sock = (af == AF_INET ? iph->iph_sock6 : iph->iph_sock);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * iph is the handle for the interface that we are trying to plumb.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * other_af_sock is the socket for the "other" address family.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr, sizeof (lifr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(other_af_sock, SIOCGLIFGROUPNAME, &lifr) != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifgr.gi_grname, lifr.lifr_groupname, LIFGRNAMSIZ);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(other_af_sock, SIOCGLIFGROUPINFO, &lifgr) != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If `ifname' *is* the IPMP group interface, or if the relevant
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * address family is already configured, then there's nothing to do.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strcmp(lifgr.gi_grifname, ifname) == 0 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (af == AF_INET && lifgr.gi_v4) || (af == AF_INET6 && lifgr.gi_v6)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_create_ipmp(iph, lifgr.gi_grifname, af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifgr.gi_grname, IPADM_OPT_ACTIVE|IPADM_OPT_IPMP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Issues the ioctl SIOCSLIFNAME to kernel on the given ARP stream fd.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_slifname_arp(char *ifname, uint64_t flags, int fd)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifspec_t ifsp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr, sizeof (lifr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) ifparse_ifspec(ifname, &ifsp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_ppa = ifsp.ifsp_ppa;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_flags = flags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Tell ARP the name and unit number for this interface.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Note that arp has no support for transparent ioctls.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (i_ipadm_strioctl(fd, SIOCSLIFNAME, (char *)&lifr,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (lifr)) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(errno));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Issues the ioctl SIOCSLIFNAME to kernel. If IPADM_OPT_GENPPA is set in
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * `ipadm_flags', then a ppa will be generated. `newif' will be updated
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * with the generated ppa.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_slifname(ipadm_handle_t iph, char *ifname, char *newif, uint64_t flags,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int fd, uint32_t ipadm_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int err = 0;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sa_family_t af;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int ppa;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifspec_t ifsp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t valid_if;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr, sizeof (lifr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ipadm_flags & IPADM_OPT_GENPPA) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * We'd like to just set lifr_ppa to UINT_MAX and have the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * kernel pick a PPA. Unfortunately, that would mishandle
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * two cases:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * 1. If the PPA is available but the groupname is taken
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * (e.g., the "ipmp2" IP interface name is available
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * but the "ipmp2" groupname is taken) then the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * auto-assignment by the kernel will fail.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * 2. If we're creating (e.g.) an IPv6-only IPMP
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interface, and there's already an IPv4-only IPMP
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interface, the kernel will allow us to accidentally
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * reuse the IPv6 IPMP interface name (since
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * SIOCSLIFNAME uniqueness is per-interface-type).
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * This will cause administrative confusion.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Thus, we instead take a brute-force approach of checking
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * whether the IPv4 or IPv6 name is already in-use before
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * attempting the SIOCSLIFNAME. As per (1) above, the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * SIOCSLIFNAME may still fail, in which case we just proceed
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * to the next one. If this approach becomes too slow, we
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * can add a new SIOC* to handle this case in the kernel.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (ppa = 0; ppa < UINT_MAX; ppa++) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) snprintf(lifr.lifr_name, LIFNAMSIZ, "%s%d",
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifname, ppa);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(iph->iph_sock, SIOCGLIFFLAGS, &lifr) != -1 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail errno != ENXIO)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(iph->iph_sock6, SIOCGLIFFLAGS, &lifr) != -1 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail errno != ENXIO)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_ppa = ppa;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_flags = flags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = ioctl(fd, SIOCSLIFNAME, &lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (err != -1 || errno != EEXIST)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (err == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * PPA has been successfully established.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Update `newif' with the ppa.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail assert(newif != NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (snprintf(newif, LIFNAMSIZ, "%s%d", ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ppa) >= LIFNAMSIZ)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* We should have already validated the interface name. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail valid_if = ifparse_ifspec(ifname, &ifsp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail assert(valid_if);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Before we call SIOCSLIFNAME, ensure that the IPMP group
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interface for this address family exists. Otherwise, the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * kernel will kick the interface out of the group when we do
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the SIOCSLIFNAME.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Example: suppose bge0 is plumbed for IPv4 and in group "a".
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If we're now plumbing bge0 for IPv6, but the IPMP group
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interface for "a" is not plumbed for IPv6, the SIOCSLIFNAME
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * will kick bge0 out of group "a", which is undesired.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags & IFF_IPV4)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail af = AF_INET;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail af = AF_INET6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_create_ipmp_peer(iph, ifname, af);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_ppa = ifsp.ifsp_ppa;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_flags = flags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(fd, SIOCSLIFNAME, &lifr) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Plumbs the interface `ifname' for the address family `af'. It also persists
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the interface for `af' if IPADM_OPT_PERSIST is set in `ipadm_flags'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_plumb_if(ipadm_handle_t iph, char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint32_t ipadm_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int ip_muxid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int mux_fd = -1, ip_fd, arp_fd;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *udp_dev_name;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dlpi_handle_t dh_arp = NULL, dh_ip;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint64_t ifflags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint_t dlpi_flags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *linkname;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t legacy = (iph->iph_flags & IPH_LEGACY);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail zoneid_t zoneid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char newif[LIFNAMSIZ];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char lifname[LIFNAMSIZ];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail datalink_id_t linkid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int sock;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t islo;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t is_persistent =
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ((ipadm_flags & IPADM_OPT_PERSIST) != 0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint32_t dlflags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dladm_status_t dlstatus;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (iph->iph_dlh != NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dlstatus = dladm_name2info(iph->iph_dlh, ifname, &linkid,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail &dlflags, NULL, NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If we're in the global zone and we're plumbing a datalink, make
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * sure that the datalink is not assigned to a non-global zone. Note
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * that the non-global zones don't need this check, because zoneadm
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * has taken care of this when the zones boot.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
550b6e4083768ca350e9e7c3a1ebbf720b23dcadSowmini Varadhan if (iph->iph_zoneid == GLOBAL_ZONEID && dlstatus == DLADM_STATUS_OK) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail zoneid = ALL_ZONES;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (zone_check_datalink(&zoneid, linkid) == 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* interface is in use by a non-global zone. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_IF_INUSE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* loopback interfaces are just added as logical interface */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr, sizeof (lifr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail islo = i_ipadm_is_loopback(ifname);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (islo || i_ipadm_get_lnum(ifname) != 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sock = iph->iph_sock;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sock = iph->iph_sock6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (islo && ioctl(sock, SIOCGLIFADDR, (caddr_t)&lifr) >= 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_IF_EXISTS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(errno));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * By default, kernel configures 127.0.0.1 on the loopback
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interface. Replace this with 0.0.0.0 to be consistent
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * with interface creation on other physical interfaces.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (islo && !legacy) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr.lifr_addr, sizeof (lifr.lifr_addr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_addr.ss_family = af;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(errno));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (is_persistent) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_persist_if(iph, ifname, af);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_delete_if(iph, ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail af, IPADM_OPT_ACTIVE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dlpi_flags = DLPI_NOATTACH;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If IPADM_OPT_IPMP is specified, then this is a request
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * to create an IPMP interface atop /dev/ipmpstub0. (We can't simply
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * pass "ipmpstub0" as devname since an admin *could* have a normal
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * vanity-named link named "ipmpstub0" that they'd like to plumb.)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ipadm_flags & IPADM_OPT_IPMP) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dlpi_flags |= DLPI_DEVONLY;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail linkname = "ipmpstub0";
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Verify that the user is not creating a persistent
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IP interface on a non-persistent data-link.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!i_ipadm_is_vni(ifname) && dlstatus == DLADM_STATUS_OK &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail is_persistent && !(dlflags & DLADM_OPT_PERSIST)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_TEMPORARY_OBJ);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail linkname = ifname;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * We use DLPI_NOATTACH because the ip module will do the attach
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * itself for DLPI style-2 devices.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (dlpi_open(linkname, &dh_ip, dlpi_flags) != DLPI_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_DLPI_FAILURE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ip_fd = dlpi_fd(dh_ip);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(ip_fd, I_PUSH, IP_MOD_NAME) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Set IFF_IPV4/IFF_IPV6 flags. The kernel only allows modifications
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * to IFF_IPv4, IFF_IPV6, IFF_BROADCAST, IFF_XRESOLV, IFF_NOLINKLOCAL.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifflags = 0;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Set the name string and the IFF_IPV* flag */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifflags = IFF_IPV4;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifflags = IFF_IPV6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * With the legacy method, the link-local address should be
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * configured as part of the interface plumb, using the default
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * token. If IPH_LEGACY is not specified, we want to set :: as
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the address and require the admin to explicitly call
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * ipadm_create_addr() with the address object type set to
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IPADM_ADDR_IPV6_ADDRCONF to create the link-local address
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * as well as the autoconfigured addresses.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!legacy && !i_ipadm_is_6to4(iph, ifname))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifflags |= IFF_NOLINKLOCAL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(newif, ifname, sizeof (newif));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_slifname(iph, ifname, newif, ifflags, ip_fd,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Get the full set of existing flags for this stream */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_get_flags(iph, newif, af, &ifflags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail udp_dev_name = (af == AF_INET6 ? UDP6_DEV_NAME : UDP_DEV_NAME);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_open_arp_on_udp(udp_dev_name, &mux_fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Check if arp is not needed */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifflags & (IFF_NOARP|IFF_IPV6)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * PLINK the interface stream so that the application can exit
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * without tearing down the stream.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * This interface does use ARP, so set up a separate stream
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * from the interface to ARP.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * We use DLPI_NOATTACH because the arp module will do the attach
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * itself for DLPI style-2 devices.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (dlpi_open(linkname, &dh_arp, dlpi_flags) != DLPI_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = IPADM_DLPI_FAILURE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail arp_fd = dlpi_fd(dh_arp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(arp_fd, I_PUSH, ARP_MOD_NAME) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_slifname_arp(newif, ifflags, arp_fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * PLINK the IP and ARP streams so that ifconfig can exit
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * without tearing down the stream.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(mux_fd, I_PLINK, arp_fd) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) ioctl(mux_fd, I_PUNLINK, ip_muxid);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaildone:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dlpi_close(dh_ip);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (dh_arp != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dlpi_close(dh_arp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mux_fd != -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) close(mux_fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* copy back new ifname */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(ifname, newif, LIFNAMSIZ);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If it is a 6to4 tunnel, create a default
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * addrobj name for the default address on the 0'th
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * logical interface and set IFF_UP in the interface flags.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (i_ipadm_is_6to4(iph, ifname)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct ipadm_addrobj_s addr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail i_ipadm_init_addr(&addr, ifname, "", IPADM_ADDR_STATIC);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail addr.ipadm_af = af;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_lookupadd_addrobj(iph, &addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_add_aobjname(iph, ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail af, addr.ipadm_aobjname, IPADM_ADDR_STATIC, 0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail addr.ipadm_lifnum = 0;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail i_ipadm_addrobj2lifname(&addr, lifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (lifname));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_set_flags(iph, lifname, af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IFF_UP, 0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Prevent static IPv6 addresses from triggering
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * autoconf. This does not have to be done for
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * 6to4 tunnel interfaces, since in.ndpd will
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * not autoconfigure those interfaces.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET6 && !legacy)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_disable_autoconf(newif);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If IPADM_OPT_PERSIST was set in flags, store the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * interface in persistent DB.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (is_persistent) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_persist_if(iph, newif, af);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_delete_if(iph, newif, af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IPADM_OPT_ACTIVE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status == IPADM_EXISTS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = IPADM_IF_EXISTS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Unplumbs the interface in `ifname' of family `af'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_unplumb_if(ipadm_handle_t iph, const char *ifname, sa_family_t af)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int ip_muxid, arp_muxid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int mux_fd = -1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int muxid_fd = -1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *udp_dev_name;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint64_t flags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t changed_arp_muxid = B_FALSE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int save_errno;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t ret = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int sock;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifgroupinfo_t lifgr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifaddrlistx_t *ifaddrs, *ifaddrp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t v6 = (af == AF_INET6);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Just do SIOCLIFREMOVEIF on loopback interfaces */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr, sizeof (lifr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (i_ipadm_is_loopback(ifname) ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (i_ipadm_get_lnum(ifname) != 0 && (iph->iph_flags & IPH_LEGACY))) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl((af == AF_INET) ? iph->iph_sock : iph->iph_sock6,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail SIOCLIFREMOVEIF, (caddr_t)&lifr) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(errno));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * We used /dev/udp or udp6 to set up the mux. So we have to use
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the same now for PUNLINK also.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (v6) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail udp_dev_name = UDP6_DEV_NAME;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sock = iph->iph_sock6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail udp_dev_name = UDP_DEV_NAME;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sock = iph->iph_sock;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((muxid_fd = open(udp_dev_name, O_RDWR)) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_open_arp_on_udp(udp_dev_name, &mux_fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ret != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(muxid_fd, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail flags = lifr.lifr_flags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailagain:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags & IFF_IPMP) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * There are two reasons the I_PUNLINK can fail with EBUSY:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * (1) if IP interfaces are in the group, or (2) if IPMP data
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * addresses are administratively up. For case (1), we fail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * here with a specific error message. For case (2), we bring
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * down the addresses prior to doing the I_PUNLINK. If the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * I_PUNLINK still fails with EBUSY then the configuration
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * must have changed after our checks, in which case we branch
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * back up to `again' and rerun this logic. The net effect is
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * that unplumbing an IPMP interface will only fail with EBUSY
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * if IP interfaces are in the group.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(sock, SIOCGLIFGROUPNAME, &lifr) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifgr.gi_grname, lifr.lifr_groupname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail LIFGRNAMSIZ);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(sock, SIOCGLIFGROUPINFO, &lifgr) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((v6 && lifgr.gi_nv6 != 0) || (!v6 && lifgr.gi_nv4 != 0)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = IPADM_GRP_NOTEMPTY;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * The kernel will fail the I_PUNLINK if the IPMP interface
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * has administratively up addresses; bring them down.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifaddrlistx(ifname, IFF_UP|IFF_DUPLICATE,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail 0, &ifaddrs) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifaddrp = ifaddrs;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (; ifaddrp != NULL; ifaddrp = ifaddrp->ia_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int sock = (ifaddrp->ia_flags & IFF_IPV4) ?
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail iph->iph_sock : iph->iph_sock6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifrl;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (((ifaddrp->ia_flags & IFF_IPV6) && !v6) ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (!(ifaddrp->ia_flags & IFF_IPV6) && v6))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifrl, sizeof (lifrl));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(lifrl.lifr_name, ifaddrp->ia_name,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (lifrl.lifr_name));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(sock, SIOCGLIFFLAGS, &lifrl) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifaddrlistx_free(ifaddrs);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (lifrl.lifr_flags & IFF_UP) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = i_ipadm_set_flags(iph, lifrl.lifr_name,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ((lifrl.lifr_flags & IFF_IPV4) ? AF_INET :
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail AF_INET6), 0, IFF_UP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ret != IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifaddrlistx_free(ifaddrs);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else if (lifrl.lifr_flags & IFF_DUPLICATE) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(sock, SIOCGLIFADDR, &lifrl) < 0 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ioctl(sock, SIOCSLIFADDR, &lifrl) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifaddrlistx_free(ifaddrs);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifaddrlistx_free(ifaddrs);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(muxid_fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail arp_muxid = lifr.lifr_arp_muxid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ip_muxid = lifr.lifr_ip_muxid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * We don't have a good way of knowing whether the arp stream is
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * plumbed. We can't rely on IFF_NOARP because someone could
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * have turned it off later using "ifconfig xxx -arp".
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (arp_muxid != 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(mux_fd, I_PUNLINK, arp_muxid) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * See the comment before the SIOCGLIFGROUPNAME call.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (errno == EBUSY && (flags & IFF_IPMP))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto again;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((errno == EINVAL) &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (flags & (IFF_NOARP | IFF_IPV6))) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Some plumbing utilities set the muxid to
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * -1 or some invalid value to signify that
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * there is no arp stream. Set the muxid to 0
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * before trying to unplumb the IP stream.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IP does not allow the IP stream to be
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * unplumbed if it sees a non-null arp muxid,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for consistency of IP-ARP streams.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_arp_muxid = 0;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) ioctl(muxid_fd, SIOCSLIFMUXID,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (caddr_t)&lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail changed_arp_muxid = B_TRUE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * In case of any other error, we continue with
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the unplumb.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ioctl(mux_fd, I_PUNLINK, ip_muxid) < 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (changed_arp_muxid) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Some error occurred, and we need to restore
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * everything back to what it was.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail save_errno = errno;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_arp_muxid = arp_muxid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_ip_muxid = ip_muxid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) ioctl(muxid_fd, SIOCSLIFMUXID, (caddr_t)&lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail errno = save_errno;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * See the comment before the SIOCGLIFGROUPNAME call.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (errno == EBUSY && (flags & IFF_IPMP))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto again;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaildone:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (muxid_fd != -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) close(muxid_fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mux_fd != -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) close(mux_fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET6 && ret == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * in.ndpd maintains the phyints in its memory even after
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the interface is plumbed, so that it can be reused when
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the interface gets plumbed again. The default behavior
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * of in.ndpd is to start autoconfiguration for an interface
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * that gets plumbed. We need to send the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * message IPADM_ENABLE_AUTOCONF to in.ndpd to restore this
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * default behavior on replumb.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_enable_autoconf(ifname);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ret);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Saves the given interface name `ifname' with address family `af' in
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * persistent DB.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_persist_if(ipadm_handle_t iph, const char *ifname, sa_family_t af)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipmgmt_if_arg_t ifarg;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(ifarg.ia_ifname, ifname, sizeof (ifarg.ia_ifname));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifarg.ia_family = af;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifarg.ia_cmd = IPMGMT_CMD_SETIF;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifarg.ia_flags = IPMGMT_PERSIST;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = ipadm_door_call(iph, &ifarg, sizeof (ifarg), NULL, 0, B_FALSE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(err));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Remove the IP interface from active configuration. If IPADM_OPT_PERSIST
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * is set in `ipadm_flags', it is also removed from persistent configuration.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_delete_if(ipadm_handle_t iph, const char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint32_t ipadm_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t ret = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t db_status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char tmp_ifname[LIFNAMSIZ];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *cp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct ipadm_addrobj_s ipaddr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t is_persistent =
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (ipadm_flags & IPADM_OPT_PERSIST);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = i_ipadm_unplumb_if(iph, ifname, af);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ret != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto done;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail cp = strrchr(ifname, IPADM_LOGICAL_SEP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (cp != NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail assert(iph->iph_flags & IPH_LEGACY);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * This is a non-zero logical interface.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Find the addrobj and remove it from the daemon's memory.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(tmp_ifname, ifname, sizeof (tmp_ifname));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail tmp_ifname[cp - ifname] = '\0';
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *cp++ = '\0';
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipaddr.ipadm_lifnum = atoi(cp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(ipaddr.ipadm_ifname, tmp_ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (ipaddr.ipadm_ifname));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipaddr.ipadm_af = af;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = i_ipadm_get_lif2addrobj(iph, &ipaddr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ret == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = i_ipadm_delete_addrobj(iph, &ipaddr,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IPADM_OPT_ACTIVE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else if (ret == IPADM_NOTFOUND) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ret);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaildone:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Even if interface does not exist, remove all its addresses and
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * properties from the persistent store. If interface does not
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * exist both in kernel and the persistent store, return IPADM_ENXIO.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((ret == IPADM_ENXIO && is_persistent) || ret == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail db_status = i_ipadm_delete_ifobj(iph, ifname, af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail is_persistent);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (db_status == IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ret = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ret);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Resets all addresses on interface `ifname' with address family `af'
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * from ipmgmtd daemon. If is_persistent = B_TRUE, all interface properties
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and address objects of `ifname' for `af' are also removed from the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * persistent DB.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_delete_ifobj(ipadm_handle_t iph, const char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t is_persistent)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipmgmt_if_arg_t ifarg;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifarg.ia_cmd = IPMGMT_CMD_RESETIF;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifarg.ia_flags = IPMGMT_ACTIVE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (is_persistent)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifarg.ia_flags |= IPMGMT_PERSIST;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifarg.ia_family = af;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(ifarg.ia_ifname, ifname, LIFNAMSIZ);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = ipadm_door_call(iph, &ifarg, sizeof (ifarg), NULL, 0, B_FALSE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(err));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Create the interface by plumbing it for IP.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * This function will check if there is saved configuration information
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for `ifname' and return IPADM_OP_DISABLE_OBJ if the name-space
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for `ifname' is taken.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_create_if(ipadm_handle_t iph, char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint32_t ipadm_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t p_exists;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sa_family_t other_af;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Return error, if the interface already exists in either the active
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * or the persistent configuration.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ipadm_if_enabled(iph, ifname, af))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_IF_EXISTS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram if (!(iph->iph_flags & IPH_LEGACY)) {
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram if (status != IPADM_SUCCESS)
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram return (status);
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram other_af = (af == AF_INET ? AF_INET6 : AF_INET);
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram if (p_exists) {
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram if (!ipadm_if_enabled(iph, ifname, other_af))
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram return (IPADM_OP_DISABLE_OBJ);
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram else
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram ipadm_flags &= ~IPADM_OPT_PERSIST;
913a902882f7ced52ed7832cccd9062aff4c27f4Vasumathi Sundaram }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (i_ipadm_plumb_if(iph, ifname, af, ipadm_flags));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Plumbs an interface. Creates both IPv4 and IPv6 interfaces by
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * default, unless a value in `af' is specified. The interface may be plumbed
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * only if there is no previously saved persistent configuration information
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for the interface (in which case the ipadm_enable_if() function must
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * be used to enable the interface).
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Returns: IPADM_SUCCESS, IPADM_FAILURE, IPADM_IF_EXISTS,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IPADM_IF_PERSIST_EXISTS, IPADM_DLPI_FAILURE,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * or appropriate ipadm_status_t corresponding to the errno.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * `ifname' must point to memory that can hold upto LIFNAMSIZ chars. It may
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * be over-written with the actual interface name when a PPA has to be
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * internally generated by the library.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_create_if(ipadm_handle_t iph, char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint32_t flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t created_v4 = B_FALSE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char newifname[LIFNAMSIZ];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Check for the required authorization */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!ipadm_check_auth())
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_EAUTH);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags == 0 || ((flags & IPADM_OPT_PERSIST) &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail !(flags & IPADM_OPT_ACTIVE)) ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (flags & ~(IPADM_COMMON_OPT_MASK | IPADM_OPT_IPMP |
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IPADM_OPT_GENPPA))) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags & IPADM_OPT_GENPPA) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (snprintf(newifname, LIFNAMSIZ, "%s0", ifname) >=
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail LIFNAMSIZ)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strlcpy(newifname, ifname, LIFNAMSIZ) >= LIFNAMSIZ)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!i_ipadm_validate_ifname(iph, newifname))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((af == AF_INET || af == AF_UNSPEC) &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail !i_ipadm_is_6to4(iph, ifname)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_create_if(iph, ifname, AF_INET, flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail created_v4 = B_TRUE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET6 || af == AF_UNSPEC) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_create_if(iph, ifname, AF_INET6, flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (created_v4) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_delete_if(iph, ifname, AF_INET,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IPADM_OPT_ACTIVE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Deletes the interface in `ifname'. Removes both IPv4 and IPv6 interfaces
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * when `af' = AF_UNSPEC.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_delete_if(ipadm_handle_t iph, const char *ifname, sa_family_t af,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint32_t flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status1 = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status2 = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t other;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Check for the required authorization */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!ipadm_check_auth())
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_EAUTH);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Validate the `ifname' for any logical interface. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags == 0 || (flags & ~(IPADM_COMMON_OPT_MASK)) ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail !i_ipadm_validate_ifname(iph, ifname))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET || af == AF_UNSPEC)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status1 = i_ipadm_delete_if(iph, ifname, AF_INET, flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET6 || af == AF_UNSPEC)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status2 = i_ipadm_delete_if(iph, ifname, AF_INET6, flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If the family has been uniquely identified, we return the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * associated status, even if that is ENXIO. Calls from ifconfig
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * which can only unplumb one of IPv4/IPv6 at any time fall under
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * this category.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (af == AF_INET)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else if (af == AF_INET6)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status2);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else if (af != AF_UNSPEC)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If af is AF_UNSPEC, then we return the following:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * status1, if status1 == status2
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IPADM_SUCCESS, if either of status1 or status2 is SUCCESS
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and the other status is ENXIO
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IPADM_ENXIO, if both status1 and status2 are ENXIO
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * IPADM_FAILURE otherwise.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status1 == status2) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* covers the case when both status1 and status2 are ENXIO */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else if (status1 == IPADM_SUCCESS || status2 == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status1 == IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail other = status2;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail other = status1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (other == IPADM_ENXIO ? IPADM_SUCCESS : IPADM_FAILURE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_FAILURE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Returns information about all interfaces in both active and persistent
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * configuration. If `ifname' is not NULL, it returns only the interface
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * identified by `ifname'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Return values:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * On success: IPADM_SUCCESS.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * On error : IPADM_INVALID_ARG, IPADM_ENXIO or IPADM_FAILURE.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_if_info(ipadm_handle_t iph, const char *ifname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t **if_info, uint32_t flags, int64_t lifc_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifspec_t ifsp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (if_info == NULL || iph == NULL || flags != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifname != NULL &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (!ifparse_ifspec(ifname, &ifsp) || ifsp.ifsp_lunvalid)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_get_all_if_info(iph, ifname, if_info, lifc_flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ifname != NULL && *if_info == NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_ENXIO);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Frees the linked list allocated by ipadm_if_info().
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailvoid
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_free_if_info(ipadm_if_info_t *ifinfo)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_info_t *ifinfo_next;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (; ifinfo != NULL; ifinfo = ifinfo_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifinfo_next = ifinfo->ifi_next;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail free(ifinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Re-enable the interface `ifname' based on the saved configuration
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for `ifname'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_enable_if(ipadm_handle_t iph, const char *ifname, uint32_t flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail nvlist_t *ifnvl;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifspec_t ifsp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Check for the required authorization */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!ipadm_check_auth())
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_EAUTH);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Check for logical interfaces. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!ifparse_ifspec(ifname, &ifsp) || ifsp.ifsp_lunvalid)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Enabling an interface persistently is not supported. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_NOTSUP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Return early by checking if the interface is already enabled.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ipadm_if_enabled(iph, ifname, AF_INET) &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_if_enabled(iph, ifname, AF_INET6)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_IF_EXISTS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Enable the interface and restore all its interface properties
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and address objects.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_init_ifs(iph, ifname, &ifnvl);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail assert(ifnvl != NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * ipadm_enable_if() does exactly what ipadm_init_ifs() does,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * but only for one interface. We need to set IPH_INIT because
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * ipmgmtd daemon does not have to write the interface to persistent
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * db. The interface is already available in persistent db
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and we are here to re-enable the persistent configuration.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail iph->iph_flags |= IPH_INIT;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_init_ifobj(iph, ifname, ifnvl);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail iph->iph_flags &= ~IPH_INIT;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Disable the interface `ifname' by removing it from the active configuration.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Error code return values follow the model in ipadm_delete_if()
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_disable_if(ipadm_handle_t iph, const char *ifname, uint32_t flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status1, status2, other;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ifspec_t ifsp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Check for the required authorization */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!ipadm_check_auth())
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_EAUTH);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Check for logical interfaces. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!ifparse_ifspec(ifname, &ifsp) || ifsp.ifsp_lunvalid)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Disabling an interface persistently is not supported. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags & IPADM_OPT_PERSIST)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_NOTSUP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status1 = i_ipadm_unplumb_if(iph, ifname, AF_INET6);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status1 == IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status1 = i_ipadm_delete_ifobj(iph, ifname, AF_INET6, B_FALSE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status2 = i_ipadm_unplumb_if(iph, ifname, AF_INET);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status2 == IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status2 = i_ipadm_delete_ifobj(iph, ifname, AF_INET, B_FALSE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status1 == status2) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status2);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else if (status1 == IPADM_SUCCESS || status2 == IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status1 == IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail other = status2;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail other = status1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (other == IPADM_ENXIO ? IPADM_SUCCESS : IPADM_FAILURE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_FAILURE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail/*
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * This workaround is until libipadm supports IPMP and is required whenever an
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * interface is moved into an IPMP group. Since libipadm doesn't support IPMP
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * yet, we will have to update the daemon's in-memory mapping of
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * `aobjname' to 'lifnum'.
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail *
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * For `IPMGMT_ACTIVE' case, i_ipadm_delete_ifobj() would only fail if
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * door_call(3C) fails. Also, there is no use in returning error because
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail * `ifname' would have been successfuly moved into IPMP group, by this time.
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail */
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbailvoid
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbailipadm_if_move(ipadm_handle_t iph, const char *ifname)
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail{
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail (void) i_ipadm_delete_ifobj(iph, ifname, AF_INET, B_FALSE);
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail (void) i_ipadm_delete_ifobj(iph, ifname, AF_INET6, B_FALSE);
36b41818c9fdc5e94b00eddbfd784080b2760c58Girish Moodalbail}