6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER START
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The contents of this file are subject to the terms of the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Common Development and Distribution License (the "License").
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You may not use this file except in compliance with the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * or http://www.opensolaris.org/os/licensing.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * See the License for the specific language governing permissions
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * and limitations under the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner]
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER END
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <arpa/inet.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <assert.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <dhcpagent_ipc.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <dhcp_inittab.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <dhcp_symbol.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <dhcpagent_util.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <errno.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <execinfo.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libnwam.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdlib.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <strings.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <ucontext.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <unistd.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libscf.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "conditions.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "events.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "ncp.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "ncu.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "objects.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "util.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * ncu_ip.c - contains routines that are IP interface-specific for NCUs.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define STATELESS_RUNNING (IFF_RUNNING | IFF_UP | IFF_ADDRCONF)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define DHCP_RUNNING (IFF_RUNNING | IFF_UP | IFF_DHCPRUNNING)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic void nwamd_dhcp(const char *, ipadm_addrobj_t, dhcp_ipc_type_t);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic void nwamd_down_interface(const char *, ipadm_addr_type_t, const char *);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t stateless_running(const nwamd_ncu_t *);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Given a sockaddr representation of an IPv4 or IPv6 address returns the
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * string representation. Note that 'sockaddr' should point at the correct
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * sockaddr structure for the address family (sockaddr_in for AF_INET or
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * structure.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic const char *
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeynwamd_sockaddr2str(const struct sockaddr *addr, char *str, size_t len)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct sockaddr_in *sin;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct sockaddr_in6 *sin6;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey const char *straddr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (addr == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (addr->sa_family == AF_INET) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* LINTED E_BAD_PTR_CAST_ALIGN */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sin = (struct sockaddr_in *)addr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey straddr = inet_ntop(AF_INET, (void *)&sin->sin_addr, str, len);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else if (addr->sa_family == AF_INET6) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* LINTED E_BAD_PTR_CAST_ALIGN */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sin6 = (struct sockaddr_in6 *)addr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey straddr = inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, str,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey errno = EINVAL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (straddr != NULL ? str : NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_propogate_link_up_down_to_ip(const char *linkname, boolean_t up)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ip_ncu = nwamd_ncu_object_find(NWAM_NCU_TYPE_INTERFACE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ip_ncu == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_propogate_link_up_down_to_ip: no IP NCU "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for link %s, cannot propogate %s event", linkname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey up ? "up" : "down");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ip_ncu->nwamd_object_data;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu->ncu_enabled) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ip_ncu->nwamd_object_aux_state ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_UNINITIALIZED) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_propogate_link_up_down_to_ip: will not "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "propogate link %s event as IP NCU %s is being "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "removed", up ? "up" : "down", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_propogate_link_up_down_to_ip: propogating "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "link %s event to interface %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey up ? "up" : "down", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ip_ncu->nwamd_object_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey up ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE :
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey up ? NWAM_AUX_STATE_INITIALIZED :
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_CONDITIONS_NOT_MET);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_propogate_link_up_down_to_ip: not propogating "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "link %s event to interface %s, IP NCU is disabled",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey up ? "up" : "down", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ip_ncu);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Returns the value associated with the given symbol for the given
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * interface. The interface may be NULL, in which case the primary
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * interface is used.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This function substitutes the need to call dhcpinfo(1), thus it is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * very similar to the implementation of dhcpinfo(1).
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * When multiple values need to be returned (e.g., nameservers), they
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * are separated by a space ' '.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeychar *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_get_dhcpinfo_data(const char *sym_name, char *ifname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_symbol_t *entry;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_optnum_t optnum;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_request_t *request;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_reply_t *reply;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DHCP_OPT *opt;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey size_t opt_len;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *value; /* return value */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char errmsg[LINE_MAX];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* if interface is not given, change it to empty string */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ifname == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifname = "";
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* find code and category in dhcp_inittab(4) */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey entry = inittab_getbyname(ITAB_CAT_SITE | ITAB_CAT_STANDARD |
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ITAB_CAT_VENDOR | ITAB_CAT_FIELD, ITAB_CONS_INFO, sym_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (entry == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(errmsg, LINE_MAX, "unknown identifier: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sym_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto fail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* allocate request */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey optnum.code = entry->ds_code;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey optnum.category = entry->ds_category;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey optnum.size = entry->ds_max * inittab_type_to_size(entry);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey request = dhcp_ipc_alloc_request(DHCP_GET_TAG, ifname, &optnum,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (dhcp_optnum_t), DHCP_TYPE_OPTNUM);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (request == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(errmsg, LINE_MAX, "failed dhcp alloc request");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto fail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* make the request */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey err = dhcp_ipc_make_request(request, &reply, DHCP_IPC_WAIT_DEFAULT);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (err != 0 || reply->return_code != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(errmsg, LINE_MAX, "%s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_strerror(err == 0 ? reply->return_code : err));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* get data from the reply */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey opt = dhcp_ipc_get_data(reply, &opt_len, NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (opt_len == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(errmsg, LINE_MAX, "invalid data");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto fail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* check protocol error */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (opt_len < 2 || (opt_len -2 != opt->len)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(errmsg, LINE_MAX, "data length mismatch");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto fail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey opt_len -= 2;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* decode the data into ascii */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey value = inittab_decode(entry, opt->value, opt_len, B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (value == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(errmsg, LINE_MAX, "cannot decode reply");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto fail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(request);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(reply);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (value);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyfail:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "get_dhcpinfo_data() failed: %s", errmsg);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(request);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(reply);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_add_default_routes(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_if_t *nif = &ncu->ncu_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char str[INET6_ADDRSTRLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nif->nwamd_if_ipv4 && nif->nwamd_if_ipv4_default_route_set) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in v4dest, v4mask;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4dest.sin_addr.s_addr = htonl(INADDR_ANY);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4dest.sin_family = AF_INET;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4mask.sin_addr.s_addr = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4mask.sin_family = AF_INET;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_add_default_routes: adding default "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "route %s", nwamd_sockaddr2str((struct sockaddr *)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey &nif->nwamd_if_ipv4_default_route, str,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (str)));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_add_route((struct sockaddr *)&v4dest,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (struct sockaddr *)&v4mask,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (struct sockaddr *)&nif->nwamd_if_ipv4_default_route,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nif->nwamd_if_ipv6 && nif->nwamd_if_ipv6_default_route_set) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in6 v6dest, v6mask;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) bzero(&v6dest, sizeof (struct sockaddr_in6));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v6dest.sin6_family = AF_INET6;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) bzero(&v6mask, sizeof (struct sockaddr_in6));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v6mask.sin6_family = AF_INET6;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_add_default_routes: adding default "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "route %s", nwamd_sockaddr2str((struct sockaddr *)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey &nif->nwamd_if_ipv6_default_route, str,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (str)));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_add_route((struct sockaddr *)&v6dest,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (struct sockaddr *)&v6mask,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (struct sockaddr *)&nif->nwamd_if_ipv6_default_route,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Returns the nwamd_if_address structure for the given static address,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * NULL if not found.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic struct nwamd_if_address *
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyfind_static_address(const struct sockaddr_storage *addr, const nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct sockaddr_storage saddr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char str[INET6_ADDRSTRLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "find_static_address: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_sockaddr2str((struct sockaddr *)addr, str, sizeof (str)));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifap->ipaddr_atype != IPADM_ADDR_STATIC ||
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_get_addr(nifap->ipaddr, &saddr) != IPADM_SUCCESS)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey continue;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (sockaddrcmp(addr, &saddr))
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (nifap);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Returns the nwamd_if_address structure representing the non-static address
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * in the NCU. For IPv6, both stateless and stateful (DHCPv6) share the same
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * nwamd_if_address. Will only return the nwamd_if_address if the relevant
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * address is configured (v4 DHCP, v6 either stateless or stateless) for the
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * NCU. Returns NULL if the structure is not found.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic struct nwamd_if_address *
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyfind_nonstatic_address(const nwamd_ncu_t *ncu, sa_family_t family)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey const nwamd_if_t *u_if = &ncu->ncu_if;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "find_nonstatic_address for %s %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (family == AF_INET ? "IPv4" : "IPv6"), ncu->ncu_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifap->ipaddr_atype == IPADM_ADDR_STATIC)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (family == AF_INET) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifap->ipaddr_atype == IPADM_ADDR_DHCP &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if->nwamd_if_dhcp_requested)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (nifap);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (family == AF_INET6) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifap->ipaddr_atype == IPADM_ADDR_IPV6_ADDRCONF &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (u_if->nwamd_if_stateful_requested ||
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if->nwamd_if_stateless_requested))
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (nifap);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Returns the nwamd_if_address structure that configured the given address,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * NULL if not found.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic struct nwamd_if_address *
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyfind_configured_address(const struct sockaddr_storage *addr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey const nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char str[INET6_ADDRSTRLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "find_configured_address: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_sockaddr2str((struct sockaddr *)addr, str, sizeof (str)));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (sockaddrcmp(addr, &nifap->conf_addr) ||
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sockaddrcmp(addr, &nifap->conf_stateless_addr))
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (nifap);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Are one or more static addresses configured?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyboolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_static_addresses_configured(nwamd_ncu_t *ncu, sa_family_t family)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *n;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (n = ncu->ncu_if.nwamd_if_list; n != NULL; n = n->next) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (n->ipaddr_atype != IPADM_ADDR_STATIC)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey continue;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((family == AF_UNSPEC || family == n->family) &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey n->configured)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "no static addresses configured for %s", ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Is DHCP probably managing an address on this index. We decide that it is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * probably managing an address if there is an interface with IFF_DHCP set
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * that isn't in our set of static addresses. Note that IFF_DHCP gets set
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * on static addresses when we do a dhcp inform and if that list has changed
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * recently then the result of this function could be erronous.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyboolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_dhcp_managing(int protocol, nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed struct sockaddr_storage addr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t rv = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *addrinfo, *a;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((ipstatus = ipadm_addr_info(ipadm_handle, ncu->ncu_name, &addrinfo,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey 0, 0)) != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "nwamd_dhcp_managing: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_addr_info failed for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu->ncu_name, ipadm_status2str(ipstatus));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (a = addrinfo; a != NULL; a = IA_NEXT(a)) {
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed /*
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed * WARNING: This memcpy() assumes knowledge of the
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed * implementation of getifaddrs() and that it always
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed * uses sockaddr_storage as the backing store for
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed * address information, thus making it possible to
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed * copy the entire structure rather than do it on
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed * the size of the sockaddr according to family.
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed * This assumption is made elsewhere in this file.
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed */
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (void) memcpy(&addr, a->ia_ifa.ifa_addr, sizeof (addr));
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* is this address an expected static one? */
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed if (find_static_address(&addr, ncu) != NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * For IPv4, DHCPRUNNING flag is set when dhcpagent is in
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the process of getting an address, but doesn't have one
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * yet (interface has 0.0.0.0). For IPv6, DHCPRUNNING flag
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * is set on the link-local address if trying to get a
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * stateful address. In both cases, consider the interface
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * as not being managed by DHCP and skip checking of flags.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((protocol == AF_INET &&
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed ((struct sockaddr_in *)&addr)->sin_addr.s_addr ==
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey INADDR_ANY) ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (protocol == AF_INET6 &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey IN6_IS_ADDR_LINKLOCAL(
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed &((struct sockaddr_in6 *)&addr)->sin6_addr))) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey flags = a->ia_ifa.ifa_flags;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (flags & IFF_DHCPRUNNING) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If we get here we have an address that has the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * DHCP flag set and isn't an expected static address.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rv = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(addrinfo);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (rv);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Return B_TRUE if IPv4 is requested in the given NCU.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_v4_requested(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t anyv4_requested;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_if_t *u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey anyv4_requested = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if = &ncu->ncu_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (u_if->nwamd_if_dhcp_requested) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey anyv4_requested = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *n;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (n = u_if->nwamd_if_list; n != NULL; n = n->next) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (n->family == AF_INET &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey n->ipaddr_atype == IPADM_ADDR_STATIC)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (n != NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey anyv4_requested = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (anyv4_requested);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Returns B_TRUE if IPv6 is requested in the given NCU.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_v6_requested(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t anyv6_requested;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_if_t *u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey anyv6_requested = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if = &ncu->ncu_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (u_if->nwamd_if_stateful_requested ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateless_requested) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey anyv6_requested = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *n;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (n = u_if->nwamd_if_list; n != NULL; n = n->next) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (n->family == AF_INET6 &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey n->ipaddr_atype == IPADM_ADDR_STATIC)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (n != NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey anyv6_requested = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (anyv6_requested);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Bring up the ncu if we have the right combination of requested configuration
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * and actual configuration and up is true, or bring down the ncu if no
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * addresses are configured, and up is false.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyinterface_ncu_up_down(nwamd_ncu_t *ncu, boolean_t up)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t ncu_online;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey assert(ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If V4 with or without V6 is configured then one of its interfaces
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * needs to be up for the ncu to come online. If only V6 is requested
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * then one of its interfaces needs to be up for the ncu to come online.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_online = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nwamd_v4_requested(ncu)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nwamd_dhcp_managing(AF_INET, ncu) ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_static_addresses_configured(ncu, AF_INET))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_online = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (nwamd_v6_requested(ncu)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((nwamd_dhcp_managing(AF_INET6, ncu) ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey stateless_running(ncu) ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_static_addresses_configured(ncu, AF_INET6)))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_online = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nwam_ncu_name_to_typed_name(ncu->ncu_name, ncu->ncu_type, &name) !=
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "interface_ncu_up_down: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwam_ncu_name_to_typed_name failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_online && up) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "interface_ncu_up_down: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "bringing %s up", name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_OFFLINE_TO_ONLINE, NWAM_AUX_STATE_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (!ncu_online && !up) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "interface_ncu_up_down: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "bringing %s down", name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_ONLINE_TO_OFFLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_DOWN);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyinterface_ncu_up(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey interface_ncu_up_down(ncu, B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyinterface_ncu_down(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey interface_ncu_up_down(ncu, B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic boolean_t
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystateless_running(const nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *ainfo, *ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey boolean_t rv = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((ipstatus = ipadm_addr_info(ipadm_handle, ncu->ncu_name, &ainfo,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey 0, 0)) != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "stateless_running: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_addr_info failed for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu->ncu_name, ipadm_status2str(ipstatus));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed if (ainfop->ia_ifa.ifa_addr->sa_family != AF_INET6)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey continue;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey flags = ainfop->ia_ifa.ifa_flags;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (flags & STATELESS_RUNNING) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey rv = B_TRUE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(ainfo);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (rv);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Returns the addrinfo associated with the given address. There is always
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * only one addrinfo for each address.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyaddrinfo_for_addr(const struct sockaddr_storage *caddr, const char *ifname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t **ainfo)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *addrinfo, *ainfop, *last = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_addr_info(ipadm_handle, ifname, &addrinfo, 0, 0);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ipstatus != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_INFO, "addrinfo_for_addr: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_addr_info failed for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname, ipadm_status2str(ipstatus));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (B_FALSE);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey *ainfo = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (ainfop = addrinfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed struct sockaddr_storage addr;
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (void) memcpy(&addr, ainfop->ia_ifa.ifa_addr, sizeof (addr));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * If addresses match, rearrange pointers so that addrinfo
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * does not contain a, and return a.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed if (sockaddrcmp(&addr, caddr)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (last != NULL)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey last->ia_ifa.ifa_next = ainfop->ia_ifa.ifa_next;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey else
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo = IA_NEXT(ainfop);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ainfop->ia_ifa.ifa_next = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey *ainfo = ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey last = ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(addrinfo);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (*ainfo == NULL ? B_FALSE : B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Returns B_TRUE if the addrinfo associated with the given ipaddr using its
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * aobjname is found. An addrinfo list is created and returned in ainfo.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Stateless and stateful IPv6 addrinfo have the same aobjname, thus the need
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * to create a list of addrinfo.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyaddrinfo_for_ipaddr(ipadm_addrobj_t ipaddr, const char *ifname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t **ainfo)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char aobjname[IPADM_AOBJSIZ];
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *addrinfo, *ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *last = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_get_aobjname(ipaddr, aobjname, sizeof (aobjname));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ipstatus != IPADM_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_addr_info(ipadm_handle, ifname, &addrinfo, 0, 0);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ipstatus != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_INFO, "addrinfo_for_ipaddr: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_addr_info failed for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname, ipadm_status2str(ipstatus));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey *ainfo = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ainfop = addrinfo;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey while (ainfop != NULL) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* If aobjnames match, rearrange pointers to create new list */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (strcmp(ainfop->ia_aobjname, aobjname) == 0) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *match = ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ainfop = IA_NEXT(ainfop); /* move iterator */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (last != NULL)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey last->ia_ifa.ifa_next = match->ia_ifa.ifa_next;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey else
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo = ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (*ainfo == NULL)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey match->ia_ifa.ifa_next = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey else
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey match->ia_ifa.ifa_next = &(*ainfo)->ia_ifa;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey *ainfo = match;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey last = ainfop;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ainfop = IA_NEXT(ainfop);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(addrinfo);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (*ainfo == NULL ? B_FALSE : B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Add the address provided in the nwamd_if_address. If DHCP is required,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * start DHCP. If a static address is configured, create the address; then do
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * a DHCP_INFORM (in a separate thread) to get other networking configuration
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * parameters. RTM_NEWADDRs - translated into IF_STATE events - will then
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * finish the job of bringing the NCU online.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic boolean_t
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeldadd_ip_address(const char *ifname, const struct nwamd_if_address *nifa,
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld boolean_t *do_inform)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *addrinfo = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifa->ipaddr_atype == IPADM_ADDR_DHCP) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * To make getting a DHCP address asynchronous, call
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * ipadm_create_addr() in a new thread.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "add_ip_address: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "adding IPv4 DHCP address on %s", ifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_dhcp(ifname, nifa->ipaddr, DHCP_START);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "add_ip_address: adding %s address on %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (nifa->ipaddr_atype == IPADM_ADDR_STATIC ?
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "STATIC" : "IPv6 ADDRCONF"), ifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((ipstatus = ipadm_create_addr(ipadm_handle, nifa->ipaddr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey IPADM_OPT_ACTIVE | IPADM_OPT_UP)) != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "add_ip_address: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_create_addr failed on %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname, ipadm_status2str(ipstatus));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (B_FALSE);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * When creating a static address, ipadm_create_addr() returns
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * SUCCESS even if duplicate address is detected. Retrieve
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * the addrinfo to get the flags.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifa->ipaddr_atype == IPADM_ADDR_STATIC) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Since we are configuring a static address, there
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * will be just *ONE* addrinfo with the aobjname in
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * nifa->ipaddr.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (!addrinfo_for_ipaddr(nifa->ipaddr, ifname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey &addrinfo)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "add_ip_address: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "could not find addrinfo on %s", ifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (B_FALSE);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey flags = addrinfo->ia_ifa.ifa_flags;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(addrinfo);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (flags & IFF_DUPLICATE) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char *object_name;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwam_error_t err;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_INFO, "add_ip_address: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "duplicate address detected on %s", ifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((err = nwam_ncu_name_to_typed_name(ifname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey NWAM_NCU_TYPE_INTERFACE, &object_name))
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey == NWAM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_object_set_state(
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey NWAM_OBJECT_TYPE_NCU,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey object_name, NWAM_STATE_MAINTENANCE,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey NWAM_AUX_STATE_IF_DUPLICATE_ADDR);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey free(object_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "add_ip_address: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "could not create state event "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname, nwam_strerror(err));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (B_FALSE);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld /*
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld * Do DHCP_INFORM using async ipadm_refresh_addr().
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld * Only need to do this once per interface, and we
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld * do *not* need to do it if we are also getting a
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld * dhcp lease; so we only send the INFORM if the
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld * passed-in flag says to, and we clear the flag
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld * once we've initiated the INFORM transaction.
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld */
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld if (*do_inform) {
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld nwamd_dhcp(ifname, nifa->ipaddr, DHCP_INFORM);
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld *do_inform = B_FALSE;
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Adds addresses for the given NCU.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyvoid
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeynwamd_configure_interface_addresses(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld boolean_t do_inform;
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld /* only need an inform if we're not also getting a dhcp lease */
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld do_inform = !ncu->ncu_if.nwamd_if_dhcp_requested;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_configure_interface_addresses(%s)",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu->ncu_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (nifap = nifa; nifap != NULL; nifap = nifap->next) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifap->configured)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld nifap->configured = add_ip_address(ncu->ncu_name, nifap,
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld &do_inform);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This event tells us that an interface address has appeared or disappeared,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * or that the interface flags on an interface have changed.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_ncu_handle_if_state_event(nwamd_event_t event)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_event_t evm;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_state_t state;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_aux_state_t aux_state;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj == NULL) {
f6904bc3cbac0d84f41b1eb2ed9489a8f221695cRenee Danson Sommerfeld nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: no object %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu = ncu_obj->nwamd_object_data;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey evm = event->event_msg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey state = ncu_obj->nwamd_object_state;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey aux_state = ncu_obj->nwamd_object_aux_state;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "if %s, state (%s, %s)", event->event_object,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_state_to_string(state), nwam_aux_state_to_string(aux_state));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Ensure object is in correct state to handle IF state events */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (state) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case NWAM_STATE_OFFLINE_TO_ONLINE:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (aux_state != NWAM_AUX_STATE_IF_WAITING_FOR_ADDR &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey aux_state != NWAM_AUX_STATE_IF_DHCP_TIMED_OUT) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "if %s is in invalid aux state %s for IF_STATE "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "events", event->event_object,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_aux_state_to_string(aux_state));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case NWAM_STATE_ONLINE:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We can get addresses from DHCP after we've taken the interface down.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We deal with those below.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case NWAM_STATE_ONLINE_TO_OFFLINE:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case NWAM_STATE_OFFLINE:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "if %s is in invalid state %s for IF_STATE events",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object, nwam_state_to_string(state));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (evm->nwe_data.nwe_if_state.nwe_addr_valid) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwam_event_if_state *if_state;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char addrstr[INET6_ADDRSTRLEN];
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey boolean_t static_addr, addr_added;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey boolean_t v4dhcp_running, v6dhcp_running, stateless_running;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *ai = NULL, *addrinfo = NULL;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey boolean_t stateless_ai_found = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey boolean_t stateful_ai_found = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *nifa = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_if_t *u_if;
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed struct sockaddr_storage *addr, ai_addr, *aip = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ushort_t family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if_state = &evm->nwe_data.nwe_if_state;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if = &ncu->ncu_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey family = if_state->nwe_addr.ss_family;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addr = &if_state->nwe_addr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addr_added = if_state->nwe_addr_added;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_event: addr %s %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_sockaddr2str((struct sockaddr *)addr, addrstr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sizeof (addrstr)), addr_added ? "added" : "removed");
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Need to get flags for this interface. Get the addrinfo for
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * the address that generated this IF_STATE event.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (addr_added) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Address was added. Find the addrinfo for this
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * address and the nwamd_if_address corresponding to
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * this address.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (!addrinfo_for_addr(addr, ncu->ncu_name, &ai)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "nwamd_ncu_handle_if_state_event: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "addrinfo doesn't exist for %s", addrstr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto valid_done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo = ai;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey flags = addrinfo->ia_ifa.ifa_flags;
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (void) memcpy(&ai_addr, addrinfo->ia_ifa.ifa_addr,
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed sizeof (ai_addr));
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed aip = &ai_addr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (addrinfo->ia_atype == IPADM_ADDR_IPV6_ADDRCONF ||
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo->ia_atype == IPADM_ADDR_DHCP)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nifa = find_nonstatic_address(ncu, family);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey else if (addrinfo->ia_atype == IPADM_ADDR_STATIC)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nifa = find_static_address(addr, ncu);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * If nwamd_if_address is not found, then this address
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * isn't one that nwamd created. Remove it.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifa == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_event: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "address %s not managed by nwam added, "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "removing it", addrstr);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_down_interface(addrinfo->ia_aobjname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo->ia_atype, ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto valid_done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* check flags to determine how intf is configured */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey stateless_running = (family == AF_INET6) &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ((flags & STATELESS_RUNNING) == STATELESS_RUNNING);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey v4dhcp_running = (family == AF_INET) &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ((flags & DHCP_RUNNING) == DHCP_RUNNING);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey v6dhcp_running = (family == AF_INET6) &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ((flags & DHCP_RUNNING) == DHCP_RUNNING);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey static_addr = (addrinfo->ia_atype == IPADM_ADDR_STATIC);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* copy the configured address into nwamd_if_address */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (stateless_running) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (void) memcpy(&nifa->conf_stateless_addr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo->ia_ifa.ifa_addr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sizeof (struct sockaddr_storage));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (void) memcpy(&nifa->conf_addr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo->ia_ifa.ifa_addr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sizeof (struct sockaddr_storage));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Address was removed. Find the nwamd_if_address
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * that configured this address.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nifa = find_configured_address(addr, ncu);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (nifa == NULL) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "nwamd_ncu_handle_if_state_event: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "address %s not managed by nwam removed, "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "nothing to do", addrstr);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_event_do_not_send(event);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto valid_done;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (addrinfo_for_ipaddr(nifa->ipaddr, ncu->ncu_name,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey &ai)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *a;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (a = ai; a != NULL; a = IA_NEXT(a)) {
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed struct sockaddr_storage stor;
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (void) memcpy(&stor, a->ia_ifa.ifa_addr,
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed sizeof (stor));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Since multiple addrinfo can have
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * the same ipaddr, find the one for
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * the address that generated this
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * state event.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed if (sockaddrcmp(addr, &stor)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey flags = a->ia_ifa.ifa_flags;
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed (void) memcpy(&ai_addr,
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed a->ia_ifa.ifa_addr,
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed sizeof (ai_addr));
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed aip = &ai_addr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo = a;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Stateful and stateless IPv6
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * addrinfo have the same aobjname.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Use the flags to determine which
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * address is present in the system.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (family == AF_INET6) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey stateless_ai_found =
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (a->ia_ifa.ifa_flags &
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey STATELESS_RUNNING);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey stateful_ai_found =
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (a->ia_ifa.ifa_flags &
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey DHCP_RUNNING);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Set the flags in the event for listeners */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey evm->nwe_data.nwe_if_state.nwe_flags = flags;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (family == AF_INET && !addr_added) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Check for failure due to CR 6745448: if we get a
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * report that an address has been deleted, then check
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * for interface up, datalink down, and actual address
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * non-zero. If that combination is seen, then this is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * a DHCP cached lease, and we need to remove it from
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the system, or it'll louse up the kernel routes
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * (which aren't smart enough to avoid dead
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * interfaces).
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (((struct sockaddr_in *)addr)->sin_addr.s_addr
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed == INADDR_ANY && aip != 0) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct sockaddr_in *a;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char astr[INET6_ADDRSTRLEN];
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed a = (struct sockaddr_in *)aip;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((flags & IFF_UP) &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey !(flags & IFF_RUNNING) &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey a->sin_addr.s_addr != INADDR_ANY) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "nwamd_ncu_handle_if_state_event: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "bug workaround: clear out addr "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "%s on %s", nwamd_sockaddr2str
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ((struct sockaddr *)a, astr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sizeof (astr)),
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu->ncu_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_down_interface(
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo->ia_aobjname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey IPADM_ADDR_DHCP, ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto valid_done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * If we received an RTM_NEWADDR and the IFF_UP flags has not
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * been set, ignore this IF_STATE event. Once the IFF_UP flag
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * is set, we'll get another RTM_NEWADDR message.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (addr_added & !(flags & IFF_UP)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "address %s added on %s without IFF_UP flag (%x), "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ignoring IF_STATE event",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrstr, ncu->ncu_name, flags);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_event_do_not_send(event);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto valid_done;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Has the address really been removed? Sometimes spurious
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * RTM_DELADDRs are generated, so we need to ensure that
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the address is really gone. If IFF_DUPLICATE is set,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * we're getting the RTM_DELADDR due to DAD, so don't test
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * in that case.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (!addr_added && !(flags & IFF_DUPLICATE)) {
64639aaf7beb84086b88f186ea1fa9ccf0be8c57Darren Reed if (aip != 0 && sockaddrcmp(addr, aip)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_INFO,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "address %s is not really gone from %s, "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "ignoring IF_STATE event",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrstr, ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto valid_done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (addr_added) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Address has been added.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We need to make sure that we really want to keep
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * this address. There is a race where we requested an
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * address but by the time we got here we don't really
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * want it and need to remove it.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Once we decide we want the address adjust the ncu
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * state accordingly. For example if this address is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * enough move online.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (u_if->nwamd_if_dhcp_requested && v4dhcp_running) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_dhcp_configured = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (u_if->nwamd_if_stateful_requested &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v6dhcp_running) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateful_configured = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (u_if->nwamd_if_stateless_requested &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey stateless_running) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateless_configured = B_TRUE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else if (!static_addr) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This is something we didn't expect. Remove
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * the address.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_down_interface(addrinfo->ia_aobjname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey addrinfo->ia_atype, ncu->ncu_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nifa->configured = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto valid_done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The address looks valid so mark configured and
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * move online if we either have a v4 address if
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * v4 is configured or a v6 address if only v6 is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * configured.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nifa->configured = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (state != NWAM_STATE_ONLINE)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey interface_ncu_up(ncu);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Refresh network/location since we may also have other
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * DHCP information. We might have to restore it first
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * in case it is in maintenance.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "refreshing %s as we may have other "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "DHCP information", NET_LOC_FMRI);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) smf_restore_instance(NET_LOC_FMRI);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (smf_refresh_instance(NET_LOC_FMRI) != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "event: refresh of %s "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "failed", NET_LOC_FMRI);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (state == NWAM_STATE_ONLINE ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey state == NWAM_STATE_OFFLINE_TO_ONLINE) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Address has been removed. Only pay attention to
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * disappearing addresses if we are online or coming
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * online.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Undo whatever configuration is necessary. Note
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * that this may or may not cause the NCU to go down.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We can get RTM_DELADDRs for duplicate addresses
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * so deal with this seperately.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nifa->configured = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (!static_addr && family == AF_INET) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_dhcp_configured = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else if (!static_addr && family == AF_INET6) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * The address is already gone. When looking
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * for the addrinfo (using aobjname in
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * ipaddr), we found addrinfo for either one
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * or both stateless and stateful. Using the
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * flags we determined whether each was
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * configured or not. Update the flags here
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * accordingly.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if->nwamd_if_stateful_configured =
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey stateless_ai_found;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if->nwamd_if_stateless_configured =
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey stateful_ai_found;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (flags & IFF_DUPLICATE) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_INFO,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "duplicate address detected on %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_STATE_MAINTENANCE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_IF_DUPLICATE_ADDR);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey interface_ncu_down(ncu);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyvalid_done:
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(ai);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_ncu_handle_if_action_event(nwamd_event_t event)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "if action event %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event->event_object[0] == '\0' ? "n/a" : event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu_obj = nwamd_object_find(NWAM_OBJECT_TYPE_NCU, event->event_object);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ncu_obj == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_if_action_event: no object");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * Remove the address in the given aobjname. IPADM_OPT_RELEASE is specified
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * for a DHCP address and specifies that the DHCP lease should also be released.
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey * ifname is only used for nlog().
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeynwamd_down_interface(const char *aobjname, ipadm_addr_type_t atype,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey const char *ifname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey uint32_t rflags = (atype == IPADM_ADDR_DHCP ? IPADM_OPT_RELEASE : 0);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_down_interface: %s [aobjname = %s]",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname, aobjname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((ipstatus = ipadm_delete_addr(ipadm_handle, aobjname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey IPADM_OPT_ACTIVE | rflags)) != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "nwamd_down_interface: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_delete_addr failed on %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname, ipadm_status2str(ipstatus));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic void
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeyunconfigure_addresses(nwamd_ncu_t *ncu, sa_family_t af)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (nifap = nifa; nifap != NULL; nifap = nifap->next)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (af == AF_UNSPEC || nifap->family == af)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nifap->configured = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeydhcp_release(const char *ifname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addr_info_t *ainfo, *ainfop;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ipadm_addr_info(ipadm_handle, ifname, &ainfo, 0, 0)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey != IPADM_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ainfop->ia_atype == IPADM_ADDR_DHCP)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_down_interface(ainfop->ia_aobjname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ainfop->ia_atype, ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_free_addr_info(ainfo);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic void
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeynwamd_plumb_unplumb_interface(nwamd_ncu_t *ncu, sa_family_t af, boolean_t plumb)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char *ifname = ncu->ncu_name;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_if_t *u_if = &ncu->ncu_if;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_plumb_unplumb_interface: %s %s %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (plumb ? "plumb" : "unplumb"), (af == AF_INET ? "IPv4" : "IPv6"),
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (plumb) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_create_if(ipadm_handle, ifname, af,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey IPADM_OPT_ACTIVE);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey } else {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* release DHCP address, if any */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (af == AF_INET)
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey dhcp_release(ifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_delete_if(ipadm_handle, ifname, af,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey IPADM_OPT_ACTIVE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ipstatus != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((plumb && ipstatus != IPADM_IF_EXISTS) ||
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (!plumb && ipstatus != IPADM_ENXIO)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s %s failed for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (plumb ? "plumb" : "unplumb"),
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey (af == AF_INET ? "IPv4" : "IPv6"),
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ifname, ipadm_status2str(ipstatus));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Unset flags */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!plumb) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey unconfigure_addresses(ncu, af);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (af) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey case AF_INET:
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if->nwamd_if_dhcp_configured = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey case AF_INET6:
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if->nwamd_if_stateful_configured = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey u_if->nwamd_if_stateless_configured = B_FALSE;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeynwamd_plumb_interface(nwamd_ncu_t *ncu, sa_family_t af)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
38f140aaa4a32508dc5318744dd8d51ab84b23a5Michael Hunter /*
38f140aaa4a32508dc5318744dd8d51ab84b23a5Michael Hunter * We get all posssible privs by calling nwamd_deescalate(). During
38f140aaa4a32508dc5318744dd8d51ab84b23a5Michael Hunter * startup opening /dev/dld (data link management) needs all privs
38f140aaa4a32508dc5318744dd8d51ab84b23a5Michael Hunter * because we don't have access to /etc/security/device_policy yet.
38f140aaa4a32508dc5318744dd8d51ab84b23a5Michael Hunter */
38f140aaa4a32508dc5318744dd8d51ab84b23a5Michael Hunter nwamd_escalate();
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_plumb_unplumb_interface(ncu, af, B_TRUE);
38f140aaa4a32508dc5318744dd8d51ab84b23a5Michael Hunter nwamd_deescalate();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeynwamd_unplumb_interface(nwamd_ncu_t *ncu, sa_family_t af)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_plumb_unplumb_interface(ncu, af, B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystart_dhcp_thread(void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey struct nwamd_dhcp_thread_arg *thread_arg = arg;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_object_t ncu_obj;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_type_t type;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *name;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_addrobj_t ipaddr;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipadm_status_t ipstatus;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey int retries = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name = thread_arg->name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey type = thread_arg->type;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipaddr = thread_arg->ipaddr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyretry:
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey /* Make sure the NCU is in appropriate state for DHCP command */
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_INTERFACE, name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ncu_obj == NULL) {
48fff0e3de5e66bd25183e5fcb5f172d19057078Renee Danson Sommerfeld nlog(LOG_ERR, "start_dhcp: no IP object %s", name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if (ncu_obj->nwamd_object_state != NWAM_STATE_OFFLINE_TO_ONLINE &&
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ncu_obj->nwamd_object_state != NWAM_STATE_ONLINE) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_INFO, "start_dhcp: IP NCU %s is in invalid state "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "for DHCP command", ncu_obj->nwamd_object_name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_object_release(ncu_obj);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nwamd_object_release(ncu_obj);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey switch (type) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey case DHCP_INFORM:
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey char aobjname[IPADM_AOBJSIZ];
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey if ((ipstatus = ipadm_get_aobjname(ipaddr, aobjname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey sizeof (aobjname))) != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "ipadm_get_aobjname failed for %s: %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey name, ipadm_status2str(ipstatus));
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_refresh_addr(ipadm_handle, aobjname,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey IPADM_OPT_ACTIVE | IPADM_OPT_INFORM);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey break;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey case DHCP_START:
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey ipstatus = ipadm_create_addr(ipadm_handle, ipaddr,
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey IPADM_OPT_ACTIVE);
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey break;
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey default:
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: invalid dhcp_ipc_type_t: %d", type);
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey goto done;
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey if (ipstatus == IPADM_DHCP_IPC_TIMEOUT) {
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey /*
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey * DHCP timed out: for DHCP_START requests, change state for
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey * this NCU and euqueue event to check NCU priority-groups;
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey * for DHCP_INFORM requests, nothing to do.
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey */
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey if (type == DHCP_START) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *object_name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey nlog(LOG_INFO,
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey "start_dhcp: DHCP_START timed out for %s", name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nwam_ncu_name_to_typed_name(name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_NCU_TYPE_INTERFACE, &object_name)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: "
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey "nwam_ncu_name_to_typed_name failed for %s",
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey goto done;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey object_name, NWAM_STATE_OFFLINE_TO_ONLINE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_IF_DHCP_TIMED_OUT);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_create_ncu_check_event(0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(object_name);
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey } else {
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey nlog(LOG_INFO,
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey "start_dhcp: DHCP_INFORM timed out for %s", name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey } else if ((ipstatus == IPADM_DHCP_IPC_ERROR ||
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey ipstatus == IPADM_IPC_ERROR) && retries++ < NWAMD_DHCP_RETRIES) {
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey /*
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey * Retry DHCP request as we may have been unplumbing as part
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey * of the configuration phase.
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey */
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: ipadm_%s_addr on %s returned: %s, "
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey "retrying in %d sec",
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey (type == DHCP_START ? "create" : "refresh"), name,
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey ipadm_status2str(ipstatus), NWAMD_DHCP_RETRY_WAIT_TIME);
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey (void) sleep(NWAMD_DHCP_RETRY_WAIT_TIME);
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey goto retry;
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey } else if (ipstatus != IPADM_SUCCESS) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: ipadm_%s_addr failed for %s: %s",
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey (type == DHCP_START ? "create" : "refresh"), name,
3dbbe3fb79c81fac93e4001bdf68eb06c8a086e8Anurag S. Maskey ipadm_status2str(ipstatus));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeydone:
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey free(name);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey free(arg);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeystatic void
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskeynwamd_dhcp(const char *ifname, ipadm_addrobj_t ipaddr, dhcp_ipc_type_t cmd)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_dhcp_thread_arg *arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_attr_t attr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_dhcp: starting DHCP %s thread for %s",
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey dhcp_ipc_type_to_string(cmd), ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg = malloc(sizeof (*arg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (arg == NULL) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "nwamd_dhcp: error allocating memory for "
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey "dhcp request");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey arg->name = strdup(ifname);
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey arg->type = cmd;
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey arg->ipaddr = ipaddr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_attr_init(&attr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (pthread_create(NULL, &attr, start_dhcp_thread, arg) == -1) {
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey nlog(LOG_ERR, "nwamd_dhcp: cannot start dhcp thread");
f6da83d4178694e7113b71d1e452f15b296f73d8Anurag S. Maskey free(arg->name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(arg);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_attr_destroy(&attr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_attr_destroy(&attr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}