ncu_ip.c revision 6ba597c56d749c61b4f783157f63196d7b2445f0
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/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Use is subject to license terms.
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 <inetcfg.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libnwam.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <netinet/in.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdlib.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <strings.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/socket.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/types.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
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *start_dhcp_thread(void *);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void nwamd_down_interface(const char *, uint_t, int);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t stateless_running(const nwamd_ncu_t *);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeychar *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_sockaddr_to_str(const struct sockaddr *sockaddr, char *str, size_t len)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_sockaddr_to_str(sockaddr->sa_family, sockaddr, str, len) !=
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (str);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_log_if_address(int severity, struct nwamd_if_address *nifa)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char str[INET6_ADDRSTRLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(severity, "%s address %s is %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nifa->address.sa_family == AF_INET ? "IPv4" : "IPv6",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_sockaddr_to_str(&nifa->address, str, sizeof (str)),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nifa->configured ? "configured" : "not configured");
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_dhcp_release(const char *ifname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_reply_t *reply = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_request_t *request;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int rc;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Now allocate and send the request */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey request = dhcp_ipc_alloc_request(DHCP_RELEASE, ifname, NULL, 0,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DHCP_TYPE_NONE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (request == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_dhcp_release: dhcp_ipc_alloc_request : "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s", strerror(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = dhcp_ipc_make_request(request, &reply, 1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(request);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(reply);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey reply = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Fall back to drop request */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey request = dhcp_ipc_alloc_request(DHCP_DROP, ifname, NULL, 0,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DHCP_TYPE_NONE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (request == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_dhcp_release: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "dhcp_ipc_alloc_request : %s", strerror(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) dhcp_ipc_make_request(request, &reply, 1);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(request);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(reply);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyadd_ip_address(const char *ifname, struct nwamd_if_address *nifa,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t logical_if)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t h, newh;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t intf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int rc;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in bcastaddr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char str[INET6_ADDRSTRLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol = nifa->address.sa_family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "add_ip_address: %s address %s for link %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey logical_if ? "adding" : "setting",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_sockaddr_to_str(&nifa->address, str, sizeof (str)),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_open(&h, &intf) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "add_ip_address: icfg_open failed on %s", ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * When working with the physical interface, we need to be careful
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * to set the prefixlen and broadcast addresses before setting the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * IP address, otherwise RTM_DELADDRs for the old broadcast/netmask
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * will confuse us into thinking we've lost the address we've just
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * assigned.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (logical_if) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = icfg_add_addr(h, &newh,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (const struct sockaddr *)&nifa->address,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol == AF_INET ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey newh = h;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Make sure DHCP is no longer running */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(newh, &flags) == ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (flags & IFF_DHCPRUNNING) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "add_ip_address: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "turning off DHCP for %s", ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_dhcp_release(ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Set interface IFF_UP if not already. Do this and
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * setting of prefixlen/broadcast addresses as otherwise
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * these can trigger an RTM_DELADDR that makes it appear
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * that the address has gone away.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = icfg_set_addr(newh,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (const struct sockaddr *)&nifa->address,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol == AF_INET ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (struct sockaddr_in) :
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (struct sockaddr_in6));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "add_ip_address: add of ipaddr failed "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for %s: %d", ifname, rc);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto out;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (nifa->prefix != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((rc = icfg_set_prefixlen(newh, nifa->prefix))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "add_ip_address: icfg_set_prefix %d "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "failed on %s: %s", nifa->prefix, ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_errmsg(rc));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (intf.if_protocol == AF_INET) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Set broadcast address based on address, prefixlen */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey bcastaddr.sin_addr.s_addr =
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((struct sockaddr_in *)&nifa->address)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ->sin_addr.s_addr |
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey htonl(0xffffffff >> nifa->prefix);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((rc = icfg_set_broadcast(newh, &bcastaddr))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "add_ip_address: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_set_broadcast(%s) failed on %s: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey inet_ntoa(bcastaddr.sin_addr), ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_errmsg(rc));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc == ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(newh, &flags) == ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((flags & IFF_UP) == 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = icfg_set_flags(newh, flags | IFF_UP);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "add_ip_address: couldn't bring up %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyout:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Check if address was a duplicate */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc == ICFG_DAD_FOUND || (flags & IFF_DUPLICATE) != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *object_name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_INFO, "add_ip_address: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "duplicate address detected on %s", ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((err = nwam_ncu_name_to_typed_name(ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_NCU_TYPE_INTERFACE, &object_name)) == NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey object_name, NWAM_STATE_MAINTENANCE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_AUX_STATE_IF_DUPLICATE_ADDR);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(object_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "add_ip_address: could not "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "create state event for %s: %s", ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_strerror(err));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = ICFG_DAD_FOUND;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (h != newh)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(newh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (rc == ICFG_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_add_default_routes(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_if_t *nif = &ncu->ncu_node.u_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 "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "route %s", nwamd_sockaddr_to_str
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((struct sockaddr *)&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 "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "route %s", nwamd_sockaddr_to_str
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((struct sockaddr *)&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. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_dhcp_inform(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_dhcp_thread_arg *arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *name = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_attr_t attr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg = malloc(sizeof (*arg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (arg == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_dhcp_inform: error allocating memory "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for dhcp request");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg->name = strdup(ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg->type = DHCP_INFORM;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg->timeout = DHCP_IPC_WAIT_DEFAULT;
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) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "Cannot start dhcp thread");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(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}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyaddresses_match(const struct sockaddr *addr1, const struct sockaddr *addr2)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (addr1->sa_family != addr2->sa_family)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (addr1->sa_family) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (memcmp(&((struct sockaddr_in *)addr1)->sin_addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &((struct sockaddr_in *)addr2)->sin_addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (struct in_addr)) == 0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET6:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (memcmp(&((struct sockaddr_in6 *)addr1)->sin6_addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &((struct sockaddr_in6 *)addr2)->sin6_addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (struct in6_addr)) == 0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
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 *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyfind_static_address(const struct sockaddr *addr, const nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char str[INET6_ADDRSTRLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "find_static_address %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_sockaddr_to_str(addr, str, sizeof (str)));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (n = nifa; n != NULL; n = n->next) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (addresses_match(addr, &n->address))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (n);
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
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * in the NCU. dhcp is used to detemrine if the DHCP (stateful for v6)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * structure is needed or the stateless/autoconf structure for the given
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * family. dhcp should be B_TRUE if looking for v4. Will only return the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * nwamd_if_address if the relevant address is configured (v4 DHCP, v6
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * stateless/stateful) for the NCU.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Returns NULL if structure is not found.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic struct nwamd_if_address *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyfind_nonstatic_address(const nwamd_ncu_t *ncu, ushort_t family, boolean_t dhcp)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey const nwamd_if_t *u_if = &ncu->ncu_node.u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "find_nonstatic_address: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp ? "dhcp" : "stateless");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (n = nifa; n != NULL; n = n->next) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (family == AF_INET) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!dhcp)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (n->address.sa_family == family && n->dhcp_if &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_dhcp_configured)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (n);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (family == AF_INET6) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (n->address.sa_family == family) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (dhcp && n->dhcp_if &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateful_configured)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (n);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey else if (!dhcp && n->stateless_if &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateless_configured)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (n);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Sets "configured" nwam_if_address value for corresponding address.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Used when we process IF_STATE events to handle RTM_NEWADDR/DELADDRs.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyupdate_address_configured_value(const struct sockaddr *configured_addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_ncu_t *ncu, boolean_t configured)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *n;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char str[INET6_ADDRSTRLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "update_address_configured_value(%s, %s, %s)",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_sockaddr_to_str(configured_addr, str, sizeof (str)),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name, configured ? "configure" : "unconfigure");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n = find_static_address(configured_addr, ncu);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (n) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n->configured = configured;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "update_address_configured_value: marking "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "address %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_sockaddr_to_str(&n->address, str, sizeof (str)));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_update_addresses_unconfigured(nwamd_ncu_t *ncu, sa_family_t af)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (n = nifa; n != NULL; n = n->next)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (af == AF_UNSPEC || n->address.sa_family == af) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n->configured = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_log_if_address(LOG_DEBUG, n);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
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
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (n = ncu->ncu_node.u_if.nwamd_if_list; n != NULL; n = n->next) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((family == AF_UNSPEC || family == n->address.sa_family) &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n->configured && !n->dhcp_if && !n->stateless_if)
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{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t *iflist;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t ifh;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int numif, i;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_storage addr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey socklen_t len;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int prefixlen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t rv = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_if_list(&iflist, &numif, protocol, ICFG_PLUMBED) !=
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 0; i < numif; i++) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strncmp(iflist[i].if_name, ncu->ncu_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strlen(ncu->ncu_name)) != 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_open(&ifh, &iflist[i]) != ICFG_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* is this address an expected static one? */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey len = sizeof (addr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_addr(ifh, (struct sockaddr *)&addr, &len,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &prefixlen, B_FALSE) != ICFG_SUCCESS ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey find_static_address((struct sockaddr *)&addr, ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
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 &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((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(
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &((struct sockaddr_in6 *)&addr)->sin6_addr))) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(ifh, &flags) == ICFG_SUCCESS &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (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 icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rv = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_free_if_list(iflist);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (rv);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag 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;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if = &ncu->ncu_node.u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (u_if->nwamd_if_dhcp_requested) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey anyv4_requested = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *a;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (a = u_if->nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey a != NULL && a->address.sa_family != AF_INET;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey a = a->next)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Empty loop body */;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (a != 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
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;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if = &ncu->ncu_node.u_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 {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *a;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (a = u_if->nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey a != NULL && a->address.sa_family != AF_INET6;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey a = a->next)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Empty loop body */;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (a != 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
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/* Callback to find if DHCP is running on the interface index */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyflags_set_for_ifindex_cb(icfg_if_t *intf, void *arg, uint64_t flags_wanted)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int *indexp = arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t h;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int index;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_open(&h, intf) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "flags_set_for_ifindex_cb: icfg_open failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_index(h, &index) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "flags_set_for_ifindex_cb: icfg_get_index failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (index != *indexp) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(h, &flags) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "flags_set_for_ifindex_cb: icfg_get_flags failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return ((flags & flags_wanted) == flags_wanted);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystateless_running_for_ifindex_cb(icfg_if_t *intf, void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (flags_set_for_ifindex_cb(intf, arg,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey IFF_RUNNING | IFF_ADDRCONF | IFF_UP));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Is autoconf running on the interface with specified ifindex?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystateless_running_for_ifindex(int ifindex)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (icfg_iterate_if(AF_INET6, ICFG_PLUMBED, &ifindex,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey stateless_running_for_ifindex_cb) != 0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystateless_running(const nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int index;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t intf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t ifh;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol = AF_INET6;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(intf.if_name, ncu->ncu_name, sizeof (intf.if_name));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_open(&ifh, &intf) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "stateless_running: icfg_open(%s) failed",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_index(ifh, &index) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "stateless_running: icfg_get_index(%s) failed",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (stateless_running_for_ifindex(index));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_configure_interface_addresses(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *nifa = ncu->ncu_node.u_if.nwamd_if_list;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *n;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int num_configured_v4 = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t add_logical_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_configure_interface_addresses(%s)",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Add static addresses. For IPv4, we only use the physical interface
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * (i.e. not a logical interface) if DHCP has not been requested and
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * this is the first address to be configured.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (n = nifa; n != NULL; n = n->next) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (n->configured || n->dhcp_if || n->stateless_if)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (n->address.sa_family) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey add_logical_if = (num_configured_v4 > 0 ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_node.u_if.nwamd_if_dhcp_requested);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey num_configured_v4++;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET6:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey add_logical_if = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey n->configured = add_ip_address(ncu->ncu_name, n,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey add_logical_if);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeylifnum_from_ifname(const char *ifname)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *lifstr = strchr(ifname, ':');
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (lifstr != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey lifstr++;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (atoi(lifstr));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Copies the ifname (with lifnum) associated with the given address.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Returns B_TRUE if a match is found, B_FASLE otherwise.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic boolean_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyifname_for_addr(const struct sockaddr *caddr, char *ifname, int len)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in6 addr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int numif, i, prefixlen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t *iflist;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t ifh;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey socklen_t slen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_if_list(&iflist, &numif, caddr->sa_family, ICFG_PLUMBED)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "ifname_for_addr: icfg_get_if_list failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey for (i = 0; i < numif; i++) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_open(&ifh, &iflist[i]) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "ifname_for_addr: icfg_open %s failed",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey iflist[i].if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey slen = sizeof (addr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_addr(ifh, (struct sockaddr *)&addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &slen, &prefixlen, B_FALSE) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "ifname_for_addr: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_get_addr %s failed", iflist[i].if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Compare addresses */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (addresses_match((struct sockaddr *)&addr, caddr)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(ifname, iflist[i].if_name, len);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_free_if_list(iflist);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_free_if_list(iflist);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (B_FALSE);
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) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "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;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t stateless_running;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char addrstr[INET6_ADDRSTRLEN], ifname[LIFNAMSIZ];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t v4dhcp_running;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t v6dhcp_running;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *nifa;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr *addr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey boolean_t static_addr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t intf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t ifh;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_if_t *u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ushort_t family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int lifnum;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if_state = &evm->nwe_data.nwe_if_state;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if = &ncu->ncu_node.u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey family = if_state->nwe_addr.ss_family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addr = (struct sockaddr *)&if_state->nwe_addr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_event: addr %s %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_sockaddr_to_str(addr, addrstr, sizeof (addrstr)),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey evm->nwe_data.nwe_if_state.nwe_addr_added ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "added" : "removed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* determine the interface name with lifnum */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (if_state->nwe_addr_added) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* figure out the ifname for the address */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!ifname_for_addr(addr, ifname, sizeof (ifname))) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_event:"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "could not find ifname for %s", addrstr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Figure out the ifname that had the address that was
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * removed. The address is already gone from the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * interface, so cannot walk the interface list.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_if_address *n;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((n = find_static_address(addr, ncu)) == NULL &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (n = find_nonstatic_address(ncu, family, B_TRUE))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (n = find_nonstatic_address(ncu, family, B_FALSE))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwamd_ncu_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "could not find nwamd_if_address for %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addrstr);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(ifname, n->ifname, sizeof (ifname));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_ncu_handle_if_state_event: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "ifname for %s is %s", addrstr, ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Get interface flags using nwe_ifname as it is logical
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * interface name.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol = family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey lifnum = lifnum_from_ifname(intf.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_open(&ifh, &intf) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_ncu_handle_if_state_event: can't "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "find if %s", intf.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(ifh, &flags) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: can't "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "get flags for %s", icfg_if_name(ifh));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If the interface is unplumbed, icfg_get_flags()
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * will fail. Don't exit, continue with empty flags.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (if_state->nwe_addr_added) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (family == AF_INET && !if_state->nwe_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 /*LINTED*/
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (((struct sockaddr_in *)addr)->sin_addr.s_addr
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey == INADDR_ANY) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey socklen_t slen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in s;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int pfxlen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((flags & IFF_UP) &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey !(flags & IFF_RUNNING) &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_get_addr(ifh, (struct sockaddr *)&s,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &slen, &pfxlen, B_FALSE) == ICFG_SUCCESS &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.sin_addr.s_addr != INADDR_ANY) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "bug workaround: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "clear out addr %s on %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey inet_ntoa(s.sin_addr), ifname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey s.sin_addr.s_addr = INADDR_ANY;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) icfg_set_addr(ifh,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (const struct sockaddr *)&s, slen);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Has 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 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!if_state->nwe_addr_added && !(flags & IFF_DUPLICATE)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_storage ifaddr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey socklen_t len;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int plen;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey len = family == AF_INET ? sizeof (struct sockaddr_in) :
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (struct sockaddr_in6);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_addr(ifh, (struct sockaddr *)&ifaddr, &len,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &plen, B_FALSE) == ICFG_SUCCESS &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addresses_match(addr, (struct sockaddr *)&ifaddr)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG,
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",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addrstr, intf.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_do_not_send(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(ifh);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey stateless_running = (family == AF_INET6) &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((flags & STATELESS_RUNNING) == STATELESS_RUNNING);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4dhcp_running = (family == AF_INET) &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((flags & DHCP_RUNNING) == DHCP_RUNNING);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v6dhcp_running = (family == AF_INET6) &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((flags & DHCP_RUNNING) == DHCP_RUNNING);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey static_addr = (find_static_address(addr, ncu) != NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (if_state->nwe_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 * [Note that since we use DHCP inform on interfaces
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * with static addresses that they will also have the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * DHCP flag set on the interface.]
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 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Figure out if we want to keep this address. */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (static_addr) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nifa = find_static_address(addr, ncu);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey assert(nifa != NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nifa->configured = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(nifa->ifname, ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (nifa->ifname));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (u_if->nwamd_if_dhcp_requested &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4dhcp_running) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_dhcp_configured = B_TRUE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nifa = find_nonstatic_address(ncu, family,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey assert(nifa != NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(nifa->ifname, ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (nifa->ifname));
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 nifa = find_nonstatic_address(ncu, family,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey assert(nifa != NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(nifa->ifname, ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (nifa->ifname));
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;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nifa = find_nonstatic_address(ncu, family,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey assert(nifa != NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(nifa->ifname, ifname,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (nifa->ifname));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This is something we didn't expect. Remove
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * it by unplumbing the logical interface.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (u_if->nwamd_if_dhcp_requested &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey v4dhcp_running)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_dhcp_release(ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (lifnum == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_down_interface(ncu->ncu_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey lifnum, family);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey interface_ncu_down(ncu);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_unplumb_interface(ncu, lifnum,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey family);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
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 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) update_address_configured_value(addr, ncu,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey 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 }
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 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (static_addr) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) update_address_configured_value(addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu, B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (family == AF_INET) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_dhcp_configured = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (family == AF_INET6) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The address is already gone. I'm not sure
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * how we figure out if this address is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * stateful (DHCP) or stateless. When we
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * are managing IPv6 more explicitly this will
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * have to be done more carefully.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateful_configured = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateless_configured = B_FALSE;
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 }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyexit:
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/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This function downs any logical interface and just zeros the address off of
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * the physical interface (logical interface 0). If you want to unplumb 0 then
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * you need to call nwamd_unplumb_interface() directly.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_down_interface(const char *linkname, uint_t lifnum, int family)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t intf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t h;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_error_t rc;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (linkname == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_down_interface: linkname null");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nwamd_link_to_ifname(linkname, lifnum, intf.if_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (intf.if_name));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol = family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = icfg_open(&h, &intf);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_down_interface: icfg_open failed for %s: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s", intf.if_name, icfg_errmsg(rc));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (lifnum == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in6 addr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) memset(&addr, 0, sizeof (addr));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey addr.sin6_family = family;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_set_addr(h, (struct sockaddr *)&addr,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey family == AF_INET ? sizeof (struct sockaddr_in) :
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (struct sockaddr_in6)) != ICFG_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_down_interface couldn't zero "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "address on %s", h->ifh_interface.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(h, &flags) == ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_set_flags(h, flags & ~IFF_UP) != ICFG_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_down_interface: couldn't "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "bring %s down", h->ifh_interface.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_down_interface: icfg_get_flags "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "failed on %s", h->ifh_interface.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_plumb_unplumb_interface(nwamd_ncu_t *ncu, uint_t lifnum,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int af, boolean_t plumb)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t intf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t h;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_error_t rc;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_if_t *u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey const char *linkname = ncu->ncu_name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (linkname == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: linkname null");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nwamd_link_to_ifname(linkname, lifnum, intf.if_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (intf.if_name));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol = af;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_plumb_unplumb_interface: %s %s on link %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey plumb ? "plumbing" : "unplumbing",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey af == AF_INET ? "IPv4" : "IPv6", linkname);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Before unplumbing, do a DHCP release if lifnum is 0. Otherwise
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * dhcpagent can get confused.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!plumb && af == AF_INET && lifnum == 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_dhcp_release(ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = icfg_open(&h, &intf);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_open failed for %s: %s", intf.if_name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_errmsg(rc));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = plumb ? icfg_plumb(h) : icfg_unplumb(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((plumb && rc != ICFG_EXISTS) ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (!plumb && rc != ICFG_NO_EXIST)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "%s %s failed for %s: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey plumb ? "plumb" : "unplumb",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey af == AF_INET ? "IPv4" : "IPv6",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_name, icfg_errmsg(rc));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (plumb) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(h, &flags) == ICFG_SUCCESS &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (flags & IFF_UP) == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_set_flags(h, flags | IFF_UP) != ICFG_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "couldn't bring %s up",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey h->ifh_interface.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_get_flags failed on %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey h->ifh_interface.if_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if = &ncu->ncu_node.u_if;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (!plumb) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_update_addresses_unconfigured(ncu, af);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (af) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_dhcp_configured = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case AF_INET6:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateful_configured = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey u_if->nwamd_if_stateless_configured = B_FALSE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey break;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_plumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, int af)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_plumb_unplumb_interface(ncu, lifnum, af, B_TRUE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_unplumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, int af)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_plumb_unplumb_interface(ncu, lifnum, af, B_FALSE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic void *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystart_dhcp_thread(void *arg)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_dhcp_thread_arg *thread_arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_reply_t *reply = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_request_t *request;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_type_t type;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int timeout;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int rc, retries = 0;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey thread_arg = (struct nwamd_dhcp_thread_arg *)arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey timeout = thread_arg->timeout;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name = thread_arg->name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey type = thread_arg->type;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Try starting agent, though it may already be there */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_to_root();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = dhcp_start_agent(DHCP_IPC_MAX_WAIT);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_from_root();
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "Unable to start %s", DHCP_AGENT_PATH);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyretry:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Now allocate and send the request */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey request = dhcp_ipc_alloc_request(type, name, NULL, 0,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DHCP_TYPE_NONE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (request == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "start_dhcp: dhcp_ipc_alloc_request : %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strerror(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = dhcp_ipc_make_request(request, &reply, timeout);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(request);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "start_dhcp %s: %s", name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_strerror(rc));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = reply->return_code;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc != 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc == DHCP_IPC_E_TIMEOUT && timeout == 0) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * DHCP timed out: change state for this NCU and enqueue
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * event to check NCU priority-groups. Only care for
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * DHCP requests (not informs).
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc == DHCP_IPC_E_TIMEOUT && type != DHCP_INFORM) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *object_name;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_INFO, "start_dhcp: DHCP timed out for %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name);
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: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "nwam_ncu_name_to_typed_name failed");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
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
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(object_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if (rc == DHCP_IPC_E_RUNNING) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * DHCP is already running. Check if IP address is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * already configured on the interface.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_handle_t h;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_if_t intf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct sockaddr_in sin;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey socklen_t alen = sizeof (struct sockaddr_in);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int plen, index;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey uint64_t flags;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_t ip_event;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: DHCP already running on %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) strlcpy(intf.if_name, name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey sizeof (intf.if_name));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey intf.if_protocol = AF_INET;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_open(&h, &intf) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_open failed on %s", name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Get address */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_addr(h, (struct sockaddr *)&sin, &alen,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey &plen, B_FALSE) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_get_addr failed on %s: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name, strerror(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto bail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Check if 0.0.0.0 */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (sin.sin_addr.s_addr == INADDR_ANY) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: empty address on %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto bail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* valid address exists, get the flags, index of intf */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_flags(h, &flags) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_get_flags failed on %s", name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto bail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (icfg_get_index(h, &index) != ICFG_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp: "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "icfg_get_index failed on %s", name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto bail;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* synthesize an IF_STATE event with the intf's flags */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ip_event = nwamd_event_init_if_state(name, flags,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey B_TRUE, index, (struct sockaddr *)&sin);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (ip_event != NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwamd_event_enqueue(ip_event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeybail:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey icfg_close(h);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else if ((rc == DHCP_IPC_E_SOCKET ||
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc == DHCP_IPC_E_INVIF) && retries++ < NWAMD_DHCP_RETRIES) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Retry DHCP request as we may have been unplumbing
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * as part of the configuration phase.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp %s: %s; will retry in %d sec",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey name, dhcp_ipc_strerror(rc),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc == DHCP_IPC_E_INVIF ?
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAMD_DHCP_RETRY_WAIT_TIME : 0);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (rc == DHCP_IPC_E_INVIF)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) sleep(NWAMD_DHCP_RETRY_WAIT_TIME);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto retry;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey } else {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "start_dhcp %s: %s", name,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey dhcp_ipc_strerror(rc));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto failed;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* If status was the command, then output the results */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (DHCP_IPC_CMD(type) == DHCP_STATUS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "%s", dhcp_status_hdr_string());
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "%s", dhcp_status_reply_to_string(reply));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyfailed:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(reply);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (arg != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(arg);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwamd_start_dhcp(nwamd_ncu_t *ncu)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct nwamd_dhcp_thread_arg *arg;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char *name = NULL;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey pthread_attr_t attr;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_DEBUG, "nwamd_start_dhcp: starting DHCP for %s %d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ncu->ncu_name, ncu->ncu_type);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg = malloc(sizeof (*arg));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (arg == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_start_dhcp: error allocating memory "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "for dhcp request");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg->name = strdup(ncu->ncu_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg->type = DHCP_START;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey arg->timeout = ncu_wait_time;
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) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nlog(LOG_ERR, "nwamd_start_dhcp: cannot start dhcp thread");
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(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}