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/*
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * This file contains the functions that are required for communicating
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * with in.ndpd while creating autoconfigured addresses.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <stdio.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <stdlib.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <string.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <strings.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <errno.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <fcntl.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <unistd.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/sockio.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/types.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/stat.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/socket.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <netinet/in.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <inet/ip.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <arpa/inet.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <assert.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <poll.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <ipadm_ndpd.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include "libipadm_impl.h"
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#define NDPDTIMEOUT 5000
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#define PREFIXLEN_LINKLOCAL 10
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t i_ipadm_create_linklocal(ipadm_handle_t,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_addrobj_t);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic void i_ipadm_make_linklocal(struct sockaddr_in6 *,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail const struct in6_addr *);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t i_ipadm_send_ndpd_cmd(const char *,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail const struct ipadm_addrobj_s *, int);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Sends message to in.ndpd asking not to do autoconf for the given interface,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * until IPADM_CREATE_ADDRS or IPADM_ENABLE_AUTOCONF is sent.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_disable_autoconf(const char *ifname)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (i_ipadm_send_ndpd_cmd(ifname, NULL, IPADM_DISABLE_AUTOCONF));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Sends message to in.ndpd to enable autoconf for the given interface,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * until another IPADM_DISABLE_AUTOCONF is sent.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_enable_autoconf(const char *ifname)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (i_ipadm_send_ndpd_cmd(ifname, NULL, IPADM_ENABLE_AUTOCONF));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_create_ipv6addrs(ipadm_handle_t iph, ipadm_addrobj_t addr,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint32_t i_flags)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Create the link local based on the given token. If the same intfid
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * was already used with a different address object, this step will
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * fail.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_create_linklocal(iph, addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Request in.ndpd to start the autoconfiguration.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If autoconfiguration was already started by another means (e.g.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * "ifconfig" ), in.ndpd will return EEXIST.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (addr->ipadm_stateless || addr->ipadm_stateful) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_send_ndpd_cmd(addr->ipadm_ifname, addr,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IPADM_CREATE_ADDRS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status != IPADM_NDPD_NOT_RUNNING) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_delete_addr(iph, addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Persist the intfid. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_addr_persist(iph, addr, B_FALSE, i_flags);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status != IPADM_SUCCESS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_delete_addr(iph, addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) i_ipadm_send_ndpd_cmd(addr->ipadm_ifname, addr,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IPADM_DELETE_ADDRS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_delete_ipv6addrs(ipadm_handle_t iph, ipadm_addrobj_t ipaddr)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Send a msg to in.ndpd to remove the autoconfigured addresses,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and delete the link local that was created.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_send_ndpd_cmd(ipaddr->ipadm_ifname, ipaddr,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail IPADM_DELETE_ADDRS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status == IPADM_NDPD_NOT_RUNNING)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = IPADM_SUCCESS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (status == IPADM_SUCCESS)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = i_ipadm_delete_addr(iph, ipaddr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_create_linklocal(ipadm_handle_t iph, ipadm_addrobj_t addr)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail boolean_t addif = B_FALSE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct sockaddr_in6 *sin6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct lifreq lifr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_status_t status;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail in6_addr_t ll_template = {0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram * Create a logical interface if needed.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaramretry:
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram status = i_ipadm_do_addif(iph, addr);
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram if (status != IPADM_SUCCESS)
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram return (status);
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram if (!(iph->iph_flags & IPH_INIT)) {
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram status = i_ipadm_setlifnum_addrobj(iph, addr);
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram if (status == IPADM_ADDROBJ_EXISTS)
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram goto retry;
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram if (status != IPADM_SUCCESS)
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram bzero(&lifr, sizeof (lifr));
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram (void) strlcpy(lifr.lifr_name, addr->ipadm_ifname, LIFNAMSIZ);
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram i_ipadm_addrobj2lifname(addr, lifr.lifr_name, sizeof (lifr.lifr_name));
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
ec3706caae60369bd59b4a7a2de365fc74637504Vasumathi Sundaram
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Create the link-local address */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&lifr.lifr_addr, sizeof (lifr.lifr_addr));
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (void) plen2mask(PREFIXLEN_LINKLOCAL, AF_INET6,
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (struct sockaddr *)&lifr.lifr_addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((err = ioctl(iph->iph_sock6, SIOCSLIFNETMASK, (caddr_t)&lifr)) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (addr->ipadm_intfidlen == 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If we have to use the default interface id,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * we just need to set the prefix to the link-local prefix.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * SIOCSLIFPREFIX sets the address with the given prefix
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and the default interface id.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6->sin6_addr = ll_template;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = ioctl(iph->iph_sock6, SIOCSLIFPREFIX, (caddr_t)&lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (err < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Make a linklocal address in sin6 and set it */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail i_ipadm_make_linklocal(sin6, &addr->ipadm_intfid.sin6_addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail err = ioctl(iph->iph_sock6, SIOCSLIFADDR, (caddr_t)&lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (err < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((err = ioctl(iph->iph_sock6, SIOCGLIFFLAGS, (char *)&lifr)) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_flags |= IFF_UP;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((err = ioctl(iph->iph_sock6, SIOCSLIFFLAGS, (char *)&lifr)) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_SUCCESS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailfail:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (errno == EEXIST)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = IPADM_ADDRCONF_EXISTS;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail status = ipadm_errno2status(errno);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Remove the linklocal that was created. */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (addif) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) ioctl(iph->iph_sock6, SIOCLIFREMOVEIF, (caddr_t)&lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail } else {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct sockaddr_in6 *sin6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail lifr.lifr_flags &= ~IFF_UP;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) ioctl(iph->iph_sock6, SIOCSLIFFLAGS, (caddr_t)&lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6->sin6_family = AF_INET6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6->sin6_addr = in6addr_any;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) ioctl(iph->iph_sock6, SIOCSLIFADDR, (caddr_t)&lifr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (status);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Make a linklocal address based on the given intfid and copy it into
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * the output parameter `sin6'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic void
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_make_linklocal(struct sockaddr_in6 *sin6, const struct in6_addr *intfid)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int i;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail in6_addr_t ll_template = {0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6->sin6_family = AF_INET6;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6->sin6_addr = *intfid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (i = 0; i < 4; i++) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6->sin6_addr.s6_addr[i] =
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sin6->sin6_addr.s6_addr[i] | ll_template.s6_addr[i];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Function that forms an ndpd msg and sends it to the in.ndpd daemon's loopback
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * listener socket.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ipadm_status_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaili_ipadm_send_ndpd_cmd(const char *ifname, const struct ipadm_addrobj_s *addr,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int cmd)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int fd;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct sockaddr_un servaddr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int flags;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ipadm_ndpd_msg_t msg;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int retval;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (addr == NULL &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (cmd == IPADM_CREATE_ADDRS || cmd == IPADM_DELETE_ADDRS)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_INVALID_ARG);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail fd = socket(AF_UNIX, SOCK_STREAM, 0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (fd == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_FAILURE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Put the socket in non-blocking mode */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail flags = fcntl(fd, F_GETFL, 0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (flags != -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) fcntl(fd, F_SETFL, flags | O_NONBLOCK);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* Connect to in.ndpd */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&servaddr, sizeof (servaddr));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail servaddr.sun_family = AF_UNIX;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(servaddr.sun_path, IPADM_UDS_PATH,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (servaddr.sun_path));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (connect(fd, (struct sockaddr *)&servaddr, sizeof (servaddr)) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&msg, sizeof (msg));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail msg.inm_cmd = cmd;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(msg.inm_ifname, ifname, sizeof (msg.inm_ifname));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (addr != NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail msg.inm_intfid = addr->ipadm_intfid;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail msg.inm_intfidlen = addr->ipadm_intfidlen;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail msg.inm_stateless = addr->ipadm_stateless;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail msg.inm_stateful = addr->ipadm_stateful;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (cmd == IPADM_CREATE_ADDRS) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strlcpy(msg.inm_aobjname, addr->ipadm_aobjname,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail sizeof (msg.inm_aobjname));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ipadm_ndpd_write(fd, &msg, sizeof (msg)) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (ipadm_ndpd_read(fd, &retval, sizeof (retval)) < 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto fail;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) close(fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (cmd == IPADM_CREATE_ADDRS && retval == EEXIST)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_ADDRCONF_EXISTS);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (ipadm_errno2status(retval));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailfail:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) close(fd);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (IPADM_NDPD_NOT_RUNNING);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Attempt to read `buflen' worth of bytes from `fd' into the buffer pointed
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * to by `buf'.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_ndpd_read(int fd, void *buffer, size_t buflen)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int retval;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ssize_t nbytes = 0; /* total bytes processed */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ssize_t prbytes; /* per-round bytes processed */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct pollfd pfd;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail while (nbytes < buflen) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail pfd.fd = fd;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail pfd.events = POLLIN;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Wait for data to come in or for the timeout to fire.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail retval = poll(&pfd, 1, NDPDTIMEOUT);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (retval <= 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (retval == 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail errno = ETIME;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Descriptor is ready; have at it.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail prbytes = read(fd, (caddr_t)buffer + nbytes, buflen - nbytes);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (prbytes <= 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (prbytes == -1 && errno == EINTR)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail nbytes += prbytes;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (nbytes == buflen ? 0 : -1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Write `buflen' bytes from `buffer' to open file `fd'. Returns 0
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * if all requested bytes were written, or an error code if not.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailipadm_ndpd_write(int fd, const void *buffer, size_t buflen)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail size_t nwritten;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ssize_t nbytes;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail const char *buf = buffer;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (nwritten = 0; nwritten < buflen; nwritten += nbytes) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail nbytes = write(fd, &buf[nwritten], buflen - nwritten);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (nbytes == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (nbytes == 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail errno = EIO;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail assert(nwritten == buflen);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}