diff --git a/exception_lists/packaging b/exception_lists/packaging index 483ddfe7ccb1..9e6b1378f289 100644 --- a/exception_lists/packaging +++ b/exception_lists/packaging @@ -258,17 +258,6 @@ usr/lib/llib-linstzones.ln usr/lib/llib-lpkg usr/lib/llib-lpkg.ln # -# These files are installed in the proto area by the build of libinetcfg. -# Only the shared object is shipped. -# -lib/libinetcfg.so -lib/llib-linetcfg -lib/llib-linetcfg.ln -usr/include/inetcfg.h -usr/lib/libinetcfg.so -usr/lib/llib-linetcfg -usr/lib/llib-linetcfg.ln -# # Don't ship header files private to libipmp and in.mpathd # usr/include/ipmp_query_impl.h diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint index d378ac798f51..7064e0231f6b 100644 --- a/usr/src/Makefile.lint +++ b/usr/src/Makefile.lint @@ -371,7 +371,6 @@ COMMON_SUBDIRS = \ lib/libhotplug \ lib/libidmap \ lib/libilb \ - lib/libinetcfg \ lib/libinetsvc \ lib/libinetutil \ lib/libinstzones \ diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs index 95957b603c20..f850a9487356 100644 --- a/usr/src/Targetdirs +++ b/usr/src/Targetdirs @@ -870,8 +870,6 @@ $(ROOT)/usr/lib/libfdisk.so.1:= REALPATH=../../lib/libfdisk.so.1 $(ROOT)/usr/lib/libfdisk.so:= REALPATH=../../lib/libfdisk.so.1 $(ROOT)/usr/lib/libgen.so.1:= REALPATH=../../lib/libgen.so.1 $(ROOT)/usr/lib/libgen.so:= REALPATH=../../lib/libgen.so.1 -$(ROOT)/usr/lib/libinetcfg.so.1:= REALPATH=../../lib/libinetcfg.so.1 -$(ROOT)/usr/lib/libinetcfg.so:= REALPATH=../../lib/libinetcfg.so.1 $(ROOT)/usr/lib/libinetutil.so.1:= REALPATH=../../lib/libinetutil.so.1 $(ROOT)/usr/lib/libinetutil.so:= REALPATH=../../lib/libinetutil.so.1 $(ROOT)/usr/lib/libintl.so.1:= REALPATH=../../lib/libintl.so.1 @@ -994,8 +992,6 @@ $(ROOT)/usr/lib/llib-lfdisk.ln:= REALPATH=../../lib/llib-lfdisk.ln $(ROOT)/usr/lib/llib-lfdisk:= REALPATH=../../lib/llib-lfdisk $(ROOT)/usr/lib/llib-lgen.ln:= REALPATH=../../lib/llib-lgen.ln $(ROOT)/usr/lib/llib-lgen:= REALPATH=../../lib/llib-lgen -$(ROOT)/usr/lib/llib-linetcfg.ln:= REALPATH=../../lib/llib-linetcfg.ln -$(ROOT)/usr/lib/llib-linetcfg:= REALPATH=../../lib/llib-linetcfg $(ROOT)/usr/lib/llib-linetutil.ln:= REALPATH=../../lib/llib-linetutil.ln $(ROOT)/usr/lib/llib-linetutil:= REALPATH=../../lib/llib-linetutil $(ROOT)/usr/lib/llib-lintl.ln:= REALPATH=../../lib/llib-lintl.ln @@ -1470,8 +1466,6 @@ SYM.USRLIB= \ /usr/lib/libelf.so.1 \ /usr/lib/libgen.so \ /usr/lib/libgen.so.1 \ - /usr/lib/libinetcfg.so \ - /usr/lib/libinetcfg.so.1 \ /usr/lib/libinetutil.so \ /usr/lib/libinetutil.so.1 \ /usr/lib/libintl.so \ @@ -1588,8 +1582,6 @@ SYM.USRLIB= \ /usr/lib/llib-lelf.ln \ /usr/lib/llib-lgen \ /usr/lib/llib-lgen.ln \ - /usr/lib/llib-linetcfg \ - /usr/lib/llib-linetcfg.ln \ /usr/lib/llib-linetutil \ /usr/lib/llib-linetutil.ln \ /usr/lib/llib-lintl \ diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/Makefile b/usr/src/cmd/cmd-inet/lib/nwamd/Makefile index 0e124210f97c..fadaa28d85e3 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/Makefile +++ b/usr/src/cmd/cmd-inet/lib/nwamd/Makefile @@ -52,7 +52,7 @@ $(ROOTCFGFILES) := FILEMODE= 644 ROOTCMDDIR= $(ROOTFS_LIBDIR)/inet LDLIBS += -ldhcpagent -ldhcputil -ldladm -ldlpi -lgen \ - -linetcfg -linetutil -lkstat -lnsl -lnvpair -lnwam \ + -linetutil -lipadm -lkstat -lnsl -lnvpair -lnwam \ -lsecdb -lscf -lsocket -lsysevent -lumem -luutil # diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/conditions.c b/usr/src/cmd/cmd-inet/lib/nwamd/conditions.c index c564dd094db3..25c5643382ca 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/conditions.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/conditions.c @@ -20,25 +20,20 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include -#include #include #include #include #include -#include #include #include #include -#include -#include #include #include "conditions.h" @@ -405,6 +400,36 @@ prefixmatch(uchar_t *addr1, uchar_t *addr2, int prefixlen) return (B_TRUE); } +/* + * Given a string representation of an IPv4 or IPv6 address returns the + * sockaddr representation. Note that 'sockaddr' should point at the correct + * sockaddr structure for the address family (sockaddr_in for AF_INET or + * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage + * structure. + */ +static struct sockaddr_storage * +nwamd_str2sockaddr(sa_family_t af, const char *straddr, + struct sockaddr_storage *addr) +{ + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + int err; + + if (af == AF_INET) { + sin = (struct sockaddr_in *)addr; + sin->sin_family = AF_INET; + err = inet_pton(AF_INET, straddr, &sin->sin_addr); + } else if (af == AF_INET6) { + sin6 = (struct sockaddr_in6 *)addr; + sin6->sin6_family = AF_INET6; + err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr); + } else { + errno = EINVAL; + return (NULL); + } + return (err == 1 ? addr : NULL); +} + struct nwamd_ipaddr_condition_walk_arg { nwam_condition_t condition; struct sockaddr_storage sockaddr; @@ -413,41 +438,25 @@ struct nwamd_ipaddr_condition_walk_arg { }; static int -check_ipaddr(icfg_if_t *intf, void *arg) +check_ipaddr(sa_family_t family, struct ifaddrs *ifa, void *arg) { struct nwamd_ipaddr_condition_walk_arg *wa = arg; - struct sockaddr_storage sockaddr; - icfg_handle_t h; - socklen_t addrlen = intf->if_protocol == AF_INET ? - sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6); - int prefixlen = 0; boolean_t match = B_FALSE; uchar_t *addr1, *addr2; - if (icfg_open(&h, intf) != ICFG_SUCCESS) - return (0); - - if (icfg_get_addr(h, (struct sockaddr *)&sockaddr, &addrlen, - &prefixlen, B_TRUE) != ICFG_SUCCESS) { - nlog(LOG_ERR, "check_ipaddr: icfg_get_addr: %s", - strerror(errno)); - return (0); - } - - if (intf->if_protocol == AF_INET) { + if (family == AF_INET) { addr1 = (uchar_t *)&(((struct sockaddr_in *) - &sockaddr)->sin_addr.s_addr); + ifa->ifa_addr)->sin_addr.s_addr); addr2 = (uchar_t *)&(((struct sockaddr_in *) &(wa->sockaddr))->sin_addr.s_addr); } else { addr1 = (uchar_t *)&(((struct sockaddr_in6 *) - &sockaddr)->sin6_addr.s6_addr); + ifa->ifa_addr)->sin6_addr.s6_addr); addr2 = (uchar_t *)&(((struct sockaddr_in6 *) &(wa->sockaddr))->sin6_addr.s6_addr); } match = prefixmatch(addr1, addr2, wa->prefixlen); - icfg_close(h); nlog(LOG_DEBUG, "check_ipaddr: match %d\n", match); switch (wa->condition) { @@ -470,11 +479,10 @@ static boolean_t test_condition_ip_address(nwam_condition_t condition, const char *ip_address_string) { - int proto; + sa_family_t family; char *copy, *ip_address, *prefixlen_string, *lasts; - socklen_t addrlen = sizeof (struct sockaddr_in); - socklen_t addr6len = sizeof (struct sockaddr_in6); struct nwamd_ipaddr_condition_walk_arg wa; + struct ifaddrs *ifap, *ifa; if ((copy = strdup(ip_address_string)) == NULL) return (B_FALSE); @@ -486,17 +494,17 @@ test_condition_ip_address(nwam_condition_t condition, prefixlen_string = strtok_r(NULL, " \t", &lasts); - if (icfg_str_to_sockaddr(AF_INET, ip_address, - (struct sockaddr *)&(wa.sockaddr), &addrlen) == ICFG_SUCCESS) { - proto = AF_INET; + if (nwamd_str2sockaddr(AF_INET, ip_address, &wa.sockaddr) != NULL) { + family = AF_INET; wa.prefixlen = IP_ABITS; - } else if (icfg_str_to_sockaddr(AF_INET6, ip_address, - (struct sockaddr *)&(wa.sockaddr), &addr6len) == ICFG_SUCCESS) { - proto = AF_INET6; + } else if (nwamd_str2sockaddr(AF_INET6, ip_address, &wa.sockaddr) + != NULL) { + family = AF_INET6; wa.prefixlen = IPV6_ABITS; } else { nlog(LOG_ERR, "test_condition_ip_address: " - "icfg_str_to_sockaddr: %s", strerror(errno)); + "nwamd_str2sockaddr failed for %s: %s", ip_address, + strerror(errno)); free(copy); return (B_FALSE); } @@ -519,11 +527,21 @@ test_condition_ip_address(nwam_condition_t condition, free(copy); return (B_FALSE); } - - (void) icfg_iterate_if(proto, ICFG_PLUMBED, &wa, check_ipaddr); - free(copy); + if (getifaddrs(&ifa) == -1) { + nlog(LOG_ERR, "test_condition_ip_address: " + "getifaddrs failed: %s", strerror(errno)); + return (wa.res); + } + for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { + if (ifap->ifa_addr->ss_family != family) + continue; + if (check_ipaddr(family, ifap, &wa) == 1) + break; + } + freeifaddrs(ifa); + return (wa.res); } diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/dlpi_events.c b/usr/src/cmd/cmd-inet/lib/nwamd/dlpi_events.c index 8789fed32bb7..a40e9da30205 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/dlpi_events.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/dlpi_events.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -106,7 +105,7 @@ nwamd_dlpi_add_link(nwamd_object_t obj) assert(ncu != NULL && ncu->ncu_type == NWAM_NCU_TYPE_LINK); - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; /* Already running? */ if (link->nwamd_link_dlpi_thread != 0) { @@ -157,16 +156,15 @@ nwamd_dlpi_delete_link(nwamd_object_t obj) nlog(LOG_DEBUG, "nwamd_dlpi_delete_link: ncu %p (%s) type %d", ncu, obj->nwamd_object_name, ncu != NULL ? ncu->ncu_type : -1); - if (ncu->ncu_node.u_link.nwamd_link_dlpi_thread != 0) { + if (ncu->ncu_link.nwamd_link_dlpi_thread != 0) { (void) pthread_cancel( - ncu->ncu_node.u_link.nwamd_link_dlpi_thread); - (void) pthread_join(ncu->ncu_node.u_link.nwamd_link_dlpi_thread, - NULL); - ncu->ncu_node.u_link.nwamd_link_dlpi_thread = 0; + ncu->ncu_link.nwamd_link_dlpi_thread); + (void) pthread_join(ncu->ncu_link.nwamd_link_dlpi_thread, NULL); + ncu->ncu_link.nwamd_link_dlpi_thread = 0; /* Unset properties before closing */ nwamd_set_unset_link_properties(ncu, B_FALSE); } - dlpi_close(ncu->ncu_node.u_link.nwamd_link_dhp); - ncu->ncu_node.u_link.nwamd_link_dhp = NULL; + dlpi_close(ncu->ncu_link.nwamd_link_dhp); + ncu->ncu_link.nwamd_link_dhp = NULL; } diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c b/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c index 02ee82896a36..5ac3cf4fcb3c 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/door_if.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -188,7 +187,7 @@ nwamd_door_req_wlan_scan_results(nwamd_door_arg_t *req, ucred_t *ucr, } ncu = obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; num_wlans = link->nwamd_link_wifi_scan.nwamd_wifi_scan_curr_num; if (num_wlans > 0) { diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/enm.c b/usr/src/cmd/cmd-inet/lib/nwamd/enm.c index a33543adcf85..e076f675cac5 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/enm.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/enm.c @@ -20,14 +20,12 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include -#include #include #include #include diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/events.c b/usr/src/cmd/cmd-inet/lib/nwamd/events.c index ff4cd71e7d34..6d587569650c 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/events.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/events.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -369,7 +368,7 @@ nwamd_event_init_link_state(const char *name, boolean_t up) nwamd_event_t nwamd_event_init_if_state(const char *linkname, uint32_t flags, - uint32_t addr_added, uint32_t index, struct sockaddr *addr) + uint32_t addr_added, struct sockaddr *addr, struct sockaddr *netmask) { nwamd_event_t event; nwam_error_t err; @@ -394,7 +393,6 @@ nwamd_event_init_if_state(const char *linkname, uint32_t flags, linkname, sizeof (event->event_msg->nwe_data.nwe_if_state.nwe_name)); event->event_msg->nwe_data.nwe_if_state.nwe_flags = flags; - event->event_msg->nwe_data.nwe_if_state.nwe_index = index; event->event_msg->nwe_data.nwe_if_state.nwe_addr_added = addr_added; event->event_msg->nwe_data.nwe_if_state.nwe_addr_valid = (addr != NULL); @@ -403,6 +401,12 @@ nwamd_event_init_if_state(const char *linkname, uint32_t flags, addr->sa_family == AF_INET ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)); } + if (netmask != NULL) { + bcopy(netmask, + &(event->event_msg->nwe_data.nwe_if_state.nwe_netmask), + netmask->sa_family == AF_INET ? + sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)); + } return (event); } diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/events.h b/usr/src/cmd/cmd-inet/lib/nwamd/events.h index 485cae55c5cf..4e3d390f5a60 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/events.h +++ b/usr/src/cmd/cmd-inet/lib/nwamd/events.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _EVENTS_H @@ -102,7 +101,7 @@ extern nwamd_event_t nwamd_event_init_priority_group_change(int64_t); extern nwamd_event_t nwamd_event_init_link_action(const char *, nwam_action_t); extern nwamd_event_t nwamd_event_init_link_state(const char *, boolean_t); extern nwamd_event_t nwamd_event_init_if_state(const char *, uint32_t, - uint32_t, uint32_t, struct sockaddr *); + uint32_t, struct sockaddr *, struct sockaddr *); extern nwamd_event_t nwamd_event_init_wlan(const char *, int32_t, boolean_t, nwam_wlan_t *, uint_t); extern nwamd_event_t nwamd_event_init_ncu_check(void); diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c b/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c index 249758e6e726..80531aa5cbca 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/known_wlans.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -501,7 +500,7 @@ nwamd_ncu_known_wlan_committed(nwamd_object_t object, void *data) return (0); /* network selection will be done only if possible */ - if (ncu_data->ncu_node.u_link.nwamd_link_media == DL_WIFI) + if (ncu_data->ncu_link.nwamd_link_media == DL_WIFI) (void) nwamd_wlan_scan(ncu_data->ncu_name); return (0); } diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/loc.c b/usr/src/cmd/cmd-inet/lib/nwamd/loc.c index d1f670402b4f..cc20f9560629 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/loc.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/loc.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/main.c b/usr/src/cmd/cmd-inet/lib/nwamd/main.c index 108463d6031d..84ff96875d21 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/main.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/main.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -55,6 +54,7 @@ boolean_t fg = B_FALSE; dladm_handle_t dld_handle = NULL; +ipadm_handle_t ipadm_handle = NULL; boolean_t shutting_down = B_FALSE; sigset_t original_sigmask; @@ -317,7 +317,8 @@ main(int argc, char *argv[]) int c; uint64_t version; nwamd_event_t event; - dladm_status_t rc; + dladm_status_t drc; + ipadm_status_t irc; uid_t uid = getuid(); /* @@ -367,13 +368,17 @@ main(int argc, char *argv[]) * then one must have *all* privs in order to open /dev/dld, which * is one of the steps performed in dladm_open(). */ - rc = dladm_open(&dld_handle); - if (rc != DLADM_STATUS_OK) { + drc = dladm_open(&dld_handle); + if (drc != DLADM_STATUS_OK) { char status_str[DLADM_STRSIZE]; - (void) dladm_status2str(rc, status_str); - pfail("failed to open dladm handle: %s", status_str); + pfail("failed to open dladm handle: %s", + dladm_status2str(drc, status_str)); } + irc = ipadm_open(&ipadm_handle, 0); + if (irc != IPADM_SUCCESS) + pfail("failed to open ipadm handle: %s", ipadm_status2str(irc)); + /* * Create the event queue before starting event sources, including * signal handling, so we are ready to handle incoming events. Also @@ -462,6 +467,7 @@ main(int argc, char *argv[]) */ nwamd_event_handler(); + ipadm_close(ipadm_handle); dladm_close(dld_handle); return (EXIT_SUCCESS); diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/ncp.c b/usr/src/cmd/cmd-inet/lib/nwamd/ncp.c index 7292b3f2dfa0..2c54caf9bdfe 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/ncp.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncp.c @@ -237,11 +237,11 @@ find_next_priority_group_cb(nwamd_object_t object, void *data) uint64_t priority; nwamd_ncu_t *ncu = object->nwamd_object_data; - if (ncu->ncu_node.u_link.nwamd_link_activation_mode != + if (ncu->ncu_link.nwamd_link_activation_mode != NWAM_ACTIVATION_MODE_PRIORITIZED) return (0); - priority = ncu->ncu_node.u_link.nwamd_link_priority_group; + priority = ncu->ncu_link.nwamd_link_priority_group; if (priority >= cbarg->minpriority && priority < cbarg->currpriority) { cbarg->found = B_TRUE; @@ -340,21 +340,21 @@ nwamd_ncu_check_or_activate(nwamd_object_t object, void *data) "skipping interface NCU %s", name); return (0); } - if (!wa->manual && ncu->ncu_node.u_link.nwamd_link_activation_mode != + if (!wa->manual && ncu->ncu_link.nwamd_link_activation_mode != NWAM_ACTIVATION_MODE_PRIORITIZED) { nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " "skipping non-prioritized NCU %s", name); return (0); } - if (wa->manual && ncu->ncu_node.u_link.nwamd_link_activation_mode != + if (wa->manual && ncu->ncu_link.nwamd_link_activation_mode != NWAM_ACTIVATION_MODE_MANUAL) { nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " "skipping non-manual NCU %s", name); return (0); } - priority_group = ncu->ncu_node.u_link.nwamd_link_priority_group; - priority_mode = ncu->ncu_node.u_link.nwamd_link_priority_mode; + priority_group = ncu->ncu_link.nwamd_link_priority_group; + priority_mode = ncu->ncu_link.nwamd_link_priority_mode; /* Only work with NCUs in the requested priority-group */ if (!wa->manual && priority_group != wa->priority_group) { nlog(LOG_DEBUG, "nwamd_ncu_check_or_activate: " diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/ncp.h b/usr/src/cmd/cmd-inet/lib/nwamd/ncp.h index c401e8d2d0ce..96f7c848fc6f 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/ncp.h +++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncp.h @@ -20,14 +20,12 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _NCP_H #define _NCP_H -#include #include #include #include diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c b/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c index b44565c1d7a1..3d4d8f09bef4 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu.c @@ -51,6 +51,8 @@ #define VBOX_IFACE_PREFIX "vboxnet" +static void populate_ip_ncu_properties(nwam_ncu_handle_t, nwamd_ncu_t *); + /* * Find ncu of specified type for link/interface name. */ @@ -149,7 +151,7 @@ nwamd_ncu_state_machine(const char *object_name) } ncu = object->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; switch (object->nwamd_object_aux_state) { case NWAM_AUX_STATE_INITIALIZED: @@ -217,8 +219,16 @@ nwamd_ncu_state_machine(const char *object_name) * would be good to try and minimize configuration * changes. */ - nwamd_unplumb_interface(ncu, 0, AF_INET); - nwamd_unplumb_interface(ncu, 0, AF_INET6); + nwamd_unplumb_interface(ncu, AF_INET); + nwamd_unplumb_interface(ncu, AF_INET6); + + /* + * We may be restarting the state machine. Re-read + * the IP NCU properties as the ipadm_addrobj_t in + * nwamd_if_address should not be reused. + */ + populate_ip_ncu_properties(object->nwamd_object_handle, + ncu); /* * Enqueue a WAITING_FOR_ADDR aux state change so that @@ -231,26 +241,14 @@ nwamd_ncu_state_machine(const char *object_name) object_name, NWAM_STATE_OFFLINE_TO_ONLINE, NWAM_AUX_STATE_IF_WAITING_FOR_ADDR); - if (ncu->ncu_node.u_if.nwamd_if_ipv4) - nwamd_plumb_interface(ncu, 0, AF_INET); + if (ncu->ncu_if.nwamd_if_ipv4) + nwamd_plumb_interface(ncu, AF_INET); - if (ncu->ncu_node.u_if.nwamd_if_ipv6) - nwamd_plumb_interface(ncu, 0, AF_INET6); + if (ncu->ncu_if.nwamd_if_ipv6) + nwamd_plumb_interface(ncu, AF_INET6); - /* - * Configure addresses. Configure any static addresses - * and start DHCP if required. If DHCP is not required, - * do a DHCPINFORM to get other networking config - * parameters. RTM_NEWADDRs - translated into IF_STATE - * events - will then finish the job of bringing us - * online. - */ + /* Configure addresses */ nwamd_configure_interface_addresses(ncu); - - if (ncu->ncu_node.u_if.nwamd_if_dhcp_requested) - nwamd_start_dhcp(ncu); - else - nwamd_dhcp_inform(ncu); } break; @@ -440,8 +438,8 @@ nwamd_ncu_state_machine(const char *object_name) * until we reconnect to a different WLAN (i.e. with * a different ESSID). */ - nwamd_unplumb_interface(ncu, 0, AF_INET); - nwamd_unplumb_interface(ncu, 0, AF_INET6); + nwamd_unplumb_interface(ncu, AF_INET); + nwamd_unplumb_interface(ncu, AF_INET6); } if (object->nwamd_object_state != NWAM_STATE_OFFLINE) { nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, @@ -471,11 +469,11 @@ nwamd_ncu_state_machine(const char *object_name) nwamd_dlpi_delete_link(object); } else { /* Unplumb here. */ - if (ncu->ncu_node.u_if.nwamd_if_ipv4) { - nwamd_unplumb_interface(ncu, 0, AF_INET); + if (ncu->ncu_if.nwamd_if_ipv4) { + nwamd_unplumb_interface(ncu, AF_INET); } - if (ncu->ncu_node.u_if.nwamd_if_ipv6) { - nwamd_unplumb_interface(ncu, 0, AF_INET6); + if (ncu->ncu_if.nwamd_if_ipv6) { + nwamd_unplumb_interface(ncu, AF_INET6); } /* trigger location condition checking */ nwamd_create_triggered_condition_check_event(0); @@ -658,13 +656,12 @@ populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) "populate_link_ncu_properties: could not get %s value: %s", NWAM_NCU_PROP_ACTIVATION_MODE, nwam_strerror(err)); } else { - ncu_data->ncu_node.u_link.nwamd_link_activation_mode = - uintval[0]; + ncu_data->ncu_link.nwamd_link_activation_mode = uintval[0]; nwam_value_free(ncu_prop); } /* priority-group and priority-mode for prioritized activation */ - if (ncu_data->ncu_node.u_link.nwamd_link_activation_mode == + if (ncu_data->ncu_link.nwamd_link_activation_mode == NWAM_ACTIVATION_MODE_PRIORITIZED) { /* ncus with prioritized activation are always enabled */ ncu_data->ncu_enabled = B_TRUE; @@ -675,7 +672,7 @@ populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) "could not get %s value: %s", NWAM_NCU_PROP_PRIORITY_MODE, nwam_strerror(err)); } else { - ncu_data->ncu_node.u_link.nwamd_link_priority_mode = + ncu_data->ncu_link.nwamd_link_priority_mode = uintval[0]; nwam_value_free(ncu_prop); } @@ -687,7 +684,7 @@ populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) "could not get %s value: %s", NWAM_NCU_PROP_PRIORITY_GROUP, nwam_strerror(err)); } else { - ncu_data->ncu_node.u_link.nwamd_link_priority_group = + ncu_data->ncu_link.nwamd_link_priority_group = uintval[0]; nwam_value_free(ncu_prop); } @@ -699,12 +696,10 @@ populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) nlog(LOG_DEBUG, "populate_link_ncu_properties: could not get %s value: %s", NWAM_NCU_PROP_LINK_MAC_ADDR, nwam_strerror(err)); - ncu_data->ncu_node.u_link.nwamd_link_mac_addr = NULL; + ncu_data->ncu_link.nwamd_link_mac_addr = NULL; } else { - ncu_data->ncu_node.u_link.nwamd_link_mac_addr = - strdup(*mac_addr); - ncu_data->ncu_node.u_link.nwamd_link_mac_addr_len = - strlen(*mac_addr); + ncu_data->ncu_link.nwamd_link_mac_addr = strdup(*mac_addr); + ncu_data->ncu_link.nwamd_link_mac_addr_len = strlen(*mac_addr); nwam_value_free(ncu_prop); } @@ -714,34 +709,35 @@ populate_link_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) nlog(LOG_DEBUG, "populate_link_ncu_properties: could not get %s value: %s", NWAM_NCU_PROP_LINK_MTU, nwam_strerror(err)); - ncu_data->ncu_node.u_link.nwamd_link_mtu = 0; + ncu_data->ncu_link.nwamd_link_mtu = 0; } else { - ncu_data->ncu_node.u_link.nwamd_link_mtu = uintval[0]; + ncu_data->ncu_link.nwamd_link_mtu = uintval[0]; nwam_value_free(ncu_prop); } /* link-autopush */ if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, - &ncu_data->ncu_node.u_link.nwamd_link_autopush, - &ncu_data->ncu_node.u_link.nwamd_link_num_autopush, + &ncu_data->ncu_link.nwamd_link_autopush, + &ncu_data->ncu_link.nwamd_link_num_autopush, NWAM_NCU_PROP_LINK_AUTOPUSH)) != NWAM_SUCCESS) { nlog(LOG_DEBUG, "populate_link_ncu_properties: could not get %s value: %s", NWAM_NCU_PROP_LINK_AUTOPUSH, nwam_strerror(err)); - ncu_data->ncu_node.u_link.nwamd_link_num_autopush = 0; + ncu_data->ncu_link.nwamd_link_num_autopush = 0; } } static void populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) { - nwamd_if_t *nif = &ncu_data->ncu_node.u_if; + nwamd_if_t *nif = &ncu_data->ncu_if; struct nwamd_if_address **nifa, *nifai, *nifait; - char *prefix; boolean_t static_addr = B_FALSE; uint64_t *addrsrcvalue; nwam_value_t ncu_prop; nwam_error_t err; + ipadm_addrobj_t ipaddr; + ipadm_status_t ipstatus; char **addrvalue; uint_t numvalues; uint64_t *ipversion; @@ -783,6 +779,7 @@ populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) for (nifai = nif->nwamd_if_list; nifai != NULL; nifai = nifait) { nifait = nifai->next; nifai->next = NULL; + ipadm_destroy_addrobj(nifai->ipaddr); free(nifai); } nif->nwamd_if_list = NULL; @@ -813,14 +810,38 @@ populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) nwam_value_free(ncu_prop); } if (nif->nwamd_if_dhcp_requested) { + ipstatus = ipadm_create_addrobj(IPADM_ADDR_DHCP, + ncu_data->ncu_name, &ipaddr); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, "populate_ip_ncu_properties: " + "ipadm_create_addrobj failed for v4 dhcp: %s", + ipadm_status2str(ipstatus)); + goto skip_ipv4_dhcp; + } + + ipstatus = ipadm_set_wait_time(ipaddr, ncu_wait_time); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, "populate_ip_ncu_properties: " + "ipadm_set_wait_time failed for v4 dhcp: %s", + ipadm_status2str(ipstatus)); + ipadm_destroy_addrobj(ipaddr); + goto skip_ipv4_dhcp; + } if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { - (*nifa)->address.sa_family = AF_INET; - (*nifa)->dhcp_if = B_TRUE; + (*nifa)->family = AF_INET; + (*nifa)->ipaddr_atype = IPADM_ADDR_DHCP; + (*nifa)->ipaddr = ipaddr; nifa = &((*nifa)->next); *nifa = NULL; + } else { + nlog(LOG_ERR, "populate_ip_ncu_properties: " + "couldn't allocate nwamd address for v4 dhcp: %s", + strerror(errno)); + ipadm_destroy_addrobj(ipaddr); } } +skip_ipv4_dhcp: /* ipv4-addr */ if (static_addr) { if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, @@ -829,28 +850,46 @@ populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) "could not get %s value; %s", NWAM_NCU_PROP_IPV4_ADDR, nwam_strerror(err)); } else { - struct sockaddr_in *s; - for (i = 0; i < numvalues; i++) { - if ((*nifa = calloc(sizeof (**nifa), 1)) - == NULL) { - nlog(LOG_ERR, "couldn't allocate nwamd" - "address"); + ipstatus = ipadm_create_addrobj( + IPADM_ADDR_STATIC, ncu_data->ncu_name, + &ipaddr); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, + "populate_ip_ncu_properties: " + "ipadm_create_addrobj failed " + "for %s: %s", addrvalue[i], + ipadm_status2str(ipstatus)); continue; } - (*nifa)->address.sa_family = AF_INET; - /*LINTED*/ - s = (struct sockaddr_in *)&(*nifa)->address; - s->sin_family = AF_INET; - s->sin_port = 0; - prefix = strchr(addrvalue[i], '/'); - if (prefix != NULL) { - *prefix++ = 0; - (*nifa)->prefix = atoi(prefix); + /* ipadm_set_addr takes [/] */ + ipstatus = ipadm_set_addr(ipaddr, addrvalue[i], + AF_INET); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, + "populate_ip_ncu_properties: " + "ipadm_set_addr failed for %s: %s", + addrvalue[i], + ipadm_status2str(ipstatus)); + ipadm_destroy_addrobj(ipaddr); + continue; + } + + if ((*nifa = calloc(sizeof (**nifa), 1)) + != NULL) { + (*nifa)->family = AF_INET; + (*nifa)->ipaddr_atype = + IPADM_ADDR_STATIC; + (*nifa)->ipaddr = ipaddr; + nifa = &((*nifa)->next); + } else { + nlog(LOG_ERR, + "populate_ip_ncu_properties: " + "couldn't allocate nwamd address " + "for %s: %s", addrvalue[i], + strerror(errno)); + ipadm_destroy_addrobj(ipaddr); } - (void) inet_pton(AF_INET, addrvalue[i], - &(s->sin_addr)); - nifa = &((*nifa)->next); } *nifa = NULL; @@ -870,7 +909,6 @@ populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) } skip_ipv4: - if (!nif->nwamd_if_ipv6) goto skip_ipv6; @@ -899,23 +937,58 @@ populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) } nwam_value_free(ncu_prop); } - if (nif->nwamd_if_stateful_requested) { - if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { - (*nifa)->address.sa_family = AF_INET6; - (*nifa)->dhcp_if = B_TRUE; - nifa = &((*nifa)->next); - *nifa = NULL; + /* + * Both stateful and stateless share the same nwamd_if_address because + * only one ipaddr for both of these addresses can be created. + * ipadm_create_addr() adds both addresses from the same ipaddr. + */ + if (nif->nwamd_if_stateful_requested || + nif->nwamd_if_stateless_requested) { + ipstatus = ipadm_create_addrobj(IPADM_ADDR_IPV6_ADDRCONF, + ncu_data->ncu_name, &ipaddr); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, "populate_ip_ncu_properties: " + "ipadm_create_addrobj failed for v6 " + "stateless/stateful: %s", + ipadm_status2str(ipstatus)); + goto skip_ipv6_addrconf; + } + /* create_addrobj sets both stateless and stateful to B_TRUE */ + if (!nif->nwamd_if_stateful_requested) { + ipstatus = ipadm_set_stateful(ipaddr, B_FALSE); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, "populate_ip_ncu_properties: " + "ipadm_set_stateful failed for v6: %s", + ipadm_status2str(ipstatus)); + ipadm_destroy_addrobj(ipaddr); + goto skip_ipv6_addrconf; + } + } + if (!nif->nwamd_if_stateless_requested) { + ipstatus = ipadm_set_stateless(ipaddr, B_FALSE); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, "populate_ip_ncu_properties: " + "ipadm_set_stateless failed for v6: %s", + ipadm_status2str(ipstatus)); + ipadm_destroy_addrobj(ipaddr); + goto skip_ipv6_addrconf; + } } - } - if (nif->nwamd_if_stateless_requested) { if ((*nifa = calloc(sizeof (**nifa), 1)) != NULL) { - (*nifa)->address.sa_family = AF_INET6; - (*nifa)->stateless_if = B_TRUE; + (*nifa)->family = AF_INET6; + (*nifa)->ipaddr_atype = IPADM_ADDR_IPV6_ADDRCONF; + (*nifa)->ipaddr = ipaddr; nifa = &((*nifa)->next); *nifa = NULL; + } else { + nlog(LOG_ERR, "populate_ip_ncu_properties: " + "couldn't allocate nwamd address for " + "v6 stateless/stateful: %s", strerror(errno)); + ipadm_destroy_addrobj(ipaddr); } } +skip_ipv6_addrconf: /* ipv6-addr */ if (static_addr) { if ((err = nwamd_get_ncu_string(ncuh, &ncu_prop, &addrvalue, @@ -924,28 +997,46 @@ populate_ip_ncu_properties(nwam_ncu_handle_t ncuh, nwamd_ncu_t *ncu_data) "could not get %s value; %s", NWAM_NCU_PROP_IPV6_ADDR, nwam_strerror(err)); } else { - struct sockaddr_in6 *s; - for (i = 0; i < numvalues; i++) { - if ((*nifa = calloc(sizeof (**nifa), 1)) - == NULL) { - nlog(LOG_ERR, "couldn't allocate nwamd" - "address"); + ipstatus = ipadm_create_addrobj( + IPADM_ADDR_STATIC, ncu_data->ncu_name, + &ipaddr); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, + "populate_ip_ncu_properties: " + "ipadm_create_addrobj failed " + "for %s: %s", addrvalue[i], + ipadm_status2str(ipstatus)); continue; } - (*nifa)->address.sa_family = AF_INET6; - /*LINTED*/ - s = (struct sockaddr_in6 *)&(*nifa)->address; - s->sin6_family = AF_INET6; - s->sin6_port = 0; - prefix = strchr(addrvalue[i], '/'); - if (prefix != NULL) { - *prefix++ = 0; - (*nifa)->prefix = atoi(prefix); + /* ipadm_set_addr takes [/] */ + ipstatus = ipadm_set_addr(ipaddr, addrvalue[i], + AF_INET6); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, + "populate_ip_ncu_properties: " + "ipadm_set_addr failed for %s: %s", + addrvalue[i], + ipadm_status2str(ipstatus)); + ipadm_destroy_addrobj(ipaddr); + continue; + } + + if ((*nifa = calloc(sizeof (**nifa), 1)) + != NULL) { + (*nifa)->family = AF_INET6; + (*nifa)->ipaddr_atype = + IPADM_ADDR_STATIC; + (*nifa)->ipaddr = ipaddr; + nifa = &((*nifa)->next); + } else { + nlog(LOG_ERR, + "populate_ip_ncu_properties: " + "couldn't allocate nwamd address " + "for %s: %s", addrvalue[i], + strerror(errno)); + ipadm_destroy_addrobj(ipaddr); } - (void) inet_pton(AF_INET6, addrvalue[i], - &(s->sin6_addr)); - nifa = &((*nifa)->next); } *nifa = NULL; @@ -984,15 +1075,15 @@ nwamd_ncu_init(nwam_ncu_type_t ncu_type, const char *name) /* Initialize link/interface-specific data */ if (rv->ncu_type == NWAM_NCU_TYPE_LINK) { - (void) bzero(&rv->ncu_node.u_link, sizeof (nwamd_link_t)); + (void) bzero(&rv->ncu_link, sizeof (nwamd_link_t)); (void) dladm_name2info(dld_handle, name, - &rv->ncu_node.u_link.nwamd_link_id, NULL, NULL, - &rv->ncu_node.u_link.nwamd_link_media); + &rv->ncu_link.nwamd_link_id, NULL, NULL, + &rv->ncu_link.nwamd_link_media); (void) pthread_mutex_init( - &rv->ncu_node.u_link.nwamd_link_wifi_mutex, NULL); - rv->ncu_node.u_link.nwamd_link_wifi_priority = MAXINT; + &rv->ncu_link.nwamd_link_wifi_mutex, NULL); + rv->ncu_link.nwamd_link_wifi_priority = MAXINT; } else { - (void) bzero(&rv->ncu_node.u_if, sizeof (nwamd_if_t)); + (void) bzero(&rv->ncu_if, sizeof (nwamd_if_t)); } return (rv); @@ -1005,7 +1096,7 @@ nwamd_ncu_free(nwamd_ncu_t *ncu) assert(ncu->ncu_type == NWAM_NCU_TYPE_LINK || ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE); if (ncu->ncu_type == NWAM_NCU_TYPE_LINK) { - struct nwamd_link *l = &ncu->ncu_node.u_link; + struct nwamd_link *l = &ncu->ncu_link; int i; free(l->nwamd_link_wifi_key); @@ -1015,12 +1106,13 @@ nwamd_ncu_free(nwamd_ncu_t *ncu) } else if (ncu->ncu_type == NWAM_NCU_TYPE_INTERFACE) { struct nwamd_if_address *nifa; - nifa = ncu->ncu_node.u_if.nwamd_if_list; + nifa = ncu->ncu_if.nwamd_if_list; while (nifa != NULL) { struct nwamd_if_address *n; n = nifa; nifa = nifa->next; + ipadm_destroy_addrobj(n->ipaddr); free(n); } } @@ -1638,7 +1730,7 @@ nwamd_ncu_handle_init_event(nwamd_event_t event) NWAM_AUX_STATE_CONDITIONS_NOT_MET; } } else { - nwamd_link_t *link = &ncu->ncu_node.u_link; + nwamd_link_t *link = &ncu->ncu_link; /* * Refresh NCU. Deal with disabled cases first, moving NCUs @@ -1689,7 +1781,7 @@ nwamd_ncu_handle_init_event(nwamd_event_t event) switch (type) { case NWAM_NCU_TYPE_LINK: - if (ncu->ncu_node.u_link.nwamd_link_media == DL_WIFI) { + if (ncu->ncu_link.nwamd_link_media == DL_WIFI) { /* * Do rescan. If the current state and the * active priority-group do not allow wireless @@ -1926,7 +2018,7 @@ nwamd_ncu_handle_state_event(nwamd_event_t event) if (is_link) (void) strlcpy(linkname, ncu->ncu_name, sizeof (linkname)); prioritized = (ncu->ncu_type == NWAM_NCU_TYPE_LINK && - ncu->ncu_node.u_link.nwamd_link_activation_mode == + ncu->ncu_link.nwamd_link_activation_mode == NWAM_ACTIVATION_MODE_PRIORITIZED); enabled = ncu->ncu_enabled; diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/ncu.h b/usr/src/cmd/cmd-inet/lib/nwamd/ncu.h index ed64ba36b416..a0c41751ecbc 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu.h +++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu.h @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _NCU_H @@ -29,10 +28,11 @@ #include #include -#include #include #include #include +#include +#include #include #include #include @@ -111,13 +111,12 @@ typedef struct nwamd_link { } nwamd_link_t; struct nwamd_if_address { - size_t prefix; - struct sockaddr address; - char pad[sizeof (struct sockaddr_storage)]; + sa_family_t family; + ipadm_addr_type_t ipaddr_atype; + ipadm_addrobj_t ipaddr; boolean_t configured; - boolean_t dhcp_if; - boolean_t stateless_if; - char ifname[LIFNAMSIZ]; + struct sockaddr_storage conf_addr; /* address configured for */ + struct sockaddr_storage conf_stateless_addr; /* this nwamd_if_address */ struct nwamd_if_address *next; }; @@ -156,7 +155,7 @@ typedef struct nwamd_ncu { struct nwamd_dhcp_thread_arg { char *name; dhcp_ipc_type_t type; - int timeout; + ipadm_addrobj_t ipaddr; volatile uint32_t *guard; }; @@ -171,10 +170,11 @@ struct nwamd_dhcp_thread_arg { #define NWAMD_READONLY_RETRY_INTERVAL 5 /* - * This dladm handle is opened before interfaces are initialized and - * closed only when nwamd shuts down. + * This dladm and ipadm handles are opened before interfaces are initialized + * and closed only when nwamd shuts down. */ extern dladm_handle_t dld_handle; +extern ipadm_handle_t ipadm_handle; extern nwamd_object_t nwamd_ncu_object_find(nwam_ncu_type_t, const char *); extern void nwamd_log_ncus(void); @@ -196,7 +196,8 @@ extern void nwamd_set_key_name(const char *, const char *, char *, size_t); /* Link functions */ extern link_state_t nwamd_get_link_state(const char *); -extern char *nwamd_sockaddr_to_str(const struct sockaddr *, char *, size_t); +extern const char *nwamd_sockaddr_to_str(const struct sockaddr *, char *, + size_t); extern void nwamd_propogate_link_up_down_to_ip(const char *, boolean_t); extern void nwamd_set_unset_link_properties(nwamd_ncu_t *, boolean_t); /* DLPI event hooking */ @@ -204,12 +205,9 @@ extern void nwamd_dlpi_add_link(nwamd_object_t); extern void nwamd_dlpi_delete_link(nwamd_object_t); /* IP functions */ -extern void nwamd_update_addresses_unconfigured(nwamd_ncu_t *, sa_family_t); extern boolean_t nwamd_static_addresses_configured(nwamd_ncu_t *, sa_family_t); -extern void nwamd_plumb_interface(nwamd_ncu_t *, uint_t, int); -extern void nwamd_unplumb_interface(nwamd_ncu_t *, uint_t, int); -extern void nwamd_start_dhcp(nwamd_ncu_t *); -extern void nwamd_dhcp_inform(nwamd_ncu_t *); +extern void nwamd_plumb_interface(nwamd_ncu_t *, sa_family_t); +extern void nwamd_unplumb_interface(nwamd_ncu_t *, sa_family_t); extern boolean_t nwamd_dhcp_managing(int, nwamd_ncu_t *); extern void nwamd_configure_interface_addresses(nwamd_ncu_t *); extern char *nwamd_get_dhcpinfo_data(const char *, char *); @@ -230,6 +228,4 @@ extern nwam_error_t nwamd_get_ncu_string(nwam_ncu_handle_t, nwam_value_t *, extern void nwamd_walk_physical_configuration(void); -char *nwamd_link_to_ifname(const char *, int, char *, int); - #endif /* _NCU_H */ diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_ip.c b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_ip.c index 0fb402063e9f..f9d90ccafe2d 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_ip.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_ip.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -32,13 +31,9 @@ #include #include #include -#include #include -#include #include #include -#include -#include #include #include #include @@ -57,30 +52,41 @@ #define STATELESS_RUNNING (IFF_RUNNING | IFF_UP | IFF_ADDRCONF) #define DHCP_RUNNING (IFF_RUNNING | IFF_UP | IFF_DHCPRUNNING) -static void *start_dhcp_thread(void *); -static void nwamd_down_interface(const char *, uint_t, int); +static void nwamd_dhcp(const char *, ipadm_addrobj_t, dhcp_ipc_type_t); +static void nwamd_down_interface(const char *, ipadm_addr_type_t, const char *); static boolean_t stateless_running(const nwamd_ncu_t *); -char * -nwamd_sockaddr_to_str(const struct sockaddr *sockaddr, char *str, size_t len) +/* + * Given a sockaddr representation of an IPv4 or IPv6 address returns the + * string representation. Note that 'sockaddr' should point at the correct + * sockaddr structure for the address family (sockaddr_in for AF_INET or + * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage + * structure. + */ +static const char * +nwamd_sockaddr2str(const struct sockaddr *addr, char *str, size_t len) { - if (icfg_sockaddr_to_str(sockaddr->sa_family, sockaddr, str, len) != - ICFG_SUCCESS) { + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + const char *straddr; + + if (addr == NULL) return (NULL); + + if (addr->sa_family == AF_INET) { + /* LINTED E_BAD_PTR_CAST_ALIGN */ + sin = (struct sockaddr_in *)addr; + straddr = inet_ntop(AF_INET, (void *)&sin->sin_addr, str, len); + } else if (addr->sa_family == AF_INET6) { + /* LINTED E_BAD_PTR_CAST_ALIGN */ + sin6 = (struct sockaddr_in6 *)addr; + straddr = inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, str, + len); } else { - return (str); + errno = EINVAL; + return (NULL); } -} - -static void -nwamd_log_if_address(int severity, struct nwamd_if_address *nifa) -{ - char str[INET6_ADDRSTRLEN]; - - nlog(severity, "%s address %s is %s", - nifa->address.sa_family == AF_INET ? "IPv4" : "IPv6", - nwamd_sockaddr_to_str(&nifa->address, str, sizeof (str)), - nifa->configured ? "configured" : "not configured"); + return (straddr != NULL ? str : NULL); } void @@ -213,170 +219,10 @@ nwamd_get_dhcpinfo_data(const char *sym_name, char *ifname) return (NULL); } -void -nwamd_dhcp_release(const char *ifname) -{ - dhcp_ipc_reply_t *reply = NULL; - dhcp_ipc_request_t *request; - int rc; - - /* Now allocate and send the request */ - request = dhcp_ipc_alloc_request(DHCP_RELEASE, ifname, NULL, 0, - DHCP_TYPE_NONE); - if (request == NULL) { - nlog(LOG_DEBUG, "nwamd_dhcp_release: dhcp_ipc_alloc_request : " - "%s", strerror(errno)); - return; - } - rc = dhcp_ipc_make_request(request, &reply, 1); - free(request); - free(reply); - reply = NULL; - if (rc != 0) { - /* Fall back to drop request */ - request = dhcp_ipc_alloc_request(DHCP_DROP, ifname, NULL, 0, - DHCP_TYPE_NONE); - if (request == NULL) { - nlog(LOG_DEBUG, "nwamd_dhcp_release: " - "dhcp_ipc_alloc_request : %s", strerror(errno)); - return; - } - (void) dhcp_ipc_make_request(request, &reply, 1); - free(request); - free(reply); - } -} - -static boolean_t -add_ip_address(const char *ifname, struct nwamd_if_address *nifa, - boolean_t logical_if) -{ - icfg_handle_t h, newh; - icfg_if_t intf; - uint64_t flags; - int rc; - struct sockaddr_in bcastaddr; - char str[INET6_ADDRSTRLEN]; - - (void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name)); - intf.if_protocol = nifa->address.sa_family; - - nlog(LOG_DEBUG, "add_ip_address: %s address %s for link %s", - logical_if ? "adding" : "setting", - nwamd_sockaddr_to_str(&nifa->address, str, sizeof (str)), - intf.if_name); - - if (icfg_open(&h, &intf) != ICFG_SUCCESS) { - nlog(LOG_ERR, "add_ip_address: icfg_open failed on %s", ifname); - return (B_FALSE); - } - /* - * When working with the physical interface, we need to be careful - * to set the prefixlen and broadcast addresses before setting the - * IP address, otherwise RTM_DELADDRs for the old broadcast/netmask - * will confuse us into thinking we've lost the address we've just - * assigned. - */ - if (logical_if) { - rc = icfg_add_addr(h, &newh, - (const struct sockaddr *)&nifa->address, - intf.if_protocol == AF_INET ? - sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)); - } else { - newh = h; - - /* Make sure DHCP is no longer running */ - if (icfg_get_flags(newh, &flags) == ICFG_SUCCESS) { - if (flags & IFF_DHCPRUNNING) { - nlog(LOG_DEBUG, "add_ip_address: " - "turning off DHCP for %s", ifname); - nwamd_dhcp_release(ifname); - } - } - /* - * Set interface IFF_UP if not already. Do this and - * setting of prefixlen/broadcast addresses as otherwise - * these can trigger an RTM_DELADDR that makes it appear - * that the address has gone away. - */ - rc = icfg_set_addr(newh, - (const struct sockaddr *)&nifa->address, - intf.if_protocol == AF_INET ? - sizeof (struct sockaddr_in) : - sizeof (struct sockaddr_in6)); - } - if (rc != ICFG_SUCCESS) { - nlog(LOG_DEBUG, "add_ip_address: add of ipaddr failed " - "for %s: %d", ifname, rc); - goto out; - } - - if (nifa->prefix != 0) { - if ((rc = icfg_set_prefixlen(newh, nifa->prefix)) - != ICFG_SUCCESS) { - nlog(LOG_ERR, "add_ip_address: icfg_set_prefix %d " - "failed on %s: %s", nifa->prefix, ifname, - icfg_errmsg(rc)); - } else if (intf.if_protocol == AF_INET) { - /* Set broadcast address based on address, prefixlen */ - bcastaddr.sin_addr.s_addr = - /*LINTED*/ - ((struct sockaddr_in *)&nifa->address) - ->sin_addr.s_addr | - htonl(0xffffffff >> nifa->prefix); - - if ((rc = icfg_set_broadcast(newh, &bcastaddr)) - != ICFG_SUCCESS) { - nlog(LOG_ERR, "add_ip_address: " - "icfg_set_broadcast(%s) failed on %s: %s", - inet_ntoa(bcastaddr.sin_addr), ifname, - icfg_errmsg(rc)); - } - } - } - if (rc == ICFG_SUCCESS) { - if (icfg_get_flags(newh, &flags) == ICFG_SUCCESS) { - if ((flags & IFF_UP) == 0) - rc = icfg_set_flags(newh, flags | IFF_UP); - } else { - nlog(LOG_DEBUG, "add_ip_address: couldn't bring up %s", - ifname); - } - } - -out: - /* Check if address was a duplicate */ - if (rc == ICFG_DAD_FOUND || (flags & IFF_DUPLICATE) != 0) { - char *object_name; - nwam_error_t err; - - nlog(LOG_INFO, "add_ip_address: " - "duplicate address detected on %s", ifname); - if ((err = nwam_ncu_name_to_typed_name(ifname, - NWAM_NCU_TYPE_INTERFACE, &object_name)) == NWAM_SUCCESS) { - nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, - object_name, NWAM_STATE_MAINTENANCE, - NWAM_AUX_STATE_IF_DUPLICATE_ADDR); - free(object_name); - } else { - nlog(LOG_ERR, "add_ip_address: could not " - "create state event for %s: %s", ifname, - nwam_strerror(err)); - } - rc = ICFG_DAD_FOUND; - } - - if (h != newh) - icfg_close(newh); - icfg_close(h); - - return (rc == ICFG_SUCCESS); -} - void nwamd_add_default_routes(nwamd_ncu_t *ncu) { - nwamd_if_t *nif = &ncu->ncu_node.u_if; + nwamd_if_t *nif = &ncu->ncu_if; char str[INET6_ADDRSTRLEN]; if (nif->nwamd_if_ipv4 && nif->nwamd_if_ipv4_default_route_set) { @@ -389,8 +235,8 @@ nwamd_add_default_routes(nwamd_ncu_t *ncu) v4mask.sin_family = AF_INET; nlog(LOG_DEBUG, "nwamd_add_default_routes: adding default " - "route %s", nwamd_sockaddr_to_str - ((struct sockaddr *)&nif->nwamd_if_ipv4_default_route, str, + "route %s", nwamd_sockaddr2str((struct sockaddr *) + &nif->nwamd_if_ipv4_default_route, str, sizeof (str))); nwamd_add_route((struct sockaddr *)&v4dest, (struct sockaddr *)&v4mask, @@ -408,8 +254,8 @@ nwamd_add_default_routes(nwamd_ncu_t *ncu) v6mask.sin6_family = AF_INET6; nlog(LOG_DEBUG, "nwamd_add_default_routes: adding default " - "route %s", nwamd_sockaddr_to_str - ((struct sockaddr *)&nif->nwamd_if_ipv6_default_route, str, + "route %s", nwamd_sockaddr2str((struct sockaddr *) + &nif->nwamd_if_ipv6_default_route, str, sizeof (str))); nwamd_add_route((struct sockaddr *)&v6dest, (struct sockaddr *)&v6mask, @@ -418,154 +264,82 @@ nwamd_add_default_routes(nwamd_ncu_t *ncu) } } -void -nwamd_dhcp_inform(nwamd_ncu_t *ncu) -{ - struct nwamd_dhcp_thread_arg *arg; - char *name = NULL; - pthread_attr_t attr; - - arg = malloc(sizeof (*arg)); - if (arg == NULL) { - nlog(LOG_ERR, "nwamd_dhcp_inform: error allocating memory " - "for dhcp request"); - free(name); - return; - } - - arg->name = strdup(ncu->ncu_name); - arg->type = DHCP_INFORM; - arg->timeout = DHCP_IPC_WAIT_DEFAULT; - - (void) pthread_attr_init(&attr); - (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (pthread_create(NULL, &attr, start_dhcp_thread, arg) == -1) { - nlog(LOG_ERR, "Cannot start dhcp thread"); - free(name); - free(arg); - (void) pthread_attr_destroy(&attr); - return; - } - (void) pthread_attr_destroy(&attr); -} - -static boolean_t -addresses_match(const struct sockaddr *addr1, const struct sockaddr *addr2) -{ - if (addr1->sa_family != addr2->sa_family) - return (B_FALSE); - - switch (addr1->sa_family) { - case AF_INET: - /*LINTED*/ - return (memcmp(&((struct sockaddr_in *)addr1)->sin_addr, - /*LINTED*/ - &((struct sockaddr_in *)addr2)->sin_addr, - sizeof (struct in_addr)) == 0); - case AF_INET6: - /*LINTED*/ - return (memcmp(&((struct sockaddr_in6 *)addr1)->sin6_addr, - /*LINTED*/ - &((struct sockaddr_in6 *)addr2)->sin6_addr, - sizeof (struct in6_addr)) == 0); - default: - return (B_FALSE); - } -} - /* * Returns the nwamd_if_address structure for the given static address, * NULL if not found. */ static struct nwamd_if_address * -find_static_address(const struct sockaddr *addr, const nwamd_ncu_t *ncu) +find_static_address(const struct sockaddr_storage *addr, const nwamd_ncu_t *ncu) { - struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list; + struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list; + struct sockaddr_storage saddr; char str[INET6_ADDRSTRLEN]; - nlog(LOG_DEBUG, "find_static_address %s", - nwamd_sockaddr_to_str(addr, str, sizeof (str))); - for (n = nifa; n != NULL; n = n->next) { - if (addresses_match(addr, &n->address)) - return (n); + nlog(LOG_DEBUG, "find_static_address: %s", + nwamd_sockaddr2str((struct sockaddr *)addr, str, sizeof (str))); + for (nifap = nifa; nifap != NULL; nifap = nifap->next) { + if (nifap->ipaddr_atype != IPADM_ADDR_STATIC || + ipadm_get_addr(nifap->ipaddr, &saddr) != IPADM_SUCCESS) + continue; + + if (sockaddrcmp(addr, &saddr)) + return (nifap); } return (NULL); } /* * Returns the nwamd_if_address structure representing the non-static address - * in the NCU. dhcp is used to detemrine if the DHCP (stateful for v6) - * structure is needed or the stateless/autoconf structure for the given - * family. dhcp should be B_TRUE if looking for v4. Will only return the - * nwamd_if_address if the relevant address is configured (v4 DHCP, v6 - * stateless/stateful) for the NCU. - * - * Returns NULL if structure is not found. + * in the NCU. For IPv6, both stateless and stateful (DHCPv6) share the same + * nwamd_if_address. Will only return the nwamd_if_address if the relevant + * address is configured (v4 DHCP, v6 either stateless or stateless) for the + * NCU. Returns NULL if the structure is not found. */ static struct nwamd_if_address * -find_nonstatic_address(const nwamd_ncu_t *ncu, ushort_t family, boolean_t dhcp) +find_nonstatic_address(const nwamd_ncu_t *ncu, sa_family_t family) { - struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list; - const nwamd_if_t *u_if = &ncu->ncu_node.u_if; + struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list; + const nwamd_if_t *u_if = &ncu->ncu_if; + + nlog(LOG_DEBUG, "find_nonstatic_address for %s %s", + (family == AF_INET ? "IPv4" : "IPv6"), ncu->ncu_name); + for (nifap = nifa; nifap != NULL; nifap = nifap->next) { + if (nifap->ipaddr_atype == IPADM_ADDR_STATIC) + continue; - nlog(LOG_DEBUG, "find_nonstatic_address: %s", - dhcp ? "dhcp" : "stateless"); - for (n = nifa; n != NULL; n = n->next) { if (family == AF_INET) { - if (!dhcp) - return (NULL); - if (n->address.sa_family == family && n->dhcp_if && - u_if->nwamd_if_dhcp_configured) - return (n); + if (nifap->ipaddr_atype == IPADM_ADDR_DHCP && + u_if->nwamd_if_dhcp_requested) + return (nifap); } else if (family == AF_INET6) { - if (n->address.sa_family == family) { - if (dhcp && n->dhcp_if && - u_if->nwamd_if_stateful_configured) - return (n); - else if (!dhcp && n->stateless_if && - u_if->nwamd_if_stateless_configured) - return (n); - } + if (nifap->ipaddr_atype == IPADM_ADDR_IPV6_ADDRCONF && + (u_if->nwamd_if_stateful_requested || + u_if->nwamd_if_stateless_requested)) + return (nifap); } } return (NULL); } /* - * Sets "configured" nwam_if_address value for corresponding address. - * Used when we process IF_STATE events to handle RTM_NEWADDR/DELADDRs. + * Returns the nwamd_if_address structure that configured the given address, + * NULL if not found. */ -static boolean_t -update_address_configured_value(const struct sockaddr *configured_addr, - nwamd_ncu_t *ncu, boolean_t configured) +static struct nwamd_if_address * +find_configured_address(const struct sockaddr_storage *addr, + const nwamd_ncu_t *ncu) { - struct nwamd_if_address *n; + struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list; char str[INET6_ADDRSTRLEN]; - nlog(LOG_DEBUG, "update_address_configured_value(%s, %s, %s)", - nwamd_sockaddr_to_str(configured_addr, str, sizeof (str)), - ncu->ncu_name, configured ? "configure" : "unconfigure"); - n = find_static_address(configured_addr, ncu); - if (n) { - n->configured = configured; - nlog(LOG_DEBUG, "update_address_configured_value: marking " - "address %s", - nwamd_sockaddr_to_str(&n->address, str, sizeof (str))); - return (B_TRUE); + nlog(LOG_DEBUG, "find_configured_address: %s", + nwamd_sockaddr2str((struct sockaddr *)addr, str, sizeof (str))); + for (nifap = nifa; nifap != NULL; nifap = nifap->next) { + if (sockaddrcmp(addr, &nifap->conf_addr) || + sockaddrcmp(addr, &nifap->conf_stateless_addr)) + return (nifap); } - return (B_FALSE); -} - -void -nwamd_update_addresses_unconfigured(nwamd_ncu_t *ncu, sa_family_t af) -{ - struct nwamd_if_address *n, *nifa = ncu->ncu_node.u_if.nwamd_if_list; - - for (n = nifa; n != NULL; n = n->next) - if (af == AF_UNSPEC || n->address.sa_family == af) { - n->configured = B_FALSE; - nwamd_log_if_address(LOG_DEBUG, n); - } + return (NULL); } /* @@ -576,9 +350,11 @@ nwamd_static_addresses_configured(nwamd_ncu_t *ncu, sa_family_t family) { struct nwamd_if_address *n; - for (n = ncu->ncu_node.u_if.nwamd_if_list; n != NULL; n = n->next) { - if ((family == AF_UNSPEC || family == n->address.sa_family) && - n->configured && !n->dhcp_if && !n->stateless_if) + for (n = ncu->ncu_if.nwamd_if_list; n != NULL; n = n->next) { + if (n->ipaddr_atype != IPADM_ADDR_STATIC) + continue; + if ((family == AF_UNSPEC || family == n->family) && + n->configured) return (B_TRUE); } nlog(LOG_DEBUG, "no static addresses configured for %s", ncu->ncu_name); @@ -595,36 +371,25 @@ nwamd_static_addresses_configured(nwamd_ncu_t *ncu, sa_family_t family) boolean_t nwamd_dhcp_managing(int protocol, nwamd_ncu_t *ncu) { - icfg_if_t *iflist; - icfg_handle_t ifh; - int numif, i; - struct sockaddr_storage addr; - socklen_t len; - int prefixlen; + struct sockaddr_storage *addr; uint64_t flags; boolean_t rv = B_FALSE; - - if (icfg_get_if_list(&iflist, &numif, protocol, ICFG_PLUMBED) != - ICFG_SUCCESS) { - return (B_TRUE); + ipadm_addr_info_t *addrinfo, *a; + ipadm_status_t ipstatus; + + if ((ipstatus = ipadm_addr_info(ipadm_handle, ncu->ncu_name, &addrinfo, + 0, 0)) != IPADM_SUCCESS) { + nlog(LOG_ERR, "nwamd_dhcp_managing: " + "ipadm_addr_info failed for %s: %s", + ncu->ncu_name, ipadm_status2str(ipstatus)); + return (B_FALSE); } - for (i = 0; i < numif; i++) { - if (strncmp(iflist[i].if_name, ncu->ncu_name, - strlen(ncu->ncu_name)) != 0) - continue; - - if (icfg_open(&ifh, &iflist[i]) != ICFG_SUCCESS) - continue; + for (a = addrinfo; a != NULL; a = IA_NEXT(a)) { /* is this address an expected static one? */ - len = sizeof (addr); - if (icfg_get_addr(ifh, (struct sockaddr *)&addr, &len, - &prefixlen, B_FALSE) != ICFG_SUCCESS || - find_static_address((struct sockaddr *)&addr, ncu) - != NULL) { - icfg_close(ifh); + addr = a->ia_ifa.ifa_addr; + if (find_static_address(addr, ncu) != NULL) continue; - } /* * For IPv4, DHCPRUNNING flag is set when dhcpagent is in @@ -635,31 +400,32 @@ nwamd_dhcp_managing(int protocol, nwamd_ncu_t *ncu) * as not being managed by DHCP and skip checking of flags. */ if ((protocol == AF_INET && - ((struct sockaddr_in *)&addr)->sin_addr.s_addr == + ((struct sockaddr_in *)addr)->sin_addr.s_addr == INADDR_ANY) || (protocol == AF_INET6 && IN6_IS_ADDR_LINKLOCAL( - &((struct sockaddr_in6 *)&addr)->sin6_addr))) { - icfg_close(ifh); + &((struct sockaddr_in6 *)addr)->sin6_addr))) { continue; } - if (icfg_get_flags(ifh, &flags) == ICFG_SUCCESS && - (flags & IFF_DHCPRUNNING)) { + flags = a->ia_ifa.ifa_flags; + if (flags & IFF_DHCPRUNNING) { /* * If we get here we have an address that has the * DHCP flag set and isn't an expected static address. */ - icfg_close(ifh); rv = B_TRUE; break; } } - icfg_free_if_list(iflist); + ipadm_free_addr_info(addrinfo); return (rv); } +/* + * Return B_TRUE if IPv4 is requested in the given NCU. + */ static boolean_t nwamd_v4_requested(nwamd_ncu_t *ncu) { @@ -667,22 +433,27 @@ nwamd_v4_requested(nwamd_ncu_t *ncu) nwamd_if_t *u_if; anyv4_requested = B_FALSE; - u_if = &ncu->ncu_node.u_if; + u_if = &ncu->ncu_if; if (u_if->nwamd_if_dhcp_requested) { anyv4_requested = B_TRUE; } else { - struct nwamd_if_address *a; - for (a = u_if->nwamd_if_list; - a != NULL && a->address.sa_family != AF_INET; - a = a->next) - /* Empty loop body */; - if (a != NULL) + struct nwamd_if_address *n; + + for (n = u_if->nwamd_if_list; n != NULL; n = n->next) { + if (n->family == AF_INET && + n->ipaddr_atype == IPADM_ADDR_STATIC) + break; + } + if (n != NULL) anyv4_requested = B_TRUE; } return (anyv4_requested); } +/* + * Returns B_TRUE if IPv6 is requested in the given NCU. + */ static boolean_t nwamd_v6_requested(nwamd_ncu_t *ncu) { @@ -690,17 +461,19 @@ nwamd_v6_requested(nwamd_ncu_t *ncu) nwamd_if_t *u_if; anyv6_requested = B_FALSE; - u_if = &ncu->ncu_node.u_if; + u_if = &ncu->ncu_if; if (u_if->nwamd_if_stateful_requested || u_if->nwamd_if_stateless_requested) { anyv6_requested = B_TRUE; } else { - struct nwamd_if_address *a; - for (a = u_if->nwamd_if_list; - a != NULL && a->address.sa_family != AF_INET6; - a = a->next) - /* Empty loop body */; - if (a != NULL) + struct nwamd_if_address *n; + + for (n = u_if->nwamd_if_list; n != NULL; n = n->next) { + if (n->family == AF_INET6 && + n->ipaddr_atype == IPADM_ADDR_STATIC) + break; + } + if (n != NULL) anyv6_requested = B_TRUE; } @@ -771,171 +544,229 @@ interface_ncu_down(nwamd_ncu_t *ncu) interface_ncu_up_down(ncu, B_FALSE); } -/* Callback to find if DHCP is running on the interface index */ -static int -flags_set_for_ifindex_cb(icfg_if_t *intf, void *arg, uint64_t flags_wanted) +static boolean_t +stateless_running(const nwamd_ncu_t *ncu) { - int *indexp = arg; - icfg_handle_t h; - int index; - uint64_t flags = 0; - - if (icfg_open(&h, intf) != ICFG_SUCCESS) { - nlog(LOG_ERR, "flags_set_for_ifindex_cb: icfg_open failed"); - return (0); - } - if (icfg_get_index(h, &index) != ICFG_SUCCESS) { - nlog(LOG_ERR, - "flags_set_for_ifindex_cb: icfg_get_index failed"); - icfg_close(h); - return (0); - } - if (index != *indexp) { - icfg_close(h); - return (0); - } + ipadm_addr_info_t *ainfo, *ainfop; + ipadm_status_t ipstatus; + boolean_t rv = B_FALSE; + uint64_t flags; - if (icfg_get_flags(h, &flags) != ICFG_SUCCESS) { - nlog(LOG_ERR, - "flags_set_for_ifindex_cb: icfg_get_flags failed"); + if ((ipstatus = ipadm_addr_info(ipadm_handle, ncu->ncu_name, &ainfo, + 0, 0)) != IPADM_SUCCESS) { + nlog(LOG_ERR, "stateless_running: " + "ipadm_addr_info failed for %s: %s", + ncu->ncu_name, ipadm_status2str(ipstatus)); + return (B_FALSE); } - icfg_close(h); - return ((flags & flags_wanted) == flags_wanted); -} -static int -stateless_running_for_ifindex_cb(icfg_if_t *intf, void *arg) -{ - return (flags_set_for_ifindex_cb(intf, arg, - IFF_RUNNING | IFF_ADDRCONF | IFF_UP)); + for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) { + if (ainfop->ia_ifa.ifa_addr->ss_family != AF_INET6) + continue; + flags = ainfop->ia_ifa.ifa_flags; + if (flags & STATELESS_RUNNING) { + rv = B_TRUE; + break; + } + } + ipadm_free_addr_info(ainfo); + return (rv); } /* - * Is autoconf running on the interface with specified ifindex? + * Returns the addrinfo associated with the given address. There is always + * only one addrinfo for each address. */ static boolean_t -stateless_running_for_ifindex(int ifindex) +addrinfo_for_addr(const struct sockaddr_storage *caddr, const char *ifname, + ipadm_addr_info_t **ainfo) { - return (icfg_iterate_if(AF_INET6, ICFG_PLUMBED, &ifindex, - stateless_running_for_ifindex_cb) != 0); + ipadm_addr_info_t *addrinfo, *ainfop, *last = NULL; + ipadm_status_t ipstatus; + + ipstatus = ipadm_addr_info(ipadm_handle, ifname, &addrinfo, 0, 0); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_INFO, "addrinfo_for_addr: " + "ipadm_addr_info failed for %s: %s", + ifname, ipadm_status2str(ipstatus)); + return (B_FALSE); + } + + *ainfo = NULL; + for (ainfop = addrinfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) { + /* + * If addresses match, rearrange pointers so that addrinfo + * does not contain a, and return a. + */ + if (sockaddrcmp(ainfop->ia_ifa.ifa_addr, caddr)) { + if (last != NULL) + last->ia_ifa.ifa_next = ainfop->ia_ifa.ifa_next; + else + addrinfo = IA_NEXT(ainfop); + + ainfop->ia_ifa.ifa_next = NULL; + *ainfo = ainfop; + break; + } + last = ainfop; + } + ipadm_free_addr_info(addrinfo); + return (*ainfo == NULL ? B_FALSE : B_TRUE); } +/* + * Returns B_TRUE if the addrinfo associated with the given ipaddr using its + * aobjname is found. An addrinfo list is created and returned in ainfo. + * Stateless and stateful IPv6 addrinfo have the same aobjname, thus the need + * to create a list of addrinfo. + */ static boolean_t -stateless_running(const nwamd_ncu_t *ncu) +addrinfo_for_ipaddr(ipadm_addrobj_t ipaddr, const char *ifname, + ipadm_addr_info_t **ainfo) { - int index; - icfg_if_t intf; - icfg_handle_t ifh; - - intf.if_protocol = AF_INET6; - (void) strlcpy(intf.if_name, ncu->ncu_name, sizeof (intf.if_name)); - if (icfg_open(&ifh, &intf) != ICFG_SUCCESS) { - nlog(LOG_ERR, "stateless_running: icfg_open(%s) failed", - ncu->ncu_name); + char aobjname[IPADM_AOBJSIZ]; + ipadm_addr_info_t *addrinfo, *ainfop; + ipadm_addr_info_t *last = NULL; + ipadm_status_t ipstatus; + + ipstatus = ipadm_get_aobjname(ipaddr, aobjname, sizeof (aobjname)); + if (ipstatus != IPADM_SUCCESS) return (B_FALSE); - } - if (icfg_get_index(ifh, &index) != ICFG_SUCCESS) { - nlog(LOG_ERR, "stateless_running: icfg_get_index(%s) failed", - ncu->ncu_name); + ipstatus = ipadm_addr_info(ipadm_handle, ifname, &addrinfo, 0, 0); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_INFO, "addrinfo_for_ipaddr: " + "ipadm_addr_info failed for %s: %s", + ifname, ipadm_status2str(ipstatus)); return (B_FALSE); } - icfg_close(ifh); - - return (stateless_running_for_ifindex(index)); + *ainfo = NULL; + ainfop = addrinfo; + while (ainfop != NULL) { + /* If aobjnames match, rearrange pointers to create new list */ + if (strcmp(ainfop->ia_aobjname, aobjname) == 0) { + ipadm_addr_info_t *match = ainfop; + + ainfop = IA_NEXT(ainfop); /* move iterator */ + if (last != NULL) + last->ia_ifa.ifa_next = match->ia_ifa.ifa_next; + else + addrinfo = ainfop; + if (*ainfo == NULL) + match->ia_ifa.ifa_next = NULL; + else + match->ia_ifa.ifa_next = &(*ainfo)->ia_ifa; + *ainfo = match; + } else { + last = ainfop; + ainfop = IA_NEXT(ainfop); + } + } + ipadm_free_addr_info(addrinfo); + return (*ainfo == NULL ? B_FALSE : B_TRUE); } -void -nwamd_configure_interface_addresses(nwamd_ncu_t *ncu) +/* + * Add the address provided in the nwamd_if_address. If DHCP is required, + * start DHCP. If a static address is configured, create the address; then do + * a DHCP_INFORM (in a separate thread) to get other networking configuration + * parameters. RTM_NEWADDRs - translated into IF_STATE events - will then + * finish the job of bringing the NCU online. + */ +static boolean_t +add_ip_address(const char *ifname, const struct nwamd_if_address *nifa) { - struct nwamd_if_address *nifa = ncu->ncu_node.u_if.nwamd_if_list; - struct nwamd_if_address *n; - int num_configured_v4 = 0; - boolean_t add_logical_if; + ipadm_status_t ipstatus; + ipadm_addr_info_t *addrinfo = NULL; + uint64_t flags; - nlog(LOG_DEBUG, "nwamd_configure_interface_addresses(%s)", - ncu->ncu_name); + if (nifa->ipaddr_atype == IPADM_ADDR_DHCP) { + /* + * To make getting a DHCP address asynchronous, call + * ipadm_create_addr() in a new thread. + */ + nlog(LOG_DEBUG, "add_ip_address: " + "adding IPv4 DHCP address on %s", ifname); + nwamd_dhcp(ifname, nifa->ipaddr, DHCP_START); + } else { + nlog(LOG_DEBUG, "add_ip_address: adding %s address on %s", + (nifa->ipaddr_atype == IPADM_ADDR_STATIC ? + "STATIC" : "IPv6 ADDRCONF"), ifname); + if ((ipstatus = ipadm_create_addr(ipadm_handle, nifa->ipaddr, + IPADM_OPT_ACTIVE | IPADM_OPT_UP)) != IPADM_SUCCESS) { + nlog(LOG_ERR, "add_ip_address: " + "ipadm_create_addr failed on %s: %s", + ifname, ipadm_status2str(ipstatus)); + return (B_FALSE); + } + /* + * When creating a static address, ipadm_create_addr() returns + * SUCCESS even if duplicate address is detected. Retrieve + * the addrinfo to get the flags. + */ + if (nifa->ipaddr_atype == IPADM_ADDR_STATIC) { + /* + * Since we are configuring a static address, there + * will be just *ONE* addrinfo with the aobjname in + * nifa->ipaddr. + */ + if (!addrinfo_for_ipaddr(nifa->ipaddr, ifname, + &addrinfo)) { + nlog(LOG_ERR, "add_ip_address: " + "could not find addrinfo on %s", ifname); + return (B_FALSE); + } - /* - * Add static addresses. For IPv4, we only use the physical interface - * (i.e. not a logical interface) if DHCP has not been requested and - * this is the first address to be configured. - */ - for (n = nifa; n != NULL; n = n->next) { - if (n->configured || n->dhcp_if || n->stateless_if) - continue; - switch (n->address.sa_family) { - case AF_INET: - add_logical_if = (num_configured_v4 > 0 || - ncu->ncu_node.u_if.nwamd_if_dhcp_requested); - num_configured_v4++; - break; - case AF_INET6: - add_logical_if = B_TRUE; - break; + flags = addrinfo->ia_ifa.ifa_flags; + ipadm_free_addr_info(addrinfo); + if (flags & IFF_DUPLICATE) { + char *object_name; + nwam_error_t err; + + nlog(LOG_INFO, "add_ip_address: " + "duplicate address detected on %s", ifname); + if ((err = nwam_ncu_name_to_typed_name(ifname, + NWAM_NCU_TYPE_INTERFACE, &object_name)) + == NWAM_SUCCESS) { + nwamd_object_set_state( + NWAM_OBJECT_TYPE_NCU, + object_name, NWAM_STATE_MAINTENANCE, + NWAM_AUX_STATE_IF_DUPLICATE_ADDR); + free(object_name); + } else { + nlog(LOG_ERR, "add_ip_address: " + "could not create state event " + "for %s: %s", + ifname, nwam_strerror(err)); + } + return (B_FALSE); + } + /* Do DHCP_INFORM using async ipadm_refresh_addr() */ + nwamd_dhcp(ifname, nifa->ipaddr, DHCP_INFORM); } - n->configured = add_ip_address(ncu->ncu_name, n, - add_logical_if); } -} - -static int -lifnum_from_ifname(const char *ifname) -{ - char *lifstr = strchr(ifname, ':'); - if (lifstr != NULL) { - lifstr++; - return (atoi(lifstr)); - } - return (0); + return (B_TRUE); } /* - * Copies the ifname (with lifnum) associated with the given address. - * Returns B_TRUE if a match is found, B_FASLE otherwise. + * Adds addresses for the given NCU. */ -static boolean_t -ifname_for_addr(const struct sockaddr *caddr, char *ifname, int len) +void +nwamd_configure_interface_addresses(nwamd_ncu_t *ncu) { - struct sockaddr_in6 addr; - int numif, i, prefixlen; - icfg_if_t *iflist; - icfg_handle_t ifh; - socklen_t slen; - - if (icfg_get_if_list(&iflist, &numif, caddr->sa_family, ICFG_PLUMBED) - != ICFG_SUCCESS) { - nlog(LOG_DEBUG, "ifname_for_addr: icfg_get_if_list failed"); - return (B_FALSE); - } + struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list; - for (i = 0; i < numif; i++) { - if (icfg_open(&ifh, &iflist[i]) != ICFG_SUCCESS) { - nlog(LOG_ERR, "ifname_for_addr: icfg_open %s failed", - iflist[i].if_name); + nlog(LOG_DEBUG, "nwamd_configure_interface_addresses(%s)", + ncu->ncu_name); + + for (nifap = nifa; nifap != NULL; nifap = nifap->next) { + if (nifap->configured) continue; - } - slen = sizeof (addr); - if (icfg_get_addr(ifh, (struct sockaddr *)&addr, - &slen, &prefixlen, B_FALSE) != ICFG_SUCCESS) { - nlog(LOG_ERR, "ifname_for_addr: " - "icfg_get_addr %s failed", iflist[i].if_name); - } else { - /* Compare addresses */ - if (addresses_match((struct sockaddr *)&addr, caddr)) { - (void) strlcpy(ifname, iflist[i].if_name, len); - icfg_close(ifh); - icfg_free_if_list(iflist); - return (B_TRUE); - } - } - icfg_close(ifh); + nifap->configured = add_ip_address(ncu->ncu_name, nifap); } - icfg_free_if_list(iflist); - return (B_FALSE); } /* @@ -1001,95 +832,144 @@ nwamd_ncu_handle_if_state_event(nwamd_event_t event) if (evm->nwe_data.nwe_if_state.nwe_addr_valid) { struct nwam_event_if_state *if_state; - boolean_t stateless_running; - char addrstr[INET6_ADDRSTRLEN], ifname[LIFNAMSIZ]; - boolean_t v4dhcp_running; - boolean_t v6dhcp_running; - struct nwamd_if_address *nifa; - struct sockaddr *addr; - boolean_t static_addr; - icfg_if_t intf; - icfg_handle_t ifh; + char addrstr[INET6_ADDRSTRLEN]; + boolean_t static_addr, addr_added; + boolean_t v4dhcp_running, v6dhcp_running, stateless_running; + ipadm_addr_info_t *ai = NULL, *addrinfo = NULL; + boolean_t stateless_ai_found = B_FALSE; + boolean_t stateful_ai_found = B_FALSE; + struct nwamd_if_address *nifa = NULL; nwamd_if_t *u_if; + struct sockaddr_storage *addr, *ai_addr = 0; ushort_t family; uint64_t flags = 0; - int lifnum; if_state = &evm->nwe_data.nwe_if_state; - u_if = &ncu->ncu_node.u_if; + u_if = &ncu->ncu_if; family = if_state->nwe_addr.ss_family; - addr = (struct sockaddr *)&if_state->nwe_addr; + addr = &if_state->nwe_addr; + addr_added = if_state->nwe_addr_added; nlog(LOG_DEBUG, "nwamd_ncu_handle_if_state_event: addr %s %s", - nwamd_sockaddr_to_str(addr, addrstr, sizeof (addrstr)), - evm->nwe_data.nwe_if_state.nwe_addr_added ? - "added" : "removed"); - - /* determine the interface name with lifnum */ - if (if_state->nwe_addr_added) { - /* figure out the ifname for the address */ - if (!ifname_for_addr(addr, ifname, sizeof (ifname))) { + nwamd_sockaddr2str((struct sockaddr *)addr, addrstr, + sizeof (addrstr)), addr_added ? "added" : "removed"); + + /* + * Need to get flags for this interface. Get the addrinfo for + * the address that generated this IF_STATE event. + */ + if (addr_added) { + /* + * Address was added. Find the addrinfo for this + * address and the nwamd_if_address corresponding to + * this address. + */ + if (!addrinfo_for_addr(addr, ncu->ncu_name, &ai)) { nlog(LOG_ERR, - "nwamd_ncu_handle_if_state_event:" - "could not find ifname for %s", addrstr); + "nwamd_ncu_handle_if_state_event: " + "addrinfo doesn't exist for %s", addrstr); nwamd_event_do_not_send(event); - goto exit; + goto valid_done; } - } else { + addrinfo = ai; + flags = addrinfo->ia_ifa.ifa_flags; + ai_addr = addrinfo->ia_ifa.ifa_addr; + + if (addrinfo->ia_atype == IPADM_ADDR_IPV6_ADDRCONF || + addrinfo->ia_atype == IPADM_ADDR_DHCP) + nifa = find_nonstatic_address(ncu, family); + else if (addrinfo->ia_atype == IPADM_ADDR_STATIC) + nifa = find_static_address(addr, ncu); + /* - * Figure out the ifname that had the address that was - * removed. The address is already gone from the - * interface, so cannot walk the interface list. + * If nwamd_if_address is not found, then this address + * isn't one that nwamd created. Remove it. */ - struct nwamd_if_address *n; - - if ((n = find_static_address(addr, ncu)) == NULL && - (n = find_nonstatic_address(ncu, family, B_TRUE)) - == NULL && - (n = find_nonstatic_address(ncu, family, B_FALSE)) - == NULL) { + if (nifa == NULL) { nlog(LOG_ERR, "nwamd_ncu_handle_if_state_event: " - "could not find nwamd_if_address for %s", - addrstr); + "address %s not managed by nwam added, " + "removing it", addrstr); + nwamd_down_interface(addrinfo->ia_aobjname, + addrinfo->ia_atype, ncu->ncu_name); nwamd_event_do_not_send(event); - goto exit; + goto valid_done; } - (void) strlcpy(ifname, n->ifname, sizeof (ifname)); - } - nlog(LOG_DEBUG, "nwamd_ncu_handle_if_state_event: " - "ifname for %s is %s", addrstr, ifname); - - /* - * Get interface flags using nwe_ifname as it is logical - * interface name. - */ - intf.if_protocol = family; - (void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name)); - lifnum = lifnum_from_ifname(intf.if_name); + /* check flags to determine how intf is configured */ + stateless_running = (family == AF_INET6) && + ((flags & STATELESS_RUNNING) == STATELESS_RUNNING); + v4dhcp_running = (family == AF_INET) && + ((flags & DHCP_RUNNING) == DHCP_RUNNING); + v6dhcp_running = (family == AF_INET6) && + ((flags & DHCP_RUNNING) == DHCP_RUNNING); + static_addr = (addrinfo->ia_atype == IPADM_ADDR_STATIC); + + /* copy the configured address into nwamd_if_address */ + if (stateless_running) { + (void) memcpy(&nifa->conf_stateless_addr, + addrinfo->ia_ifa.ifa_addr, + sizeof (struct sockaddr_storage)); + } else { + (void) memcpy(&nifa->conf_addr, + addrinfo->ia_ifa.ifa_addr, + sizeof (struct sockaddr_storage)); + } - if (icfg_open(&ifh, &intf) != ICFG_SUCCESS) { - nlog(LOG_ERR, "nwamd_ncu_handle_if_state_event: can't " - "find if %s", intf.if_name); - nwamd_event_do_not_send(event); - goto exit; - } - if (icfg_get_flags(ifh, &flags) != ICFG_SUCCESS) { - nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: can't " - "get flags for %s", icfg_if_name(ifh)); + } else { /* - * If the interface is unplumbed, icfg_get_flags() - * will fail. Don't exit, continue with empty flags. + * Address was removed. Find the nwamd_if_address + * that configured this address. */ - if (if_state->nwe_addr_added) { - icfg_close(ifh); - goto exit; + nifa = find_configured_address(addr, ncu); + if (nifa == NULL) { + nlog(LOG_ERR, + "nwamd_ncu_handle_if_state_event: " + "address %s not managed by nwam removed, " + "nothing to do", addrstr); + nwamd_event_do_not_send(event); + goto valid_done; + } + + if (addrinfo_for_ipaddr(nifa->ipaddr, ncu->ncu_name, + &ai)) { + ipadm_addr_info_t *a; + for (a = ai; a != NULL; a = IA_NEXT(a)) { + /* + * Since multiple addrinfo can have + * the same ipaddr, find the one for + * the address that generated this + * state event. + */ + if (sockaddrcmp(addr, + a->ia_ifa.ifa_addr)) { + flags = a->ia_ifa.ifa_flags; + ai_addr = a->ia_ifa.ifa_addr; + addrinfo = a; + } + /* + * Stateful and stateless IPv6 + * addrinfo have the same aobjname. + * Use the flags to determine which + * address is present in the system. + */ + if (family == AF_INET6) { + stateless_ai_found = + (a->ia_ifa.ifa_flags & + STATELESS_RUNNING); + stateful_ai_found = + (a->ia_ifa.ifa_flags & + DHCP_RUNNING); + } + } } } - if (family == AF_INET && !if_state->nwe_addr_added) { + /* Set the flags in the event for listeners */ + evm->nwe_data.nwe_if_state.nwe_flags = flags; + + if (family == AF_INET && !addr_added) { /* * Check for failure due to CR 6745448: if we get a * report that an address has been deleted, then check @@ -1100,68 +980,64 @@ nwamd_ncu_handle_if_state_event(nwamd_event_t event) * (which aren't smart enough to avoid dead * interfaces). */ - /*LINTED*/ if (((struct sockaddr_in *)addr)->sin_addr.s_addr - == INADDR_ANY) { - socklen_t slen; - struct sockaddr_in s; - int pfxlen; + == INADDR_ANY && ai_addr != 0) { + struct sockaddr_in *a; + char astr[INET6_ADDRSTRLEN]; + a = (struct sockaddr_in *)ai_addr; if ((flags & IFF_UP) && !(flags & IFF_RUNNING) && - icfg_get_addr(ifh, (struct sockaddr *)&s, - &slen, &pfxlen, B_FALSE) == ICFG_SUCCESS && - s.sin_addr.s_addr != INADDR_ANY) { - nlog(LOG_DEBUG, "bug workaround: " - "clear out addr %s on %s", - inet_ntoa(s.sin_addr), ifname); - s.sin_addr.s_addr = INADDR_ANY; - (void) icfg_set_addr(ifh, - (const struct sockaddr *)&s, slen); + a->sin_addr.s_addr != INADDR_ANY) { + nlog(LOG_DEBUG, + "nwamd_ncu_handle_if_state_event: " + "bug workaround: clear out addr " + "%s on %s", nwamd_sockaddr2str + ((struct sockaddr *)a, astr, + sizeof (astr)), + ncu->ncu_name); + nwamd_down_interface( + addrinfo->ia_aobjname, + IPADM_ADDR_DHCP, ncu->ncu_name); } - icfg_close(ifh); - goto exit; + goto valid_done; } } /* - * Has address really been removed? Sometimes spurious + * If we received an RTM_NEWADDR and the IFF_UP flags has not + * been set, ignore this IF_STATE event. Once the IFF_UP flag + * is set, we'll get another RTM_NEWADDR message. + */ + if (addr_added & !(flags & IFF_UP)) { + nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: " + "address %s added on %s without IFF_UP flag (%x), " + "ignoring IF_STATE event", + addrstr, ncu->ncu_name, flags); + nwamd_event_do_not_send(event); + goto valid_done; + } + + /* + * Has the address really been removed? Sometimes spurious * RTM_DELADDRs are generated, so we need to ensure that * the address is really gone. If IFF_DUPLICATE is set, * we're getting the RTM_DELADDR due to DAD, so don't test * in that case. */ - if (!if_state->nwe_addr_added && !(flags & IFF_DUPLICATE)) { - struct sockaddr_storage ifaddr; - socklen_t len; - int plen; - - len = family == AF_INET ? sizeof (struct sockaddr_in) : - sizeof (struct sockaddr_in6); - if (icfg_get_addr(ifh, (struct sockaddr *)&ifaddr, &len, - &plen, B_FALSE) == ICFG_SUCCESS && - addresses_match(addr, (struct sockaddr *)&ifaddr)) { - nlog(LOG_DEBUG, + if (!addr_added && !(flags & IFF_DUPLICATE)) { + if (ai_addr != 0 && sockaddrcmp(addr, ai_addr)) { + nlog(LOG_INFO, "nwamd_ncu_handle_if_state_event: " "address %s is not really gone from %s, " "ignoring IF_STATE event", - addrstr, intf.if_name); - icfg_close(ifh); + addrstr, ncu->ncu_name); nwamd_event_do_not_send(event); - goto exit; + goto valid_done; } } - icfg_close(ifh); - stateless_running = (family == AF_INET6) && - ((flags & STATELESS_RUNNING) == STATELESS_RUNNING); - v4dhcp_running = (family == AF_INET) && - ((flags & DHCP_RUNNING) == DHCP_RUNNING); - v6dhcp_running = (family == AF_INET6) && - ((flags & DHCP_RUNNING) == DHCP_RUNNING); - static_addr = (find_static_address(addr, ncu) != NULL); - - if (if_state->nwe_addr_added) { + if (addr_added) { /* * Address has been added. * @@ -1170,63 +1046,27 @@ nwamd_ncu_handle_if_state_event(nwamd_event_t event) * address but by the time we got here we don't really * want it and need to remove it. * - * [Note that since we use DHCP inform on interfaces - * with static addresses that they will also have the - * DHCP flag set on the interface.] - * * Once we decide we want the address adjust the ncu * state accordingly. For example if this address is * enough move online. */ - - /* Figure out if we want to keep this address. */ - if (static_addr) { - nifa = find_static_address(addr, ncu); - assert(nifa != NULL); - nifa->configured = B_TRUE; - (void) strlcpy(nifa->ifname, ifname, - sizeof (nifa->ifname)); - } else if (u_if->nwamd_if_dhcp_requested && - v4dhcp_running) { + if (u_if->nwamd_if_dhcp_requested && v4dhcp_running) { u_if->nwamd_if_dhcp_configured = B_TRUE; - nifa = find_nonstatic_address(ncu, family, - B_TRUE); - assert(nifa != NULL); - (void) strlcpy(nifa->ifname, ifname, - sizeof (nifa->ifname)); } else if (u_if->nwamd_if_stateful_requested && v6dhcp_running) { u_if->nwamd_if_stateful_configured = B_TRUE; - nifa = find_nonstatic_address(ncu, family, - B_TRUE); - assert(nifa != NULL); - (void) strlcpy(nifa->ifname, ifname, - sizeof (nifa->ifname)); } else if (u_if->nwamd_if_stateless_requested && stateless_running) { u_if->nwamd_if_stateless_configured = B_TRUE; - nifa = find_nonstatic_address(ncu, family, - B_FALSE); - assert(nifa != NULL); - (void) strlcpy(nifa->ifname, ifname, - sizeof (nifa->ifname)); - } else { + } else if (!static_addr) { /* * This is something we didn't expect. Remove - * it by unplumbing the logical interface. + * the address. */ - if (u_if->nwamd_if_dhcp_requested && - v4dhcp_running) - nwamd_dhcp_release(ncu->ncu_name); - if (lifnum == 0) { - nwamd_down_interface(ncu->ncu_name, - lifnum, family); - interface_ncu_down(ncu); - } else { - nwamd_unplumb_interface(ncu, lifnum, - family); - } - goto exit; + nwamd_down_interface(addrinfo->ia_aobjname, + addrinfo->ia_atype, ncu->ncu_name); + nifa->configured = B_FALSE; + goto valid_done; } /* @@ -1235,8 +1075,7 @@ nwamd_ncu_handle_if_state_event(nwamd_event_t event) * v4 is configured or a v6 address if only v6 is * configured. */ - (void) update_address_configured_value(addr, ncu, - B_TRUE); + nifa->configured = B_TRUE; if (state != NWAM_STATE_ONLINE) interface_ncu_up(ncu); @@ -1255,6 +1094,7 @@ nwamd_ncu_handle_if_state_event(nwamd_event_t event) "event: refresh of %s " "failed", NET_LOC_FMRI); } + } else if (state == NWAM_STATE_ONLINE || state == NWAM_STATE_OFFLINE_TO_ONLINE) { /* @@ -1267,21 +1107,24 @@ nwamd_ncu_handle_if_state_event(nwamd_event_t event) * We can get RTM_DELADDRs for duplicate addresses * so deal with this seperately. */ - if (static_addr) { - (void) update_address_configured_value(addr, - ncu, B_FALSE); - } else if (family == AF_INET) { + nifa->configured = B_FALSE; + + if (!static_addr && family == AF_INET) { u_if->nwamd_if_dhcp_configured = B_FALSE; - } else if (family == AF_INET6) { + } else if (!static_addr && family == AF_INET6) { /* - * The address is already gone. I'm not sure - * how we figure out if this address is - * stateful (DHCP) or stateless. When we - * are managing IPv6 more explicitly this will - * have to be done more carefully. + * The address is already gone. When looking + * for the addrinfo (using aobjname in + * ipaddr), we found addrinfo for either one + * or both stateless and stateful. Using the + * flags we determined whether each was + * configured or not. Update the flags here + * accordingly. */ - u_if->nwamd_if_stateful_configured = B_FALSE; - u_if->nwamd_if_stateless_configured = B_FALSE; + u_if->nwamd_if_stateful_configured = + stateless_ai_found; + u_if->nwamd_if_stateless_configured = + stateful_ai_found; } if (flags & IFF_DUPLICATE) { @@ -1297,8 +1140,9 @@ nwamd_ncu_handle_if_state_event(nwamd_event_t event) interface_ncu_down(ncu); } } +valid_done: + ipadm_free_addr_info(ai); } -exit: nwamd_object_release(ncu_obj); } @@ -1320,140 +1164,104 @@ nwamd_ncu_handle_if_action_event(nwamd_event_t event) } /* - * This function downs any logical interface and just zeros the address off of - * the physical interface (logical interface 0). If you want to unplumb 0 then - * you need to call nwamd_unplumb_interface() directly. + * Remove the address in the given aobjname. IPADM_OPT_RELEASE is specified + * for a DHCP address and specifies that the DHCP lease should also be released. + * ifname is only used for nlog(). */ static void -nwamd_down_interface(const char *linkname, uint_t lifnum, int family) +nwamd_down_interface(const char *aobjname, ipadm_addr_type_t atype, + const char *ifname) { - uint64_t flags; - icfg_if_t intf; - icfg_handle_t h; - icfg_error_t rc; - - if (linkname == NULL) { - nlog(LOG_ERR, "nwamd_down_interface: linkname null"); - return; - } - - (void) nwamd_link_to_ifname(linkname, lifnum, intf.if_name, - sizeof (intf.if_name)); - intf.if_protocol = family; - - rc = icfg_open(&h, &intf); - if (rc != ICFG_SUCCESS) { - nlog(LOG_ERR, "nwamd_down_interface: icfg_open failed for %s: " - "%s", intf.if_name, icfg_errmsg(rc)); - return; + ipadm_status_t ipstatus; + uint32_t rflags = (atype == IPADM_ADDR_DHCP ? IPADM_OPT_RELEASE : 0); + + nlog(LOG_DEBUG, "nwamd_down_interface: %s [aobjname = %s]", + ifname, aobjname); + if ((ipstatus = ipadm_delete_addr(ipadm_handle, aobjname, + IPADM_OPT_ACTIVE | rflags)) != IPADM_SUCCESS) { + nlog(LOG_ERR, "nwamd_down_interface: " + "ipadm_delete_addr failed on %s: %s", + ifname, ipadm_status2str(ipstatus)); } +} - if (lifnum == 0) { - struct sockaddr_in6 addr; - - (void) memset(&addr, 0, sizeof (addr)); - addr.sin6_family = family; - if (icfg_set_addr(h, (struct sockaddr *)&addr, - family == AF_INET ? sizeof (struct sockaddr_in) : - sizeof (struct sockaddr_in6)) != ICFG_SUCCESS) - nlog(LOG_ERR, "nwamd_down_interface couldn't zero " - "address on %s", h->ifh_interface.if_name); - } else { - if (icfg_get_flags(h, &flags) == ICFG_SUCCESS) { - if (icfg_set_flags(h, flags & ~IFF_UP) != ICFG_SUCCESS) - nlog(LOG_ERR, "nwamd_down_interface: couldn't " - "bring %s down", h->ifh_interface.if_name); - } else { - nlog(LOG_ERR, "nwamd_down_interface: icfg_get_flags " - "failed on %s", h->ifh_interface.if_name); - } - } +static void +unconfigure_addresses(nwamd_ncu_t *ncu, sa_family_t af) +{ + struct nwamd_if_address *nifap, *nifa = ncu->ncu_if.nwamd_if_list; - icfg_close(h); + for (nifap = nifa; nifap != NULL; nifap = nifap->next) + if (af == AF_UNSPEC || nifap->family == af) + nifap->configured = B_FALSE; } static void -nwamd_plumb_unplumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, - int af, boolean_t plumb) +dhcp_release(const char *ifname) { - uint64_t flags; - icfg_if_t intf; - icfg_handle_t h; - icfg_error_t rc; - nwamd_if_t *u_if; - const char *linkname = ncu->ncu_name; + ipadm_addr_info_t *ainfo, *ainfop; - if (linkname == NULL) { - nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: linkname null"); + if (ipadm_addr_info(ipadm_handle, ifname, &ainfo, 0, 0) + != IPADM_SUCCESS) return; + + for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) { + if (ainfop->ia_atype == IPADM_ADDR_DHCP) + nwamd_down_interface(ainfop->ia_aobjname, + ainfop->ia_atype, ifname); } + ipadm_free_addr_info(ainfo); +} - (void) nwamd_link_to_ifname(linkname, lifnum, intf.if_name, - sizeof (intf.if_name)); - intf.if_protocol = af; +static void +nwamd_plumb_unplumb_interface(nwamd_ncu_t *ncu, sa_family_t af, boolean_t plumb) +{ + char *ifname = ncu->ncu_name; + nwamd_if_t *u_if = &ncu->ncu_if; + ipadm_status_t ipstatus; - nlog(LOG_DEBUG, "nwamd_plumb_unplumb_interface: %s %s on link %s", - plumb ? "plumbing" : "unplumbing", - af == AF_INET ? "IPv4" : "IPv6", linkname); + nlog(LOG_DEBUG, "nwamd_plumb_unplumb_interface: %s %s %s", + (plumb ? "plumb" : "unplumb"), (af == AF_INET ? "IPv4" : "IPv6"), + ifname); - /* - * Before unplumbing, do a DHCP release if lifnum is 0. Otherwise - * dhcpagent can get confused. - */ - if (!plumb && af == AF_INET && lifnum == 0) - nwamd_dhcp_release(ncu->ncu_name); - - rc = icfg_open(&h, &intf); - if (rc != ICFG_SUCCESS) { - nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: " - "icfg_open failed for %s: %s", intf.if_name, - icfg_errmsg(rc)); - return; + if (plumb) { + ipstatus = ipadm_create_if(ipadm_handle, ifname, af, + IPADM_OPT_ACTIVE); + } else { + /* release DHCP address, if any */ + if (af == AF_INET) + dhcp_release(ifname); + ipstatus = ipadm_delete_if(ipadm_handle, ifname, af, + IPADM_OPT_ACTIVE); } - rc = plumb ? icfg_plumb(h) : icfg_unplumb(h); - if (rc != ICFG_SUCCESS) { - if ((plumb && rc != ICFG_EXISTS) || - (!plumb && rc != ICFG_NO_EXIST)) { + if (ipstatus != IPADM_SUCCESS) { + if ((plumb && ipstatus != IPADM_IF_EXISTS) || + (!plumb && ipstatus != IPADM_ENXIO)) { nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: " "%s %s failed for %s: %s", - plumb ? "plumb" : "unplumb", - af == AF_INET ? "IPv4" : "IPv6", - intf.if_name, icfg_errmsg(rc)); - } - } else if (plumb) { - if (icfg_get_flags(h, &flags) == ICFG_SUCCESS && - (flags & IFF_UP) == 0) { - if (icfg_set_flags(h, flags | IFF_UP) != ICFG_SUCCESS) - nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: " - "couldn't bring %s up", - h->ifh_interface.if_name); - } else { - nlog(LOG_ERR, "nwamd_plumb_unplumb_interface: " - "icfg_get_flags failed on %s", - h->ifh_interface.if_name); + (plumb ? "plumb" : "unplumb"), + (af == AF_INET ? "IPv4" : "IPv6"), + ifname, ipadm_status2str(ipstatus)); } } - u_if = &ncu->ncu_node.u_if; + /* Unset flags */ if (!plumb) { - nwamd_update_addresses_unconfigured(ncu, af); + unconfigure_addresses(ncu, af); switch (af) { - case AF_INET: - u_if->nwamd_if_dhcp_configured = B_FALSE; - break; - case AF_INET6: - u_if->nwamd_if_stateful_configured = B_FALSE; - u_if->nwamd_if_stateless_configured = B_FALSE; - break; + case AF_INET: + u_if->nwamd_if_dhcp_configured = B_FALSE; + break; + case AF_INET6: + u_if->nwamd_if_stateful_configured = B_FALSE; + u_if->nwamd_if_stateless_configured = B_FALSE; + break; } } - - icfg_close(h); } void -nwamd_plumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, int af) +nwamd_plumb_interface(nwamd_ncu_t *ncu, sa_family_t af) { /* * We get all posssible privs by calling nwamd_deescalate(). During @@ -1461,80 +1269,88 @@ nwamd_plumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, int af) * because we don't have access to /etc/security/device_policy yet. */ nwamd_escalate(); - nwamd_plumb_unplumb_interface(ncu, lifnum, af, B_TRUE); + nwamd_plumb_unplumb_interface(ncu, af, B_TRUE); nwamd_deescalate(); } void -nwamd_unplumb_interface(nwamd_ncu_t *ncu, uint_t lifnum, int af) +nwamd_unplumb_interface(nwamd_ncu_t *ncu, sa_family_t af) { - nwamd_plumb_unplumb_interface(ncu, lifnum, af, B_FALSE); + nwamd_plumb_unplumb_interface(ncu, af, B_FALSE); } static void * start_dhcp_thread(void *arg) { - struct nwamd_dhcp_thread_arg *thread_arg; - dhcp_ipc_reply_t *reply = NULL; - dhcp_ipc_request_t *request; + struct nwamd_dhcp_thread_arg *thread_arg = arg; + nwamd_object_t ncu_obj; dhcp_ipc_type_t type; - int timeout; char *name; - int rc, retries = 0; + ipadm_addrobj_t ipaddr; + ipadm_status_t ipstatus; + int retries = 0; - thread_arg = (struct nwamd_dhcp_thread_arg *)arg; - timeout = thread_arg->timeout; name = thread_arg->name; type = thread_arg->type; + ipaddr = thread_arg->ipaddr; - /* Try starting agent, though it may already be there */ - nwamd_escalate(); - rc = dhcp_start_agent(DHCP_IPC_MAX_WAIT); - nwamd_deescalate(); - if (rc == -1) { - nlog(LOG_DEBUG, "Unable to start %s", DHCP_AGENT_PATH); - goto failed; - } retry: - /* Now allocate and send the request */ - request = dhcp_ipc_alloc_request(type, name, NULL, 0, - DHCP_TYPE_NONE); - if (request == NULL) { - nlog(LOG_DEBUG, "start_dhcp: dhcp_ipc_alloc_request : %s", - strerror(errno)); - goto failed; + /* Make sure the NCU is in appropriate state for DHCP command */ + ncu_obj = nwamd_ncu_object_find(NWAM_NCU_TYPE_INTERFACE, name); + if (ncu_obj == NULL) { + nlog(LOG_ERR, "start_dhcp: no IP object %s"); + return (NULL); } - rc = dhcp_ipc_make_request(request, &reply, timeout); - free(request); - if (rc != 0) { - nlog(LOG_DEBUG, "start_dhcp %s: %s", name, - dhcp_ipc_strerror(rc)); - goto failed; + if (ncu_obj->nwamd_object_state != NWAM_STATE_OFFLINE_TO_ONLINE && + ncu_obj->nwamd_object_state != NWAM_STATE_ONLINE) { + nlog(LOG_INFO, "start_dhcp: IP NCU %s is in invalid state " + "for DHCP command", ncu_obj->nwamd_object_name); + nwamd_object_release(ncu_obj); + return (NULL); } + nwamd_object_release(ncu_obj); - rc = reply->return_code; - if (rc != 0) { - if (rc == DHCP_IPC_E_TIMEOUT && timeout == 0) { - goto failed; + switch (type) { + case DHCP_INFORM: + { + char aobjname[IPADM_AOBJSIZ]; + + if ((ipstatus = ipadm_get_aobjname(ipaddr, aobjname, + sizeof (aobjname))) != IPADM_SUCCESS) { + nlog(LOG_ERR, "start_dhcp: " + "ipadm_get_aobjname failed for %s: %s", + name, ipadm_status2str(ipstatus)); + goto done; } + ipstatus = ipadm_refresh_addr(ipadm_handle, aobjname, + IPADM_OPT_ACTIVE | IPADM_OPT_INFORM); - /* - * DHCP timed out: change state for this NCU and enqueue - * event to check NCU priority-groups. Only care for - * DHCP requests (not informs). - */ - if (rc == DHCP_IPC_E_TIMEOUT && type != DHCP_INFORM) { + break; + } + case DHCP_START: + { + ipstatus = ipadm_create_addr(ipadm_handle, ipaddr, + IPADM_OPT_ACTIVE); + + if (ipstatus == IPADM_DHCP_IPC_TIMEOUT) { + /* + * DHCP timed out: change state for this NCU and enqueue + * event to check NCU priority-groups. Only care for + * DHCP requests (not informs). + */ char *object_name; nlog(LOG_INFO, "start_dhcp: DHCP timed out for %s", name); + if (nwam_ncu_name_to_typed_name(name, NWAM_NCU_TYPE_INTERFACE, &object_name) != NWAM_SUCCESS) { nlog(LOG_ERR, "start_dhcp: " - "nwam_ncu_name_to_typed_name failed"); - goto failed; + "nwam_ncu_name_to_typed_name failed " + "for %s", name); + goto done; } nwamd_object_set_state(NWAM_OBJECT_TYPE_NCU, object_name, NWAM_STATE_OFFLINE_TO_ONLINE, @@ -1542,133 +1358,63 @@ start_dhcp_thread(void *arg) nwamd_create_ncu_check_event(0); free(object_name); - goto failed; - - } else if (rc == DHCP_IPC_E_RUNNING) { - /* - * DHCP is already running. Check if IP address is - * already configured on the interface. - */ - - icfg_handle_t h; - icfg_if_t intf; - struct sockaddr_in sin; - socklen_t alen = sizeof (struct sockaddr_in); - int plen, index; - uint64_t flags; - nwamd_event_t ip_event; - - nlog(LOG_ERR, "start_dhcp: DHCP already running on %s", - name); - - (void) strlcpy(intf.if_name, name, - sizeof (intf.if_name)); - intf.if_protocol = AF_INET; - - if (icfg_open(&h, &intf) != ICFG_SUCCESS) { - nlog(LOG_ERR, "start_dhcp: " - "icfg_open failed on %s", name); - goto failed; - } - - /* Get address */ - if (icfg_get_addr(h, (struct sockaddr *)&sin, &alen, - &plen, B_FALSE) != ICFG_SUCCESS) { - nlog(LOG_ERR, "start_dhcp: " - "icfg_get_addr failed on %s: %s", - name, strerror(errno)); - goto bail; - } - /* Check if 0.0.0.0 */ - if (sin.sin_addr.s_addr == INADDR_ANY) { - nlog(LOG_ERR, "start_dhcp: empty address on %s", - name); - goto bail; - } - - /* valid address exists, get the flags, index of intf */ - if (icfg_get_flags(h, &flags) != ICFG_SUCCESS) { - nlog(LOG_ERR, "start_dhcp: " - "icfg_get_flags failed on %s", name); - goto bail; - } - if (icfg_get_index(h, &index) != ICFG_SUCCESS) { - nlog(LOG_ERR, "start_dhcp: " - "icfg_get_index failed on %s", name); - goto bail; - } + goto done; - /* synthesize an IF_STATE event with the intf's flags */ - ip_event = nwamd_event_init_if_state(name, flags, - B_TRUE, index, (struct sockaddr *)&sin); - if (ip_event != NULL) - nwamd_event_enqueue(ip_event); -bail: - icfg_close(h); - goto failed; - - } else if ((rc == DHCP_IPC_E_SOCKET || - rc == DHCP_IPC_E_INVIF) && retries++ < NWAMD_DHCP_RETRIES) { + } else if (ipstatus == IPADM_DHCP_IPC_ERROR && + retries++ < NWAMD_DHCP_RETRIES) { /* * Retry DHCP request as we may have been unplumbing * as part of the configuration phase. */ - nlog(LOG_ERR, "start_dhcp %s: %s; will retry in %d sec", - name, dhcp_ipc_strerror(rc), - rc == DHCP_IPC_E_INVIF ? - NWAMD_DHCP_RETRY_WAIT_TIME : 0); - if (rc == DHCP_IPC_E_INVIF) - (void) sleep(NWAMD_DHCP_RETRY_WAIT_TIME); + nlog(LOG_ERR, "start_dhcp: will retry on %s in %d sec", + name, NWAMD_DHCP_RETRY_WAIT_TIME); + (void) sleep(NWAMD_DHCP_RETRY_WAIT_TIME); goto retry; - } else { - nlog(LOG_ERR, "start_dhcp %s: %s", name, - dhcp_ipc_strerror(rc)); - goto failed; } + break; } - - /* If status was the command, then output the results */ - if (DHCP_IPC_CMD(type) == DHCP_STATUS) { - nlog(LOG_DEBUG, "%s", dhcp_status_hdr_string()); - nlog(LOG_DEBUG, "%s", dhcp_status_reply_to_string(reply)); + default: + nlog(LOG_ERR, "start_dhcp: invalid dhcp_ipc_type_t: %d", type); + goto done; } -failed: - free(reply); - if (arg != NULL) { - free(name); - free(arg); + if (ipstatus != IPADM_SUCCESS) { + nlog(LOG_ERR, "start_dhcp: ipadm_%s_addr failed for %s: %s", + (type == DHCP_START ? "create" : "refresh"), + name, ipadm_status2str(ipstatus)); } + +done: + free(name); + free(arg); return (NULL); } -void -nwamd_start_dhcp(nwamd_ncu_t *ncu) +static void +nwamd_dhcp(const char *ifname, ipadm_addrobj_t ipaddr, dhcp_ipc_type_t cmd) { struct nwamd_dhcp_thread_arg *arg; - char *name = NULL; pthread_attr_t attr; - nlog(LOG_DEBUG, "nwamd_start_dhcp: starting DHCP for %s %d", - ncu->ncu_name, ncu->ncu_type); + nlog(LOG_DEBUG, "nwamd_dhcp: starting DHCP %s thread for %s", + dhcp_ipc_type_to_string(cmd), ifname); arg = malloc(sizeof (*arg)); if (arg == NULL) { - nlog(LOG_ERR, "nwamd_start_dhcp: error allocating memory " - "for dhcp request"); - free(name); + nlog(LOG_ERR, "nwamd_dhcp: error allocating memory for " + "dhcp request"); return; } - arg->name = strdup(ncu->ncu_name); - arg->type = DHCP_START; - arg->timeout = ncu_wait_time; + arg->name = strdup(ifname); + arg->type = cmd; + arg->ipaddr = ipaddr; (void) pthread_attr_init(&attr); (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (pthread_create(NULL, &attr, start_dhcp_thread, arg) == -1) { - nlog(LOG_ERR, "nwamd_start_dhcp: cannot start dhcp thread"); - free(name); + nlog(LOG_ERR, "nwamd_dhcp: cannot start dhcp thread"); + free(arg->name); free(arg); (void) pthread_attr_destroy(&attr); return; diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c index ca9a136b5a9b..d5c46a081174 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/ncu_phys.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -61,17 +60,6 @@ * Mostly WiFi code. */ -char * -nwamd_link_to_ifname(const char *linkname, int lifnum, char *ifname, int len) -{ - if (lifnum == 0) { - (void) strlcpy(ifname, linkname, len); - } else { - (void) snprintf(ifname, len, "%s:%d", linkname, lifnum); - } - return (ifname); -} - /* * Get link state from kstats. Used to determine initial link state for * cases where drivers do not support DL_NOTE_LINK_UP/DOWN. If link @@ -121,12 +109,11 @@ nwamd_get_link_state(const char *name) void nwamd_set_unset_link_properties(nwamd_ncu_t *ncu, boolean_t set) { - dlpi_handle_t dh = ncu->ncu_node.u_link.nwamd_link_dhp; - char *addr = set ? ncu->ncu_node.u_link.nwamd_link_mac_addr : NULL; - uint64_t mtu = set ? ncu->ncu_node.u_link.nwamd_link_mtu : 0; - char **autopush = set ? ncu->ncu_node.u_link.nwamd_link_autopush : NULL; - uint_t num_autopush = set ? - ncu->ncu_node.u_link.nwamd_link_num_autopush : 0; + dlpi_handle_t dh = ncu->ncu_link.nwamd_link_dhp; + char *addr = set ? ncu->ncu_link.nwamd_link_mac_addr : NULL; + uint64_t mtu = set ? ncu->ncu_link.nwamd_link_mtu : 0; + char **autopush = set ? ncu->ncu_link.nwamd_link_autopush : NULL; + uint_t num_autopush = set ? ncu->ncu_link.nwamd_link_num_autopush : 0; uchar_t *hwaddr = NULL, curraddr[DLPI_PHYSADDR_MAX]; size_t hwaddrlen = DLPI_PHYSADDR_MAX; int retval; @@ -143,8 +130,8 @@ nwamd_set_unset_link_properties(nwamd_ncu_t *ncu, boolean_t set) if (mtu == 0) { cp = mtustr; status = dladm_get_linkprop(dld_handle, - ncu->ncu_node.u_link.nwamd_link_id, DLADM_PROP_VAL_DEFAULT, - "mtu", &cp, &cnt); + ncu->ncu_link.nwamd_link_id, DLADM_PROP_VAL_DEFAULT, "mtu", + &cp, &cnt); if (status != DLADM_STATUS_OK) { nlog(LOG_ERR, "nwamd_set_unset_link_properties: " "dladm_get_linkprop failed: %s", @@ -159,9 +146,8 @@ nwamd_set_unset_link_properties(nwamd_ncu_t *ncu, boolean_t set) nlog(LOG_DEBUG, "nwamd_set_unset_link_properties: setting MTU of %s " "for link %s", mtustr, ncu->ncu_name); - status = dladm_set_linkprop(dld_handle, - ncu->ncu_node.u_link.nwamd_link_id, "mtu", &cp, 1, - DLADM_OPT_ACTIVE); + status = dladm_set_linkprop(dld_handle, ncu->ncu_link.nwamd_link_id, + "mtu", &cp, 1, DLADM_OPT_ACTIVE); if (status != DLADM_STATUS_OK) { nlog(LOG_ERR, "nwamd_set_unset_link_properties: " "dladm_set_linkprop failed: %s", @@ -170,9 +156,8 @@ nwamd_set_unset_link_properties(nwamd_ncu_t *ncu, boolean_t set) nlog(LOG_DEBUG, "nwamd_set_unset_link_properties: setting %d " "autopush module for link %s", num_autopush, ncu->ncu_name); - status = dladm_set_linkprop(dld_handle, - ncu->ncu_node.u_link.nwamd_link_id, "autopush", autopush, - num_autopush, DLADM_OPT_ACTIVE); + status = dladm_set_linkprop(dld_handle, ncu->ncu_link.nwamd_link_id, + "autopush", autopush, num_autopush, DLADM_OPT_ACTIVE); if (status != DLADM_STATUS_OK) { nlog(LOG_ERR, "nwamd_set_unset_link_properties: " "dladm_set_linkprop failed for autopush property: %s", @@ -432,7 +417,7 @@ nwamd_wlan_set_key(const char *linkname, const char *essid, const char *bssid, return (NWAM_ENTITY_NOT_FOUND); } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; nlog(LOG_DEBUG, "nwamd_wlan_set_key: running for link %s", linkname); /* @@ -629,17 +614,17 @@ wireless_selection_possible(nwamd_object_t object) { nwamd_ncu_t *ncu = object->nwamd_object_data; - if (ncu->ncu_node.u_link.nwamd_link_media != DL_WIFI) + if (ncu->ncu_link.nwamd_link_media != DL_WIFI) return (B_FALSE); (void) pthread_mutex_lock(&active_ncp_mutex); if (object->nwamd_object_state == NWAM_STATE_DISABLED || ((object->nwamd_object_state == NWAM_STATE_OFFLINE || object->nwamd_object_state == NWAM_STATE_ONLINE_TO_OFFLINE) && - ncu->ncu_node.u_link.nwamd_link_activation_mode == + ncu->ncu_link.nwamd_link_activation_mode == NWAM_ACTIVATION_MODE_PRIORITIZED && (current_ncu_priority_group == INVALID_PRIORITY_GROUP || - ncu->ncu_node.u_link.nwamd_link_priority_group > + ncu->ncu_link.nwamd_link_priority_group > current_ncu_priority_group))) { (void) pthread_mutex_unlock(&active_ncp_mutex); return (B_FALSE); @@ -659,7 +644,7 @@ void nwamd_set_selected_connected(nwamd_ncu_t *ncu, boolean_t selected, boolean_t connected) { - nwamd_link_t *link = &ncu->ncu_node.u_link; + nwamd_link_t *link = &ncu->ncu_link; nwamd_wifi_scan_t *s = &link->nwamd_link_wifi_scan; int i; boolean_t trigger_scan_event = B_FALSE; @@ -780,7 +765,7 @@ nwamd_wlan_select(const char *linkname, const char *essid, const char *bssid, return (NWAM_ENTITY_NOT_FOUND); } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; /* * If wireless selection is not possible because of the current @@ -932,7 +917,7 @@ static int find_best_wlan_cb(nwam_known_wlan_handle_t kwh, void *data) { nwamd_ncu_t *ncu = data; - nwamd_link_t *link = &ncu->ncu_node.u_link; + nwamd_link_t *link = &ncu->ncu_link; nwamd_wifi_scan_t *s = &link->nwamd_link_wifi_scan; nwam_error_t err; char *name = NULL; @@ -1163,7 +1148,7 @@ boolean_t nwamd_wlan_connected(nwamd_object_t ncu_obj) { nwamd_ncu_t *ncu = ncu_obj->nwamd_object_data; - nwamd_link_t *link = &ncu->ncu_node.u_link; + nwamd_link_t *link = &ncu->ncu_link; dladm_wlan_linkattr_t attr; char essid[DLADM_STRSIZE]; char bssid[DLADM_STRSIZE]; @@ -1274,7 +1259,7 @@ wlan_scan_thread(void *arg) } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; /* * It is possible multiple scan threads have queued up waiting for the @@ -1339,7 +1324,7 @@ wlan_scan_thread(void *arg) return (NULL); } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; /* For new scan data, add key info from known WLANs */ for (i = 0; i < s.nwamd_wifi_scan_curr_num; i++) { @@ -1522,7 +1507,7 @@ wlan_connect_thread(void *arg) } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; if (!wireless_selection_possible(ncu_obj)) { nlog(LOG_DEBUG, "wlan_connect_thread: %s in invalid state or " @@ -1623,7 +1608,7 @@ wlan_connect_thread(void *arg) } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; if (autoconf) link->nwamd_link_wifi_autoconf = B_TRUE; @@ -1719,7 +1704,7 @@ wlan_monitor_signal_thread(void *arg) break; } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; /* If the NCU is DISABLED/OFFLINE, exit the monitoring thread */ if (ncu_obj->nwamd_object_state == NWAM_STATE_OFFLINE || @@ -1810,7 +1795,7 @@ nwamd_ncu_handle_link_state_event(nwamd_event_t event) return; } ncu = ncu_obj->nwamd_object_data; - link = &ncu->ncu_node.u_link; + link = &ncu->ncu_link; evm = event->event_msg; /* diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/routing_events.c b/usr/src/cmd/cmd-inet/lib/nwamd/routing_events.c index 8a7a2910d467..12be965f6a80 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/routing_events.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/routing_events.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -38,7 +37,6 @@ #include #include -#include #include #include "events.h" #include "ncp.h" @@ -101,8 +99,6 @@ rtmtype_str(int type) return ("CHGADDR"); case RTM_FREEADDR: return ("FREEADDR"); - case RTM_IFINFO: - return ("IFINFO"); default: (void) snprintf(typestr, sizeof (typestr), "type %d", type); return (typestr); @@ -117,10 +113,9 @@ routing_events_v4(void *arg) union rtm_buf buffer; struct rt_msghdr *rtm; struct ifa_msghdr *ifa; - struct if_msghdr *ifm; char *addrs, *if_name; struct sockaddr_dl *addr_dl; - struct sockaddr *addr; + struct sockaddr *addr, *netmask; nwamd_event_t ip_event; nlog(LOG_DEBUG, "v4 routing socket %d", v4_sock); @@ -169,7 +164,6 @@ routing_events_v4(void *arg) nlog(LOG_DEBUG, "v4 routing message %s: " "index %d flags %x", rtmtype_str(rtm->rtm_type), ifa->ifam_index, ifa->ifam_flags); - printaddrs(ifa->ifam_addrs, addrs); if ((addr = (struct sockaddr *)getaddr(RTA_IFA, ifa->ifam_addrs, addrs)) == NULL) @@ -184,6 +178,10 @@ routing_events_v4(void *arg) break; } + if ((netmask = (struct sockaddr *)getaddr(RTA_NETMASK, + ifa->ifam_addrs, addrs)) == NULL) + break; + if ((addr_dl = (struct sockaddr_dl *)getaddr (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL) break; @@ -205,57 +203,17 @@ routing_events_v4(void *arg) break; } + printaddrs(ifa->ifam_addrs, addrs); + /* Create and enqueue IF_STATE event */ ip_event = nwamd_event_init_if_state(if_name, ifa->ifam_flags, (rtm->rtm_type == RTM_NEWADDR || rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE), - ifa->ifam_index, addr); - if (ip_event != NULL) - nwamd_event_enqueue(ip_event); - break; - - case RTM_IFINFO: - - ifm = (void *)rtm; - addrs = (char *)ifm + sizeof (*ifm); - nlog(LOG_DEBUG, "v4 routing message %s: " - "index %d flags %x", rtmtype_str(rtm->rtm_type), - ifm->ifm_index, ifm->ifm_flags); - printaddrs(ifm->ifm_addrs, addrs); - - if ((addr_dl = (struct sockaddr_dl *)getaddr(RTA_IFP, - ifm->ifm_addrs, addrs)) == NULL) - break; - /* - * We don't use the lladdr in this structure so we can - * run over it. - */ - addr_dl->sdl_data[addr_dl->sdl_nlen] = 0; - if_name = addr_dl->sdl_data; /* no lifnum */ - - if (ifm->ifm_index == 0) { - nlog(LOG_DEBUG, "tossing index 0 message"); - break; - } - if (ifm->ifm_type != RTM_IFINFO) { - nlog(LOG_DEBUG, - "routing_events_v4: unhandled type %d", - ifm->ifm_type); - break; - } - - /* Create and enqueue IF_STATE event */ - ip_event = nwamd_event_init_if_state(if_name, - ifm->ifm_flags, B_FALSE, ifm->ifm_index, NULL); + addr, netmask); if (ip_event != NULL) nwamd_event_enqueue(ip_event); break; - - default: - nlog(LOG_DEBUG, "v4 routing message %s discarded", - rtmtype_str(rtm->rtm_type)); - break; } } /* NOTREACHED */ @@ -270,10 +228,9 @@ routing_events_v6(void *arg) union rtm_buf buffer; struct rt_msghdr *rtm; struct ifa_msghdr *ifa; - struct if_msghdr *ifm; char *addrs, *if_name; struct sockaddr_dl *addr_dl; - struct sockaddr *addr; + struct sockaddr *addr, *netmask; nwamd_event_t ip_event; nlog(LOG_DEBUG, "v6 routing socket %d", v6_sock); @@ -323,13 +280,19 @@ routing_events_v6(void *arg) nlog(LOG_DEBUG, "v6 routing message %s: " "index %d flags %x", rtmtype_str(rtm->rtm_type), ifa->ifam_index, ifa->ifam_flags); - printaddrs(ifa->ifam_addrs, addrs); if ((addr = (struct sockaddr *)getaddr(RTA_IFA, ifa->ifam_addrs, addrs)) == NULL) break; - /* Ignore messages for link local address */ + /* Ignore routing socket messages for :: & linklocal */ + /*LINTED*/ + if (IN6_IS_ADDR_UNSPECIFIED( + &((struct sockaddr_in6 *)addr)->sin6_addr)) { + nlog(LOG_INFO, "routing_events_v6: " + "tossing message for ::"); + break; + } /*LINTED*/ if (IN6_IS_ADDR_LINKLOCAL( &((struct sockaddr_in6 *)addr)->sin6_addr)) { @@ -338,6 +301,11 @@ routing_events_v6(void *arg) break; } + if ((netmask = + (struct sockaddr *)getaddr(RTA_NETMASK, + ifa->ifam_addrs, addrs)) == NULL) + break; + if ((addr_dl = (struct sockaddr_dl *)getaddr (RTA_IFP, ifa->ifam_addrs, addrs)) == NULL) break; @@ -359,57 +327,18 @@ routing_events_v6(void *arg) break; } + printaddrs(ifa->ifam_addrs, addrs); + /* Create and enqueue IF_STATE event */ ip_event = nwamd_event_init_if_state(if_name, ifa->ifam_flags, (rtm->rtm_type == RTM_NEWADDR || rtm->rtm_type == RTM_CHGADDR ? B_TRUE : B_FALSE), - ifa->ifam_index, addr); - if (ip_event != NULL) - nwamd_event_enqueue(ip_event); - break; - - case RTM_IFINFO: - - ifm = (void *)rtm; - addrs = (char *)ifm + sizeof (*ifm); - nlog(LOG_DEBUG, "v6 routing message %s: " - "index %d flags %x", rtmtype_str(rtm->rtm_type), - ifm->ifm_index, ifm->ifm_flags); - printaddrs(ifm->ifm_addrs, addrs); - - if ((addr_dl = (struct sockaddr_dl *)getaddr(RTA_IFP, - ifm->ifm_addrs, addrs)) == NULL) - break; - /* - * We don't use the lladdr in this structure so we can - * run over it. - */ - addr_dl->sdl_data[addr_dl->sdl_nlen] = 0; - if_name = addr_dl->sdl_data; /* no lifnum */ - - if (ifm->ifm_index == 0) { - nlog(LOG_DEBUG, "tossing index 0 message"); - break; - } - if (ifm->ifm_type != RTM_IFINFO) { - nlog(LOG_DEBUG, - "routing_events_v6: unhandled type %d", - ifm->ifm_type); - break; - } - - /* Create and enqueue IF_STATE event */ - ip_event = nwamd_event_init_if_state(if_name, - ifm->ifm_flags, B_FALSE, ifm->ifm_index, NULL); + addr, netmask); if (ip_event != NULL) nwamd_event_enqueue(ip_event); break; - default: - nlog(LOG_DEBUG, "v6 routing message %s discarded", - rtmtype_str(rtm->rtm_type)); - break; } } /* NOTREACHED */ @@ -458,26 +387,18 @@ nwamd_add_route(struct sockaddr *dest, struct sockaddr *mask, struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf; void *addrs = rtbuf + sizeof (struct rt_msghdr); struct sockaddr_dl sdl; - icfg_if_t intf; - icfg_handle_t h; int rlen, index; int af; af = gateway->sa_family; - /* set interface for default route to be associated with */ - (void) strlcpy(intf.if_name, ifname, sizeof (intf.if_name)); - intf.if_protocol = af; - if (icfg_open(&h, &intf) != ICFG_SUCCESS) { - nlog(LOG_ERR, "nwamd_add_route: " - "icfg_open failed on %s", ifname); + /* retrieve the index value for the interface */ + if ((index = if_nametoindex(ifname)) == 0) { + nlog(LOG_ERR, "nwamd_add_route: if_nametoindex failed on %s", + ifname); return; } - if (icfg_get_index(h, &index) != ICFG_SUCCESS) { - nlog(LOG_ERR, "nwamd_add_route: " - "icfg_get_index failed on %s", ifname); - } - icfg_close(h); + (void) bzero(&sdl, sizeof (struct sockaddr_dl)); sdl.sdl_family = AF_LINK; sdl.sdl_index = index; diff --git a/usr/src/cmd/cmd-inet/lib/nwamd/util.c b/usr/src/cmd/cmd-inet/lib/nwamd/util.c index 8cd054138033..561031958d24 100644 --- a/usr/src/cmd/cmd-inet/lib/nwamd/util.c +++ b/usr/src/cmd/cmd-inet/lib/nwamd/util.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -35,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/usr/src/cmd/cmd-inet/usr.lib/vrrpd/Makefile b/usr/src/cmd/cmd-inet/usr.lib/vrrpd/Makefile index 4b840248a3fd..664c09c9221b 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/vrrpd/Makefile +++ b/usr/src/cmd/cmd-inet/usr.lib/vrrpd/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. # PROG= vrrpd @@ -45,7 +44,7 @@ C99MODE= $(C99_ENABLE) # via the SUS standards. Further, C99 support requires SUSv3 or higher. # CPPFLAGS += -D_XOPEN_SOURCE=600 -D__EXTENSIONS__ -LDLIBS += -lvrrpadm -lsocket -lnsl -ldladm -linetutil -lsysevent -lnvpair -lsecdb -linetcfg +LDLIBS += -lvrrpadm -lsocket -lnsl -ldladm -linetutil -lipadm -lsysevent -lnvpair -lsecdb LINTFLAGS += -erroff=E_INCONS_ARG_DECL2 -erroff=E_INCONS_ARG_USED2 # diff --git a/usr/src/cmd/cmd-inet/usr.lib/vrrpd/vrrpd.c b/usr/src/cmd/cmd-inet/usr.lib/vrrpd/vrrpd.c index f081287d0acc..223c5e4916b3 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/vrrpd/vrrpd.c +++ b/usr/src/cmd/cmd-inet/usr.lib/vrrpd/vrrpd.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -41,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -51,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +88,7 @@ typedef struct vrrpd_rtsock_s { iu_event_id_t vrt_eid; /* event ID */ } vrrpd_rtsock_t; +static ipadm_handle_t vrrp_ipadm_handle = NULL; /* libipadm handle */ static int vrrp_logflag = 0; boolean_t vrrp_debug_level = 0; iu_eh_t *vrrpd_eh = NULL; @@ -216,7 +216,7 @@ static void vrrpd_delete_ip(vrrp_intf_t *, vrrp_ip_t *); static void vrrpd_init_ipcache(int); static void vrrpd_update_ipcache(int); -static int vrrpd_walk_ipaddr(icfg_if_t *, void *); +static ipadm_status_t vrrpd_walk_addr_info(int); static vrrp_err_t vrrpd_add_ipaddr(char *, int, vrrp_addr_t *, int, uint64_t); static vrrp_ip_t *vrrpd_select_primary(vrrp_intf_t *); @@ -796,6 +796,12 @@ vrrpd_init() goto fail; } + /* Open the libipadm handle */ + if (ipadm_open(&vrrp_ipadm_handle, 0) != IPADM_SUCCESS) { + vrrp_log(VRRP_ERR, "vrrpd_init(): ipadm_open() failed"); + goto fail; + } + /* * Build the list of interfaces and IP addresses. Also, start the time * to scan the interfaces/IP addresses periodically. @@ -852,6 +858,8 @@ vrrpd_fini() vrrpd_vh = NULL; assert(TAILQ_EMPTY(&vrrp_vr_list)); assert(TAILQ_EMPTY(&vrrp_intf_list)); + + ipadm_close(vrrp_ipadm_handle); } static void @@ -1460,11 +1468,8 @@ vrrpd_scan(int af) again: vrrpd_init_ipcache(af); - /* - * If interface index changes, walk again. - */ - if (icfg_iterate_if(af, ICFG_PLUMBED, NULL, - vrrpd_walk_ipaddr) != ICFG_SUCCESS) + /* If interface index changes, walk again. */ + if (vrrpd_walk_addr_info(af) != IPADM_SUCCESS) goto again; vrrpd_update_ipcache(af); @@ -1544,86 +1549,74 @@ vrrpd_init_ipcache(int af) } /* - * Walk all the IP addresses on the given interface and update its - * addresses list. Return ICFG_FAILURE if it is required to walk + * Walk all the IP addresses of the given family and update its + * addresses list. Return IPADM_FAILURE if it is required to walk * all the interfaces again (one of the interface index changes in between). */ -/* ARGSUSED */ -static int -vrrpd_walk_ipaddr(icfg_if_t *intf, void *arg) +static ipadm_status_t +vrrpd_walk_addr_info(int af) { - icfg_handle_t ih; - int ifindex; - vrrp_addr_t addr; - socklen_t addrlen = (socklen_t)sizeof (struct sockaddr_in6); - int prefixlen; - uint64_t flags; - int err = ICFG_SUCCESS; - - vrrp_log(VRRP_DBG0, "vrrpd_walk_ipaddr(%s, %s)", intf->if_name, - af_str(intf->if_protocol)); - - if (icfg_open(&ih, intf) != ICFG_SUCCESS) { - vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s): icfg_open() " - "failed: %s", intf->if_name, af_str(intf->if_protocol), - strerror(errno)); - return (err); + ipadm_addr_info_t *ainfo, *ainfop; + ipadm_status_t ipstatus; + char *lifname; + vrrp_addr_t *addr; + int ifindex; + uint64_t flags; + + vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s)", af_str(af)); + + ipstatus = ipadm_addr_info(vrrp_ipadm_handle, NULL, &ainfo, 0, 0); + if (ipstatus != IPADM_SUCCESS) { + vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): " + "ipadm_addr_info() failed: %s", + af_str(af), ipadm_status2str(ipstatus)); + return (IPADM_SUCCESS); } - if (icfg_get_flags(ih, &flags) != ICFG_SUCCESS) { - if (errno != ENXIO && errno != ENOENT) { - vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s): " - "icfg_get_flags() failed %s", intf->if_name, - af_str(intf->if_protocol), strerror(errno)); + for (ainfop = ainfo; ainfop != NULL; ainfop = IA_NEXT(ainfop)) { + if (ainfop->ia_ifa.ifa_addr->ss_family != af) + continue; + + lifname = ainfop->ia_ifa.ifa_name; + flags = ainfop->ia_ifa.ifa_flags; + addr = (vrrp_addr_t *)ainfop->ia_ifa.ifa_addr; + + vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): %s", + af_str(af), lifname); + + /* Skip virtual/IPMP/P2P interfaces */ + if (flags & (IFF_VIRTUAL|IFF_IPMP|IFF_POINTOPOINT)) { + vrrp_log(VRRP_DBG0, "vrrpd_walk_addr_info(%s): " + "skipped %s", af_str(af), lifname); + continue; } - goto done; - } - /* - * skip virtual/IPMP/P2P interfaces. - */ - if ((flags & (IFF_VIRTUAL|IFF_IPMP|IFF_POINTOPOINT)) != 0) { - vrrp_log(VRRP_DBG0, "vrrpd_walk_ipaddr(%s, %s) skipped", - intf->if_name, af_str(intf->if_protocol)); - goto done; - } + /* Filter out the all-zero IP address */ + if (VRRPADDR_UNSPECIFIED(af, addr)) + continue; - if (icfg_get_index(ih, &ifindex) != ICFG_SUCCESS) { - if (errno != ENXIO && errno != ENOENT) { - vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s) " - "icfg_get_index() failed: %s", intf->if_name, - af_str(intf->if_protocol), strerror(errno)); + if ((ifindex = if_nametoindex(lifname)) == 0) { + if (errno != ENXIO && errno != ENOENT) { + vrrp_log(VRRP_ERR, "vrrpd_walk_addr_info(%s): " + "if_nametoindex() failed for %s: %s", + af_str(af), lifname, strerror(errno)); + } + break; } - goto done; - } - if (icfg_get_addr(ih, (struct sockaddr *)&addr, &addrlen, - &prefixlen, _B_FALSE) != ICFG_SUCCESS) { - if (errno != ENXIO && errno != ENOENT) { - vrrp_log(VRRP_ERR, "vrrpd_walk_ipaddr(%s, %s) " - "icfg_get_addr() failed: %s", intf->if_name, - af_str(intf->if_protocol), strerror(errno)); + /* + * The interface is unplumbed/replumbed during the walk. Try + * to walk the IP addresses one more time. + */ + if (vrrpd_add_ipaddr(lifname, af, addr, ifindex, flags) + == VRRP_EAGAIN) { + ipstatus = IPADM_FAILURE; + break; } - goto done; } - /* - * Filter out the all-zero IP address. - */ - if (VRRPADDR_UNSPECIFIED(intf->if_protocol, &addr)) - goto done; - - /* - * The interface is unplumbed/replumbed during we walk the IP - * addresses. Try walk the IP addresses one more time. - */ - if (vrrpd_add_ipaddr(intf->if_name, intf->if_protocol, - &addr, ifindex, flags) == VRRP_EAGAIN) - err = ICFG_FAILURE; - -done: - icfg_close(ih); - return (err); + ipadm_free_addr_info(ainfo); + return (ipstatus); } /* diff --git a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c index 597f50ac7be1..bae4b9915e13 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/ipadm/ipadm.c @@ -1264,7 +1264,7 @@ do_create_addr(int argc, char *argv[], const char *use) ipadm_status_t status; int option; uint32_t flags = - IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP; + IPADM_OPT_PERSIST|IPADM_OPT_ACTIVE|IPADM_OPT_UP|IPADM_OPT_V46; char *cp; char *atype = NULL; char *static_arg = NULL; diff --git a/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c b/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c index 49cdd983a2dd..5f348bd2bb33 100644 --- a/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c +++ b/usr/src/cmd/cmd-inet/usr.sbin/nwamadm/nwamadm.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -123,8 +124,8 @@ typedef struct profile_entry { #define STATE_WIDTH 15 /* width of STATE column */ #define AUXSTATE_WIDTH 36 /* width of AUXILIARY STATE column */ -#define EVENT_WIDTH 22 /* width of EVENT column */ -#define DESCRIPTION_WIDTH 56 /* width of DESCRIPTION column */ +#define EVENT_WIDTH 15 /* width of EVENT column */ +#define DESCRIPTION_WIDTH 64 /* width of DESCRIPTION column */ /* id for columns of "nwamadm list" */ typedef enum { @@ -1108,9 +1109,12 @@ eventhandler(nwam_event_t event) if (event->nwe_data.nwe_if_state.nwe_addr_valid) { struct sockaddr_storage *address = &(event->nwe_data.nwe_if_state.nwe_addr); + struct sockaddr_storage *netmask = + &(event->nwe_data.nwe_if_state.nwe_netmask); struct sockaddr_in *v4addr; struct sockaddr_in6 *v6addr; char addrstr[NWAM_MAX_VALUE_LEN]; + int plen = mask2plen(netmask); switch (address->ss_family) { case AF_INET: @@ -1125,14 +1129,12 @@ eventhandler(nwam_event_t event) break; } (void) snprintf(statestr, sizeof (statestr), - "index %d flags 0x%x address %s", - event->nwe_data.nwe_if_state.nwe_index, - event->nwe_data.nwe_if_state.nwe_flags, addrstr); + "flags %x addr %s/%d", + event->nwe_data.nwe_if_state.nwe_flags, + addrstr, plen); } else { (void) snprintf(statestr, sizeof (statestr), - "(%d) flags %x", - event->nwe_data.nwe_if_state.nwe_index, - event->nwe_data.nwe_if_state.nwe_flags); + "flags %x", event->nwe_data.nwe_if_state.nwe_flags); } state = statestr; break; diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index ce7b3bc7b686..9bd2a3443f95 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -108,7 +108,6 @@ SUBDIRS += \ libwanboot \ libwanbootutil \ libcryptoutil \ - libinetcfg \ libinetutil \ libipadm \ libipmp \ @@ -328,7 +327,6 @@ MSGSUBDIRS= \ libgrubmgmt \ libgss \ libidmap \ - libinetcfg \ libipmp \ libilb \ libinetutil \ @@ -413,7 +411,6 @@ HDRSUBDIRS= \ libgen \ libipadm \ libipsecutil \ - libinetcfg \ libinetsvc \ libinetutil \ libinstzones \ @@ -593,7 +590,6 @@ libefi: libuuid libfstyp: libnvpair libelfsign: libcryptoutil libkmf libidmap: libadutils libldap5 libavl libsldap -libinetcfg: libnsl libsocket libdlpi libinetutil libipadm: libnsl libinetutil libsocket libdlpi libnvpair libdhcpagent \ libdladm libsecdb libiscsit: libc libnvpair libstmf libuuid libnsl diff --git a/usr/src/lib/libinetcfg/Makefile b/usr/src/lib/libinetcfg/Makefile deleted file mode 100644 index 4d7c98746eae..000000000000 --- a/usr/src/lib/libinetcfg/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include $(SRC)/lib/Makefile.lib - -HDRS = inetcfg.h -SRCS = inetcfg.c -HDRDIR = common -SUBDIRS = $(MACH) -POFILE = libinetcfg.po -MSGFILES = common/inetcfg.c -XGETFLAGS = -a -x libinetcfg.xcl - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint - -.KEEP_STATE: - -all clean clobber install lint: $(SUBDIRS) - -install_h: $(ROOTHDRS) - -check: $(CHECKHDRS) - -$(POFILE): pofile_MSGFILES - -_msg: $(MSGDOMAINPOFILE) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include $(SRC)/Makefile.msg.targ -include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/libinetcfg/Makefile.com b/usr/src/lib/libinetcfg/Makefile.com deleted file mode 100644 index 26e4604be1fc..000000000000 --- a/usr/src/lib/libinetcfg/Makefile.com +++ /dev/null @@ -1,50 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY = libinetcfg.a -VERS = .1 -OBJECTS = inetcfg.o - -include ../../Makefile.lib - -# install this library in the root filesystem -include ../../Makefile.rootfs - -LIBS = $(DYNLIB) $(LINTLIB) - -LDLIBS += -lc -lnsl -lsocket -ldladm -ldlpi -linetutil - -SRCDIR = ../common -$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) -D_REENTRANT - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/libinetcfg/common/inetcfg.c b/usr/src/lib/libinetcfg/common/inetcfg.c deleted file mode 100644 index f61df0e28738..000000000000 --- a/usr/src/lib/libinetcfg/common/inetcfg.c +++ /dev/null @@ -1,2259 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define ICFG_SOCKADDR_LEN(protocol) \ - (protocol == AF_INET) ? \ - (socklen_t)sizeof (struct sockaddr_in) : \ - (socklen_t)sizeof (struct sockaddr_in6) - -#define ICFG_LOGICAL_SEP ':' -#define LOOPBACK_IF "lo0" -#define ARP_MOD_NAME "arp" - -/* - * Maximum amount of time (in milliseconds) to wait for Duplicate Address - * Detection to complete in the kernel. - */ -#define DAD_WAIT_TIME 5000 - -/* error codes and text descriiption */ -static struct icfg_error_info { - icfg_error_t error_code; - const char *error_desc; -} icfg_errors[] = { - { ICFG_SUCCESS, "No error occurred" }, - { ICFG_FAILURE, "Generic failure" }, - { ICFG_NO_MEMORY, "Insufficient memory" }, - { ICFG_NOT_TUNNEL, "Tunnel operation attempted on non-tunnel" }, - { ICFG_NOT_SET, "Could not return non-existent value" }, - { ICFG_BAD_ADDR, "Invalid address" }, - { ICFG_BAD_PROTOCOL, "Wrong protocol family for operation" }, - { ICFG_DAD_FAILED, "Duplicate address detection failure" }, - { ICFG_DAD_FOUND, "Duplicate address detected" }, - { ICFG_IF_UP, "Interface is up" }, - { ICFG_EXISTS, "Interface already exists" }, - { ICFG_NO_EXIST, "Interface does not exist" }, - { ICFG_INVALID_ARG, "Invalid argument" }, - { ICFG_INVALID_NAME, "Invalid name" }, - { ICFG_DLPI_INVALID_LINK, "Link does not exist" }, - { ICFG_DLPI_FAILURE, "DLPI error" }, - { ICFG_NO_PLUMB_IP, "Could not plumb IP stream" }, - { ICFG_NO_PLUMB_ARP, "Could not plumb ARP stream" }, - { ICFG_NO_UNPLUMB_IP, "Could not unplumb IP stream" }, - { ICFG_NO_UNPLUMB_ARP, "Could not unplumb ARP stream" }, - { ICFG_NO_IP_MUX, "No IP mux set" }, - { 0, NULL } -}; - -/* convert libdlpi error to libinetcfg error */ -icfg_error_t -dlpi_error_to_icfg_error(int err) -{ - switch (err) { - case DLPI_SUCCESS: - return (ICFG_SUCCESS); - case DLPI_ELINKNAMEINVAL: - return (ICFG_INVALID_NAME); - case DLPI_ENOLINK: - case DLPI_EBADLINK: - return (ICFG_DLPI_INVALID_LINK); - case DLPI_EINVAL: - case DLPI_ENOTSTYLE2: - case DLPI_EBADMSG: - case DLPI_EINHANDLE: - case DLPI_EVERNOTSUP: - case DLPI_EMODENOTSUP: - return (ICFG_INVALID_ARG); - case DL_BADADDR: - return (ICFG_BAD_ADDR); - case DL_SYSERR: - switch (errno) { - case ENOMEM: - return (ICFG_NO_MEMORY); - case EINVAL: - return (ICFG_INVALID_ARG); - } - /* FALLTHROUGH */ - case DLPI_FAILURE: - default: - return (ICFG_DLPI_FAILURE); - } -} - -/* - * Copies an an IPv4 or IPv6 address from a sockaddr_storage - * structure into the appropriate sockaddr structure for the - * address family (sockaddr_in for AF_INET or sockaddr_in6 for - * AF_INET6) and verifies that the structure size is large enough - * for the copy. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -static int -to_sockaddr(sa_family_t af, struct sockaddr *addr, - socklen_t *addrlen, const struct sockaddr_storage *ssaddr) -{ - socklen_t len; - - assert((af == AF_INET) || (af == AF_INET6)); - - len = ICFG_SOCKADDR_LEN(af); - if (*addrlen < len) { - errno = ENOSPC; - return (ICFG_FAILURE); - } - - (void) memcpy(addr, ssaddr, len); - *addrlen = len; - - return (ICFG_SUCCESS); -} - -/* - * Copies an an IPv4 or IPv6 address frrom its sockaddr structure - * into a sockaddr_storage structure and does a simple size of - * structure verification. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -static int -to_sockaddr_storage(sa_family_t af, const struct sockaddr *addr, - socklen_t addrlen, struct sockaddr_storage *ssaddr) -{ - socklen_t len; - - assert((af == AF_INET) || (af == AF_INET6)); - - len = ICFG_SOCKADDR_LEN(af); - if (addrlen < len) { - errno = EINVAL; - return (ICFG_FAILURE); - } - - (void) memcpy(ssaddr, addr, len); - - return (ICFG_SUCCESS); -} - -/* - * Return the appropriate error message for a given ICFG error. - */ -const char * -icfg_errmsg(int errcode) -{ - int i; - - for (i = 0; icfg_errors[i].error_desc != NULL; i++) { - if (errcode == icfg_errors[i].error_code) - return (dgettext(TEXT_DOMAIN, - icfg_errors[i].error_desc)); - } - - return (dgettext(TEXT_DOMAIN, "")); -} - -/* - * Opens the an interface as defined by the interface argument and returns - * a handle to the interface via the 'handle' argument. The caller is - * responsible for freeing resources allocated by this API by calling the - * icfg_close() API. - * - * Returns: ICFG_SUCCESS, ICFG_NO_MEMORY or ICFG_FAILURE. - */ -int -icfg_open(icfg_handle_t *handle, const icfg_if_t *interface) -{ - icfg_handle_t loc_handle; - int sock; - sa_family_t family; - int syserr; - - /* - * Make sure that a valid protocol family was specified. - */ - if ((interface->if_protocol != AF_INET) && - (interface->if_protocol != AF_INET6)) { - errno = EINVAL; - return (ICFG_FAILURE); - } - - family = interface->if_protocol; - - if ((loc_handle = calloc(1, sizeof (struct icfg_handle))) == NULL) { - return (ICFG_NO_MEMORY); - } - - if ((sock = socket(family, SOCK_DGRAM, 0)) < 0) { - syserr = errno; - free(loc_handle); - errno = syserr; - return (ICFG_FAILURE); - } - - loc_handle->ifh_sock = sock; - loc_handle->ifh_interface = *interface; - - *handle = loc_handle; - - return (ICFG_SUCCESS); -} - -/* - * Closes the interface opened by icfg_open() and releases all resources - * associated with the handle. - */ -void -icfg_close(icfg_handle_t handle) -{ - (void) close(handle->ifh_sock); - free(handle); -} - -/* - * Retrieves the interface name associated with the handle passed in. - */ -const char * -icfg_if_name(icfg_handle_t handle) -{ - return (handle->ifh_interface.if_name); -} - -/* - * Retrieves the protocol associated with the handle passed in. - */ -static int -icfg_if_protocol(icfg_handle_t handle) -{ - return (handle->ifh_interface.if_protocol); -} - -/* - * Any time that flags are changed on an interface where either the new or the - * existing flags have IFF_UP set, we'll get at least one RTM_IFINFO message to - * announce the flag status. Typically, there are two such messages: one - * saying that the interface is going down, and another saying that it's coming - * back up. - * - * We wait here for that second message, which can take one of two forms: - * either IFF_UP or IFF_DUPLICATE. If something's amiss with the kernel, - * though, we don't wait forever. (Note that IFF_DUPLICATE is a high-order - * bit, and we can't see it in the routing socket messages.) - */ -static int -dad_wait(icfg_handle_t handle, int rtsock) -{ - struct pollfd fds[1]; - union { - struct if_msghdr ifm; - char buf[1024]; - } msg; - int index; - int retv; - uint64_t flags; - hrtime_t starttime, now; - - fds[0].fd = rtsock; - fds[0].events = POLLIN; - fds[0].revents = 0; - - if ((retv = icfg_get_index(handle, &index)) != ICFG_SUCCESS) - return (retv); - - starttime = gethrtime(); - for (;;) { - now = gethrtime(); - now = (now - starttime) / 1000000; - if (now >= DAD_WAIT_TIME) - break; - if (poll(fds, 1, DAD_WAIT_TIME - (int)now) <= 0) - break; - if (read(rtsock, &msg, sizeof (msg)) <= 0) - break; - if (msg.ifm.ifm_type != RTM_IFINFO) - continue; - /* Note that ifm_index is just 16 bits */ - if (index == msg.ifm.ifm_index && (msg.ifm.ifm_flags & IFF_UP)) - return (ICFG_SUCCESS); - if ((retv = icfg_get_flags(handle, &flags)) != ICFG_SUCCESS) - return (retv); - if (flags & IFF_DUPLICATE) - return (ICFG_DAD_FOUND); - } - return (ICFG_DAD_FAILED); -} - -/* - * Sets the flags for the interface represented by the 'handle' - * argument to the value contained in the 'flags' argument. - * - * If the new flags value will transition the interface from "down" to "up," - * then duplicate address detection is performed by the kernel. This routine - * waits to get the outcome of that test. - * - * Returns: ICFG_SUCCESS, ICFG_DAD_FOUND, ICFG_DAD_FAILED or ICFG_FAILURE. - */ -int -icfg_set_flags(icfg_handle_t handle, uint64_t flags) -{ - struct lifreq lifr; - uint64_t oflags; - int ret; - int rtsock = -1; - int aware = RTAW_UNDER_IPMP; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if ((ret = icfg_get_flags(handle, &oflags)) != ICFG_SUCCESS) - return (ret); - if (oflags == flags) - return (ICFG_SUCCESS); - - /* - * Any time flags are changed on an interface that has IFF_UP set, - * you'll get a routing socket message. We care about the status, - * though, only when the new flags are marked "up." Since we may be - * changing an IPMP test address, we enable RTAW_UNDER_IPMP. - */ - if (flags & IFF_UP) { - rtsock = socket(PF_ROUTE, SOCK_RAW, icfg_if_protocol(handle)); - if (rtsock != -1) { - (void) setsockopt(rtsock, SOL_ROUTE, RT_AWARE, &aware, - sizeof (aware)); - } - } - - lifr.lifr_flags = flags; - if (ioctl(handle->ifh_sock, SIOCSLIFFLAGS, (caddr_t)&lifr) < 0) { - if (rtsock != -1) - (void) close(rtsock); - return (ICFG_FAILURE); - } - - if (rtsock == -1) { - return (ICFG_SUCCESS); - } else { - ret = dad_wait(handle, rtsock); - (void) close(rtsock); - return (ret); - } -} - -/* - * Sets the metric value for the interface represented by the - * 'handle' argument to the value contained in the 'metric' - * argument. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_set_metric(icfg_handle_t handle, int metric) -{ - struct lifreq lifr; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - lifr.lifr_metric = metric; - - if (ioctl(handle->ifh_sock, SIOCSLIFMETRIC, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the mtu value for the interface represented by the - * 'handle' argument to the value contained in the 'mtu' - * argument. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_set_mtu(icfg_handle_t handle, uint_t mtu) -{ - struct lifreq lifr; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - lifr.lifr_mtu = mtu; - - if (ioctl(handle->ifh_sock, SIOCSLIFMTU, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the index value for the interface represented by the - * 'handle' argument to the value contained in the 'index' - * argument. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_set_index(icfg_handle_t handle, int index) -{ - struct lifreq lifr; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - lifr.lifr_index = index; - - if (ioctl(handle->ifh_sock, SIOCSLIFINDEX, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the netmask address for the interface represented by - * 'handle'. - * - * The handle must represent an IPv4 interface. - * - * The address will be set to the value pointed to by 'addr'. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE. - */ -int -icfg_set_netmask(icfg_handle_t handle, const struct sockaddr_in *addr) -{ - struct lifreq lifr; - int ret; - - if (icfg_if_protocol(handle) != AF_INET) { - return (ICFG_BAD_PROTOCOL); - } - - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), - (struct sockaddr *)addr, sizeof (*addr), - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = AF_INET; - - if (ioctl(handle->ifh_sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the broadcast address for the interface represented by - * 'handle'. - * - * The handle must represent an IPv4 interface. - * - * The address will be set to the value pointed to by 'addr'. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE. - */ -int -icfg_set_broadcast(icfg_handle_t handle, const struct sockaddr_in *addr) -{ - struct lifreq lifr; - int ret; - - if (icfg_if_protocol(handle) != AF_INET) { - return (ICFG_BAD_PROTOCOL); - } - - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), - (struct sockaddr *)addr, sizeof (*addr), - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = AF_INET; - - if (ioctl(handle->ifh_sock, SIOCSLIFBRDADDR, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the prefixlen value for the interface represented by the handle - * argument to the value contained in the 'prefixlen' argument. The - * prefixlen is actually stored internally as a netmask value and the API - * will convert the value contained in 'prefixlen' into the correct netmask - * value according to the protocol family of the interface. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_set_prefixlen(icfg_handle_t handle, int prefixlen) -{ - struct lifreq lifr; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - - if (plen2mask(prefixlen, icfg_if_protocol(handle), - &lifr.lifr_addr) != 0) { - return (ICFG_FAILURE); - } - - if (ioctl(handle->ifh_sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) - return (ICFG_FAILURE); - - return (ICFG_SUCCESS); -} - -/* - * Sets the address for the interface represented by 'handle'. - * - * The 'addr' argument points to either a sockaddr_in structure - * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds - * the IP address. The 'addrlen' argument gives the length of the - * 'addr' structure. - * - * If the interface is an IPv6 interface and the interface is - * already in the "up" state, then duplicate address detection - * is performed before the address is set and is set only if no - * duplicate address is detected. - * - * Returns: ICFG_SUCCESS, ICFG_FAILURE, ICFG_DAD_FOUND, ICFG_DAD_FAILED - * or ICFG_FAILURE. - */ -int -icfg_set_addr(icfg_handle_t handle, const struct sockaddr *addr, - socklen_t addrlen) -{ - struct lifreq lifr; - uint64_t flags; - int ret; - int rtsock = -1; - int aware = RTAW_UNDER_IPMP; - - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), addr, addrlen, - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - - /* - * Need to check duplicate address detection results if the address is - * up. Since this may be an IPMP test address, enable RTAW_UNDER_IPMP. - */ - if ((ret = icfg_get_flags(handle, &flags)) != ICFG_SUCCESS) - return (ret); - - if (flags & IFF_UP) { - rtsock = socket(PF_ROUTE, SOCK_RAW, icfg_if_protocol(handle)); - if (rtsock != -1) { - (void) setsockopt(rtsock, SOL_ROUTE, RT_AWARE, &aware, - sizeof (aware)); - } - } - - (void) strlcpy(lifr.lifr_name, handle->ifh_interface.if_name, - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) { - if (rtsock != -1) - (void) close(rtsock); - return (ICFG_FAILURE); - } - - if (rtsock == -1) { - return (ICFG_SUCCESS); - } else { - ret = dad_wait(handle, rtsock); - (void) close(rtsock); - return (ret); - } -} - -/* - * Sets the token for the interface represented by 'handle'. - * - * The handle must represent an IPv6 interface. - * - * The token will be set to the value contained in 'addr' and - * its associated prefixlen will be set to 'prefixlen'. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE. - */ -int -icfg_set_token(icfg_handle_t handle, const struct sockaddr_in6 *addr, - int prefixlen) -{ - struct lifreq lifr; - int ret; - - if (icfg_if_protocol(handle) != AF_INET6) { - return (ICFG_BAD_PROTOCOL); - } - - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), - (struct sockaddr *)addr, sizeof (*addr), - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - lifr.lifr_addrlen = prefixlen; - - if (ioctl(handle->ifh_sock, SIOCSLIFTOKEN, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the subnet address for the interface represented by 'handle'. - * - * The 'addr' argument points to either a sockaddr_in structure - * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds - * the IP address. The 'addrlen' argument gives the length of the - * 'addr' structure. - * - * The prefixlen of the subnet address will be set to 'prefixlen'. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_set_subnet(icfg_handle_t handle, const struct sockaddr *addr, - socklen_t addrlen, int prefixlen) -{ - struct lifreq lifr; - int ret; - - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), addr, addrlen, - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - lifr.lifr_addrlen = prefixlen; - - if (ioctl(handle->ifh_sock, SIOCSLIFSUBNET, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Sets the destination address for the interface represented by - * 'handle'. - * - * The 'addr' argument points to either a sockaddr_in structure - * (for IPv4) or a sockaddr_in6 structure (for IPv6) that holds - * the IP address. The 'addrlen' argument gives the length of the - * 'addr' structure. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_set_dest_addr(icfg_handle_t handle, const struct sockaddr *addr, - socklen_t addrlen) -{ - struct lifreq lifr; - int ret; - - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if ((ret = to_sockaddr_storage(icfg_if_protocol(handle), addr, addrlen, - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - - if (ioctl(handle->ifh_sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - return (ICFG_SUCCESS); -} - -/* - * Returns the address and prefixlen of the interface represented - * by 'handle'. - * - * The 'addr' argument is a result parameter that is filled in with - * the requested address. The format of the 'addr' parameter is - * determined by the address family of the interface. - * - * The 'addrlen' argument is a value-result parameter. Initially, it - * contains the amount of space pointed to by 'addr'; on return it - * contains the length in bytes of the address returned. - * - * Note that if 'addrlen' is not large enough for the returned address - * value, then ICFG_FAILURE will be returned and errno will be set to ENOSPC. - * - * If the 'force' argument is set to B_TRUE, then non-critical errors in - * obtaining the address will be ignored and the address will be set to - * all 0's. Non-critical errors consist of EADDRNOTAVAIL, EAFNOSUPPORT, - * and ENXIO. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_get_addr(icfg_handle_t handle, struct sockaddr *addr, socklen_t *addrlen, - int *prefixlen, boolean_t force) -{ - struct lifreq lifr; - int ret; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFADDR, (caddr_t)&lifr) < 0) { - if (force && ((errno == EADDRNOTAVAIL) || - (errno == EAFNOSUPPORT) || (errno == ENXIO))) { - (void) memset(&lifr.lifr_addr, 0, - sizeof (lifr.lifr_addr)); - } else { - return (ICFG_FAILURE); - } - } - - if ((ret = to_sockaddr(icfg_if_protocol(handle), addr, addrlen, - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - *prefixlen = lifr.lifr_addrlen; - - return (ICFG_SUCCESS); -} - -/* - * Returns the token address and the token prefixlen of the - * interface represented by 'handle'. - * - * The 'addr' argument is a result parameter that is filled in - * with the requested address. - * - * The 'prefixlen' argument is a result paramter that is filled - * in with the token prefixlen. - * - * If the 'force' argument is set to B_TRUE, then non-critical errors in - * obtaining the token address will be ignored and the address will be set - * to all 0's. Non-critical errors consist of EADDRNOTAVAIL and EINVAL. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE. - */ -int -icfg_get_token(icfg_handle_t handle, struct sockaddr_in6 *addr, - int *prefixlen, boolean_t force) -{ - struct lifreq lifr; - socklen_t addrlen = sizeof (*addr); - - if (icfg_if_protocol(handle) != AF_INET6) { - return (ICFG_BAD_PROTOCOL); - } - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFTOKEN, (caddr_t)&lifr) < 0) { - if (force && ((errno == EADDRNOTAVAIL) || (errno == EINVAL))) { - (void) memset(&lifr.lifr_addr, 0, - sizeof (lifr.lifr_addr)); - } else { - return (ICFG_FAILURE); - } - } - - *prefixlen = lifr.lifr_addrlen; - return (to_sockaddr(icfg_if_protocol(handle), (struct sockaddr *)addr, - &addrlen, &lifr.lifr_addr)); -} - -/* - * Returns the subnet address and the subnet prefixlen of the interface - * represented by 'handle'. - * - * The 'addr' argument is a result parameter that is filled in with - * the requested address. The format of the 'addr' parameter is - * determined by the address family of the interface. - * - * The 'addrlen' argument is a value-result parameter. Initially, it - * contains the amount of space pointed to by 'addr'; on return it - * contains the length in bytes of the address returned. - * - * Note that if 'addrlen' is not large enough for the returned address - * value, then ICFG_FAILURE will be returned and errno will be set to ENOSPC. - * - * If the 'force' argument is set to B_TRUE, then non-critical errors in - * obtaining the address will be ignored and the address will be set to all - * 0's. Non-critical errors consist of EADDRNOTAVAIL, EAFNOSUPPORT,and ENXIO. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_get_subnet(icfg_handle_t handle, struct sockaddr *addr, - socklen_t *addrlen, int *prefixlen, boolean_t force) -{ - struct lifreq lifr; - int ret; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFSUBNET, (caddr_t)&lifr) < 0) { - if (force && ((errno == EADDRNOTAVAIL) || - (errno == EAFNOSUPPORT) || (errno == ENXIO))) { - (void) memset(&lifr.lifr_addr, 0, - sizeof (lifr.lifr_addr)); - } else { - return (ICFG_FAILURE); - } - } - - if ((ret = to_sockaddr(icfg_if_protocol(handle), addr, addrlen, - &lifr.lifr_addr)) != ICFG_SUCCESS) { - return (ret); - } - *prefixlen = lifr.lifr_addrlen; - - return (ICFG_SUCCESS); -} - -/* - * Returns the netmask address of the interface represented by 'handle'. - * - * The handle must represent an IPv4 interface. - * - * The 'addr' argument is a result parameter that is filled in with - * the requested address. - * - * If no netmask address has been set for the interface, an address of - * all 0's will be returned. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE. - */ -int -icfg_get_netmask(icfg_handle_t handle, struct sockaddr_in *addr) -{ - struct lifreq lifr; - socklen_t addrlen = sizeof (*addr); - - if (icfg_if_protocol(handle) != AF_INET) { - return (ICFG_BAD_PROTOCOL); - } - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0) { - if (errno != EADDRNOTAVAIL) { - return (ICFG_FAILURE); - } - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - } - - return (to_sockaddr(icfg_if_protocol(handle), (struct sockaddr *)addr, - &addrlen, &lifr.lifr_addr)); -} - -/* - * Returns the broadcast address of the interface represented by 'handle'. - * - * The handle must represent an IPv4 interface. - * - * The 'addr' argument is a result parameter that is filled in with - * the requested address. - * - * If no broadcast address has been set for the interface, an address - * of all 0's will be returned. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL or ICFG_FAILURE. - */ -int -icfg_get_broadcast(icfg_handle_t handle, struct sockaddr_in *addr) -{ - struct lifreq lifr; - socklen_t addrlen = sizeof (*addr); - - if (icfg_if_protocol(handle) != AF_INET) { - return (ICFG_BAD_PROTOCOL); - } - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFBRDADDR, (caddr_t)&lifr) < 0) { - if (errno != EADDRNOTAVAIL) { - return (ICFG_FAILURE); - } - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - } - - return (to_sockaddr(icfg_if_protocol(handle), (struct sockaddr *)addr, - &addrlen, &lifr.lifr_addr)); -} - -/* - * Returns the destination address of the interface represented - * by 'handle'. - * - * The 'addr' argument is a result parameter that is filled in with - * the requested address. The format of the 'addr' parameter is - * determined by the address family of the interface. - * - * The 'addrlen' argument is a value-result parameter. Initially, it - * contains the amount of space pointed to by 'addr'; on return it - * contains the length in bytes of the address returned. - * - * Note that if 'addrlen' is not large enough for the returned address - * value, then ICFG_FAILURE will be returned and errno will be set to - * ENOSPC. - * - * If no destination address has been set for the interface, an address - * of all 0's will be returned. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_get_dest_addr(icfg_handle_t handle, struct sockaddr *addr, - socklen_t *addrlen) -{ - struct lifreq lifr; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFDSTADDR, (caddr_t)&lifr) < 0) { - if (errno != EADDRNOTAVAIL) { - return (ICFG_FAILURE); - } - /* No destination address set yet */ - (void) memset(&lifr.lifr_dstaddr, 0, - sizeof (lifr.lifr_dstaddr)); - } - - return (to_sockaddr(icfg_if_protocol(handle), addr, addrlen, - &lifr.lifr_addr)); -} - -/* - * Returns the groupname, if any, of the interface represented by the handle - * argument into the buffer pointed to by the 'groupname' argument. The size - * of the groupname buffer is expected to be of 'len' bytes in length and - * should be large enough to receive the groupname of the interface - * (i.e., LIFNAMSIZ). - * - * Returns: ICFG_SUCCESS, ICFG_NOT_SET or ICFG_FAILURE. - */ -int -icfg_get_groupname(icfg_handle_t handle, char *groupname, size_t len) -{ - struct lifreq lifr; - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - (void) memset(lifr.lifr_groupname, 0, sizeof (lifr.lifr_groupname)); - - if (ioctl(handle->ifh_sock, SIOCGLIFGROUPNAME, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - - if (strlen(lifr.lifr_groupname) > 0) { - (void) strlcpy(groupname, lifr.lifr_groupname, len); - } else { - return (ICFG_NOT_SET); - } - - return (ICFG_SUCCESS); -} - -/* - * Returns the groupinfo, if any, associated with the group identified in - * the gi_grname field of the passed-in lifgr structure. Upon successful - * return, the lifgr structure will be populated with the associated - * group info. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -static int -icfg_get_groupinfo(icfg_handle_t handle, lifgroupinfo_t *lifgr) -{ - if (ioctl(handle->ifh_sock, SIOCGLIFGROUPINFO, lifgr) < 0) - return (ICFG_FAILURE); - - return (ICFG_SUCCESS); -} - -/* - * Returns the flags value of the interface represented by the handle - * argument into the buffer pointed to by the 'flags' argument. - * - * Returns: ICFG_SUCCESS, ICFG_NO_EXIST or ICFG_FAILURE. - */ -int -icfg_get_flags(icfg_handle_t handle, uint64_t *flags) -{ - struct lifreq lifr; - - if (flags == NULL) - return (ICFG_INVALID_ARG); - - (void) memset(&lifr, 0, sizeof (lifr)); - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) { - if (errno == ENXIO) - return (ICFG_NO_EXIST); - else - return (ICFG_FAILURE); - } - *flags = lifr.lifr_flags; - - return (ICFG_SUCCESS); -} - -/* - * Returns the metric value of the interface represented by the handle - * argument into the buffer pointed to by the 'metric' argument. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_get_metric(icfg_handle_t handle, int *metric) -{ - struct lifreq lifr; - - if (metric == NULL) - return (ICFG_INVALID_ARG); - - (void) memset(&lifr, 0, sizeof (lifr)); - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFMETRIC, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - *metric = lifr.lifr_metric; - - return (ICFG_SUCCESS); -} - -/* - * Returns the mtu value of the interface represented by the handle - * argument into the buffer pointed to by the 'mtu' argument. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_get_mtu(icfg_handle_t handle, uint_t *mtu) -{ - struct lifreq lifr; - - if (mtu == NULL) - return (ICFG_INVALID_ARG); - - (void) memset(&lifr, 0, sizeof (lifr)); - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFMTU, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - *mtu = lifr.lifr_mtu; - - return (ICFG_SUCCESS); -} - -/* - * Returns the index value of the interface represented by the handle - * argument into the buffer pointed to by the 'index' argument. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_get_index(icfg_handle_t handle, int *index) -{ - struct lifreq lifr; - - if (index == NULL) - return (ICFG_INVALID_ARG); - - (void) memset(&lifr, 0, sizeof (lifr)); - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - lifr.lifr_addr.ss_family = icfg_if_protocol(handle); - - if (ioctl(handle->ifh_sock, SIOCGLIFINDEX, (caddr_t)&lifr) < 0) { - return (ICFG_FAILURE); - } - *index = lifr.lifr_index; - - return (ICFG_SUCCESS); -} - -/* - * Walks a list of interfaces and for each interface found, the - * caller-supplied function 'callback()' is invoked. The iteration will be - * interrupted if the caller-supplied function does not return ICFG_SUCCESS. - * - * The 'proto' argument is used by the caller to define which interfaces are - * to be walked by the API. The possible values for 'proto' are AF_INET, - * AF_INET6, and AF_UNSPEC. - * - * The 'arg' argument is a pointer to caller-specific data. - * - * Returns: ICFG_SUCCESS, ICFG_FAILURE or error code returned by callback(). - */ -int -icfg_iterate_if(int proto, int type, void *arg, - int (*callback)(icfg_if_t *interface, void *arg)) -{ - icfg_if_t *if_ids; - int len; - int i; - int ret; - - ret = icfg_get_if_list(&if_ids, &len, proto, type); - if (ret != ICFG_SUCCESS) { - return (ret); - } - - for (i = 0; i < len; i++) { - if ((ret = callback(&if_ids[i], arg)) != ICFG_SUCCESS) { - break; - } - } - - icfg_free_if_list(if_ids); - - return (ret); - -} - -/* - * Returns a list of currently plumbed interfaces. The list of interfaces is - * returned as an array of icfg_if_t structures. The number of interfaces in - * the array will be returned via the 'numif' argument. Since the array of - * interfaces is allocated by this API, the caller is responsible for freeing - * the memory associated with this array by calling icfg_free_if_list(). - * - * The 'proto' argument is used by the caller to define which interfaces are - * to be listed by the API. The possible values for proto are AF_INET, - * AF_INET6, and AF_UNSPEC. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_PROTOCOL, ICFG_NO_MEMORY or ICFG_FAILURE. - */ -static int -get_plumbed_if_list(icfg_if_t **list, int *numif, int proto) { - int sock; - struct lifconf lifc; - struct lifnum lifn; - struct lifreq *lifrp; - char *buf; - unsigned bufsize; - icfg_if_t *loc_list; - int num; - sa_family_t lifc_family; - int lifc_flags = LIFC_NOXMIT; - int syserr; - int i; - - /* - * Validate the protocol family. - */ - if ((proto != AF_UNSPEC) && - (proto != AF_INET) && - (proto != AF_INET6)) { - errno = EINVAL; - return (ICFG_BAD_PROTOCOL); - } - lifc_family = proto; - - /* - * Open a socket. Note that the AF_INET domain seems to - * support both IPv4 and IPv6. - */ - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - return (ICFG_FAILURE); - } - - /* - * Get the number of interfaces and allocate a buffer - * large enough to allow the interfaces to be enumerated. - */ - lifn.lifn_family = lifc_family; - lifn.lifn_flags = lifc_flags; - if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { - syserr = errno; - (void) close(sock); - errno = syserr; - return (ICFG_FAILURE); - } - num = lifn.lifn_count; - bufsize = num * sizeof (struct lifreq); - buf = malloc(bufsize); - if (buf == NULL) { - syserr = errno; - (void) close(sock); - errno = syserr; - return (ICFG_NO_MEMORY); - } - - /* - * Obtain a list of the interfaces. - */ - lifc.lifc_family = lifc_family; - lifc.lifc_flags = lifc_flags; - lifc.lifc_len = bufsize; - lifc.lifc_buf = buf; - if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) { - syserr = errno; - (void) close(sock); - free(buf); - errno = syserr; - return (ICFG_FAILURE); - } - (void) close(sock); - - bufsize = num * sizeof (icfg_if_t); - loc_list = malloc(bufsize); - if (loc_list == NULL) { - syserr = errno; - free(buf); - errno = syserr; - return (ICFG_NO_MEMORY); - } - - lifrp = lifc.lifc_req; - for (i = 0; i < num; i++, lifrp++) { - (void) strlcpy(loc_list[i].if_name, lifrp->lifr_name, - sizeof (loc_list[i].if_name)); - if (lifrp->lifr_addr.ss_family == AF_INET) { - loc_list[i].if_protocol = AF_INET; - } else { - loc_list[i].if_protocol = AF_INET6; - } - } - - *list = loc_list; - *numif = num; - - free(buf); - - return (ICFG_SUCCESS); -} - -typedef struct linklist { - struct linklist *ll_next; - char ll_name[DLPI_LINKNAME_MAX]; -} linklist_t; - -typedef struct linkwalk { - linklist_t *lw_list; - int lw_num; - int lw_err; -} linkwalk_t; - -static boolean_t -add_link_list(const char *link, void *arg) -{ - linkwalk_t *lwp = (linkwalk_t *)arg; - linklist_t *entry = NULL; - - if ((entry = calloc(1, sizeof (linklist_t))) == NULL) { - lwp->lw_err = ENOMEM; - return (B_TRUE); - } - (void) strlcpy(entry->ll_name, link, DLPI_LINKNAME_MAX); - - if (lwp->lw_list == NULL) - lwp->lw_list = entry; - else - lwp->lw_list->ll_next = entry; - - lwp->lw_num++; - return (B_FALSE); -} - -/* - * Returns a list of data links that can be plumbed. The list of interfaces is - * returned as an array of icfg_if_t structures. The number of interfaces in - * the array will be returned via the 'numif' argument. - * - * Returns: ICFG_SUCCESS, ICFG_NO_MEMORY or ICFG_FAILURE. - */ -static int -get_link_list(icfg_if_t **listp, int *numif) { - - linkwalk_t lw = {NULL, 0, 0}; - linklist_t *entry, *next; - icfg_if_t *list; - int save_errno = 0; - int ret = ICFG_FAILURE; - - dlpi_walk(add_link_list, &lw, 0); - if (lw.lw_err != 0) { - errno = lw.lw_err; - goto done; - } - if (lw.lw_num == 0) { - /* no links found, nothing else to do */ - *listp = NULL; - *numif = 0; - return (ICFG_SUCCESS); - } - - list = calloc(lw.lw_num, sizeof (icfg_if_t)); - if (list == NULL) { - ret = ICFG_NO_MEMORY; - goto done; - } - - *listp = list; - for (entry = lw.lw_list; entry != NULL; entry = entry->ll_next) { - (void) strlcpy(list->if_name, entry->ll_name, - sizeof (list->if_name)); - list->if_protocol = AF_UNSPEC; - list++; - } - *numif = lw.lw_num; - ret = ICFG_SUCCESS; - -done: - save_errno = errno; - for (entry = lw.lw_list; entry != NULL; entry = next) { - next = entry->ll_next; - free(entry); - } - errno = save_errno; - return (ret); -} - -/* - * Returns a list of network interfaces. The list of - * interfaces is returned as an array of icfg_if_t structures. - * The number of interfaces in the array will be returned via - * the 'numif' argument. Since the array of interfaces is - * allocated by this API, the caller is responsible for freeing - * the memory associated with this array by calling - * icfg_free_if_list(). - * - * The 'proto' argument is used by the caller to define which - * interfaces are to be listed by the API. The possible values - * for 'proto' are AF_INET, AF_INET6, and AF_UNSPEC. - * - * The 'type' argument is used by the caller specify whether - * to enumerate installed network interfaces or plumbed - * network interfaces. The value for 'type' can be ICFG_PLUMBED - * or ICFG_INSTALLED. - */ -int -icfg_get_if_list(icfg_if_t **list, int *numif, int proto, int type) -{ - if (list == NULL || numif == NULL) - return (ICFG_INVALID_ARG); - - *list = NULL; - *numif = 0; - - if (type == ICFG_PLUMBED) { - return (get_plumbed_if_list(list, numif, proto)); - } else if (type == ICFG_INSTALLED) { - return (get_link_list(list, numif)); - } else { - errno = EINVAL; - return (ICFG_FAILURE); - } -} - -/* - * Frees the memory allocated by icfg_get_list(). - */ -void -icfg_free_if_list(icfg_if_t *list) -{ - free(list); - list = NULL; -} - -/* - * Determines whether or not an interface name represents - * a logical interface or not. - * - * Returns: B_TRUE if logical, B_FALSE if not. - * - * Note: this API can be vastly improved once interface naming - * is resolved in the future. This will do for now. - */ -boolean_t -icfg_is_logical(icfg_handle_t handle) -{ - return (strchr(icfg_if_name(handle), ICFG_LOGICAL_SEP) - != NULL); -} - -/* - * Determines whether or not an interface name represents a loopback - * interface or not. - * - * Returns: B_TRUE if loopback, B_FALSE if not. - */ -static boolean_t -icfg_is_loopback(icfg_handle_t handle) -{ - return (strcmp(icfg_if_name(handle), LOOPBACK_IF) == 0); -} - -/* - * Given a sockaddr representation of an IPv4 or IPv6 address returns the - * string representation. Note that 'sockaddr' should point at the correct - * sockaddr structure for the address family (sockaddr_in for AF_INET or - * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage - * structure. - * - * Returns: ICFG_SUCCESS or ICFG_FAILURE. - */ -int -icfg_sockaddr_to_str(sa_family_t af, const struct sockaddr *sockaddr, - char *straddr, size_t len) -{ - const void *addr = sockaddr; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - const char *str; - int ret = ICFG_FAILURE; - - if (af == AF_INET) { - sin = (struct sockaddr_in *)addr; - str = inet_ntop(AF_INET, (void *)&sin->sin_addr, straddr, len); - } else if (af == AF_INET6) { - sin6 = (struct sockaddr_in6 *)addr; - str = inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, straddr, - len); - } else { - errno = EINVAL; - return (ICFG_FAILURE); - } - - if (str != NULL) { - ret = ICFG_SUCCESS; - } - - return (ret); -} - -/* - * Given a string representation of an IPv4 or IPv6 address returns the - * sockaddr representation. Note that 'sockaddr' should point at the correct - * sockaddr structure for the address family (sockaddr_in for AF_INET or - * sockaddr_in6 for AF_INET6) or alternatively at a sockaddr_storage - * structure. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_ADDR or ICFG_FAILURE. - */ -int -icfg_str_to_sockaddr(sa_family_t af, const char *straddr, - struct sockaddr *sockaddr, socklen_t *addrlen) -{ - void *addr = sockaddr; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - int ret; - int err; - - if (af == AF_INET) { - if (*addrlen < sizeof (*sin)) { - errno = ENOSPC; - return (ICFG_FAILURE); - } - *addrlen = sizeof (*sin); - sin = (struct sockaddr_in *)addr; - sin->sin_family = AF_INET; - err = inet_pton(AF_INET, straddr, &sin->sin_addr); - } else if (af == AF_INET6) { - if (*addrlen < sizeof (*sin6)) { - errno = ENOSPC; - return (ICFG_FAILURE); - } - *addrlen = sizeof (*sin6); - sin6 = (struct sockaddr_in6 *)addr; - sin6->sin6_family = AF_INET6; - err = inet_pton(AF_INET6, straddr, &sin6->sin6_addr); - } else { - errno = EINVAL; - return (ICFG_FAILURE); - } - - if (err == 0) { - ret = ICFG_BAD_ADDR; - } else if (err == 1) { - ret = ICFG_SUCCESS; - } else { - ret = ICFG_FAILURE; - } - - return (ret); -} - -/* - * Adds the IP address contained in the 'addr' argument to the physical - * interface represented by the handle passed in. At present, - * additional IP addresses assigned to a physical interface are - * represented as logical interfaces. - * - * If the 'handle' argument is a handle to a physical interface, a logical - * interface will be created, named by the next unused logical unit number - * for that physical interface. - * - * If the 'handle' argument is a handle to an logical interface, then that - * logical interface is the one that will be created. If the logical - * interface model is abandoned in the future, passing in a logical - * interface name should result in ICFG_UNSUPPORTED being returned. - * - * If the 'new_handle' argument is not NULL, then a handle is created for the - * new IP address alias and returned to the caller via 'new_handle'. - * At present this handle refers to a logical interface, but in the future - * it may represent an IP address alias, and be used for setting/retrieving - * address-related information only. - * - * - * Returns: ICFG_SUCCESS, ICFG_BAD_ADDR, ICFG_DAD_FOUND, ICFG_EXISTS - * or ICFG_FAILURE. - */ -int -icfg_add_addr(icfg_handle_t handle, icfg_handle_t *new_handle, - const struct sockaddr *addr, socklen_t addrlen) -{ - struct lifreq lifr; - size_t addrsize; - int ret = ICFG_SUCCESS; - icfg_handle_t loc_handle; - - if (addr->sa_family != icfg_if_protocol(handle)) - return (ICFG_BAD_ADDR); - - switch (addr->sa_family) { - case AF_INET: - addrsize = sizeof (struct sockaddr_in); - break; - case AF_INET6: - addrsize = sizeof (struct sockaddr_in6); - break; - default: - return (ICFG_BAD_ADDR); - } - - if (addrlen < addrsize) { - errno = ENOSPC; - return (ICFG_FAILURE); - } - - /* - * See comments in ifconfig.c as to why this dance is necessary. - */ - (void) memset(&lifr, 0, sizeof (lifr)); - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - - if (ioctl(handle->ifh_sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0) { - if (errno == EEXIST) - return (ICFG_EXISTS); - else - return (ICFG_FAILURE); - } - - /* Create the handle for the new interface name. */ - ret = icfg_open(&loc_handle, &(handle->ifh_interface)); - if (ret != ICFG_SUCCESS) { - return (ret); - } - (void) strlcpy(loc_handle->ifh_interface.if_name, - lifr.lifr_name, - sizeof (loc_handle->ifh_interface.if_name)); - - if (addr != NULL) - ret = icfg_set_addr(loc_handle, addr, addrsize); - - if (new_handle != NULL) - *new_handle = loc_handle; - else - icfg_close(loc_handle); - - return (ret); -} - -/* - * Removes specified IP address alias from physical interface. If the - * If the 'handle' argument is a handle to a physical interface, then - * the address alias removed must be specified by 'addr'. If the - * 'handle' argument is a handle for an IP address alias (currently - * represented as a logical interface), then that address alias - * (logical interface) is removed and the 'addr' argument is ignored. - * - * Under the logical interface model, an interface may only be removed - * if the interface is 'down'. - * - * Returns: ICFG_SUCCESS, ICFG_BAD_ADDR, ICFG_IF_UP, ICFG_NO_EXIST, - * or ICFG_FAILURE. - */ -int -icfg_remove_addr(icfg_handle_t handle, const struct sockaddr *addr, - socklen_t addrlen) -{ - struct lifreq lifr; - size_t addrsize; - - switch (icfg_if_protocol(handle)) { - case AF_INET: - addrsize = sizeof (struct sockaddr_in); - break; - case AF_INET6: - addrsize = sizeof (struct sockaddr_in6); - break; - default: - return (ICFG_BAD_ADDR); - } - - if (addr != NULL) { - if (addrlen < addrsize) { - errno = ENOSPC; - return (ICFG_FAILURE); - } - (void) memcpy(&lifr.lifr_addr, addr, addrsize); - } else { - (void) memset(&lifr.lifr_addr, 0, sizeof (lifr.lifr_addr)); - } - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - - if (ioctl(handle->ifh_sock, SIOCLIFREMOVEIF, (caddr_t)&lifr) < 0) - return (ICFG_FAILURE); - - return (ICFG_SUCCESS); -} - -/* - * Wrapper for sending a nontransparent I_STR ioctl(). - * Returns: Result from ioctl(). - * - * Same as in usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c - */ -static int -strioctl(int s, int cmd, char *buf, int buflen) -{ - struct strioctl ioc; - - (void) memset(&ioc, 0, sizeof (ioc)); - ioc.ic_cmd = cmd; - ioc.ic_timout = 0; - ioc.ic_len = buflen; - ioc.ic_dp = buf; - - return (ioctl(s, I_STR, (char *)&ioc)); -} - -/* - * Open a stream on /dev/udp{,6}, pop off all undesired modules (note that - * the user may have configured autopush to add modules above - * udp), and push the arp module onto the resulting stream. - * This is used to make IP+ARP be able to atomically track the muxid - * for the I_PLINKed STREAMS, thus it isn't related to ARP running the ARP - * protocol. - * - * Same as in usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c - */ -static int -open_arp_on_udp(char *udp_dev_name) -{ - int fd; - - if ((fd = open(udp_dev_name, O_RDWR)) == -1) - return (-1); - - errno = 0; - while (ioctl(fd, I_POP, 0) != -1) - ; - - if (errno == EINVAL && ioctl(fd, I_PUSH, ARP_MOD_NAME) != -1) - return (fd); - - (void) close(fd); - return (-1); -} - -/* - * We need to plink both the arp-device stream and the arp-ip-device stream. - * However the muxid is stored only in IP. Plumbing 2 streams individually - * is not atomic, and if ifconfig is killed, the resulting plumbing can - * be inconsistent. For eg. if only the arp stream is plumbed, we have lost - * the muxid, and the half-baked plumbing can neither be unplumbed nor - * replumbed, thus requiring a reboot. To avoid the above the following - * scheme is used. - * - * We ask IP to enforce atomicity of plumbing the arp and IP streams. - * This is done by pushing arp on to the mux (/dev/udp). ARP adds some - * extra information in the I_PLINK and I_PUNLINK ioctls to let IP know - * that the plumbing/unplumbing has to be done atomically. Ifconfig plumbs - * the IP stream first, and unplumbs it last. The kernel (IP) does not - * allow IP stream to be unplumbed without unplumbing arp stream. Similarly - * it does not allow arp stream to be plumbed before IP stream is plumbed. - * There is no need to use SIOCSLIFMUXID, since the whole operation is atomic, - * and IP uses the info in the I_PLINK message to get the muxid. - * - * a. STREAMS does not allow us to use /dev/ip itself as the mux. So we use - * /dev/udp{,6}. - * b. SIOCGLIFMUXID returns the muxid corresponding to the V4 or V6 stream - * depending on the open i.e. V4 vs V6 open. So we need to use /dev/udp - * or /dev/udp6 for SIOCGLIFMUXID and SIOCSLIFMUXID. - * c. We need to push ARP in order to get the required kernel support for - * atomic plumbings. The actual work done by ARP is explained in arp.c - * Without pushing ARP, we will still be able to plumb/unplumb. But - * it is not atomic, and is supported by the kernel for backward - * compatibility for other utilities like atmifconfig etc. In this case - * the utility must use SIOCSLIFMUXID. - * - * Returns: ICFG_SUCCESS, ICFG_EXISTS, ICFG_BAD_ADDR, ICFG_FAILURE, - * ICFG_DLPI_*, ICFG_NO_PLUMB_IP, ICFG_NO_PLUMB_ARP, - * ICFG_NO_UNPLUMB_ARP - */ -int -icfg_plumb(icfg_handle_t handle) -{ - int ip_muxid; - int mux_fd, ip_fd, arp_fd; - uint_t ppa; - char *udp_dev_name; - char provider[DLPI_LINKNAME_MAX]; - dlpi_handle_t dh_arp, dh_ip; - struct lifreq lifr; - int dlpi_ret, ret = ICFG_SUCCESS; - int saved_errno; /* to set errno after close() */ - int dh_arp_ret; /* to track if dh_arp was successfully opened */ - zoneid_t zoneid; - - /* Logical and loopback interfaces are just added */ - if (icfg_is_loopback(handle) || icfg_is_logical(handle)) - return (icfg_add_addr(handle, NULL, NULL, 0)); - - /* - * If we're running in the global zone, we need to - * make sure this link is actually assigned to us. - * - * This is not an issue if we are not in the global - * zone, as we simply can't see links we don't own. - */ - zoneid = getzoneid(); - if (zoneid == GLOBAL_ZONEID) { - dladm_handle_t dlh; - dladm_status_t status; - datalink_id_t linkid; - - if (dladm_open(&dlh) != DLADM_STATUS_OK) - return (ICFG_FAILURE); - status = dladm_name2info(dlh, icfg_if_name(handle), &linkid, - NULL, NULL, NULL); - dladm_close(dlh); - if (status != DLADM_STATUS_OK) - return (ICFG_INVALID_ARG); - zoneid = ALL_ZONES; - if (zone_check_datalink(&zoneid, linkid) == 0) - return (ICFG_INVALID_ARG); - } - - /* - * We use DLPI_NOATTACH because the ip module will do the attach - * itself for DLPI style-2 devices. - */ - if ((dlpi_ret = dlpi_open(icfg_if_name(handle), &dh_ip, - DLPI_NOATTACH)) != DLPI_SUCCESS) { - return (dlpi_error_to_icfg_error(dlpi_ret)); - } - if ((dlpi_ret = dlpi_parselink(icfg_if_name(handle), provider, - &ppa)) != DLPI_SUCCESS) { - ret = dlpi_error_to_icfg_error(dlpi_ret); - goto done; - } - - ip_fd = dlpi_fd(dh_ip); - if (ioctl(ip_fd, I_PUSH, IP_MOD_NAME) == -1) { - ret = ICFG_NO_PLUMB_IP; - goto done; - } - - /* - * Push the ARP module onto the interface stream. IP uses - * this to send resolution requests up to ARP. We need to - * do this before the SLIFNAME ioctl is sent down because - * the interface becomes publicly known as soon as the SLIFNAME - * ioctl completes. Thus some other process trying to bring up - * the interface after SLIFNAME but before we have pushed ARP - * could hang. We pop the module again later if it is not needed. - */ - if (ioctl(ip_fd, I_PUSH, ARP_MOD_NAME) == -1) { - ret = ICFG_NO_PLUMB_ARP; - goto done; - } - - /* - * Set appropriate IFF flags. The kernel only allows us to - * modify IFF_IPv[46], IFF_BROADCAST, and IFF_XRESOLV in the - * SIOCSLIFNAME ioctl call; so we only need to set the ones - * from that set that we care about. - */ - if (icfg_if_protocol(handle) == AF_INET6) - lifr.lifr_flags = IFF_IPV6; - else - lifr.lifr_flags = IFF_IPV4 | IFF_BROADCAST; - - /* record the device and module names as interface name */ - lifr.lifr_ppa = ppa; - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - - /* set the interface name */ - if (ioctl(ip_fd, SIOCSLIFNAME, (char *)&lifr) == -1) { - if (errno == EALREADY) - ret = ICFG_EXISTS; - else - ret = ICFG_NO_PLUMB_IP; - goto done; - } - - /* Get the full set of existing flags for this stream */ - if (ioctl(ip_fd, SIOCGLIFFLAGS, (char *)&lifr) == -1) { - if (errno == ENXIO) - ret = ICFG_NO_EXIST; - else - ret = ICFG_FAILURE; - goto done; - } - - /* Check if arp is not actually needed */ - if (lifr.lifr_flags & (IFF_NOARP|IFF_IPV6)) { - if (ioctl(ip_fd, I_POP, 0) == -1) { - ret = ICFG_NO_UNPLUMB_ARP; - goto done; - } - } - - /* - * Open "/dev/udp" for use as a multiplexor to PLINK the - * interface stream under. We use "/dev/udp" instead of "/dev/ip" - * since STREAMS will not let you PLINK a driver under itself, - * and "/dev/ip" is typically the driver at the bottom of - * the stream for tunneling interfaces. - */ - if (icfg_if_protocol(handle) == AF_INET6) - udp_dev_name = UDP6_DEV_NAME; - else - udp_dev_name = UDP_DEV_NAME; - - if ((mux_fd = open_arp_on_udp(udp_dev_name)) == -1) { - ret = ICFG_NO_PLUMB_ARP; - goto done; - } - - /* Check if arp is not needed */ - if (lifr.lifr_flags & (IFF_NOARP|IFF_IPV6)) { - /* - * PLINK the interface stream so that ifconfig can exit - * without tearing down the stream. - */ - if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) { - ret = ICFG_NO_PLUMB_IP; - goto done; - } - (void) close(mux_fd); - dlpi_close(dh_ip); - return (ICFG_SUCCESS); - } - - /* - * This interface does use ARP, so set up a separate stream - * from the interface to ARP. - * - * Note: modules specified by the user are pushed - * only on the interface stream, not on the ARP stream. - * - * We use DLPI_NOATTACH because the arp module will do the attach - * itself for DLPI style-2 devices. - */ - if ((dh_arp_ret = dlpi_open(icfg_if_name(handle), &dh_arp, - DLPI_NOATTACH)) != DLPI_SUCCESS) { - ret = dlpi_error_to_icfg_error(dh_arp_ret); - goto done; - } - - arp_fd = dlpi_fd(dh_arp); - if (ioctl(arp_fd, I_PUSH, ARP_MOD_NAME) == -1) { - ret = ICFG_NO_PLUMB_ARP; - goto done; - } - - /* - * Tell ARP the name and unit number for this interface. - * Note that arp has no support for transparent ioctls. - */ - if (strioctl(arp_fd, SIOCSLIFNAME, (char *)&lifr, - sizeof (lifr)) == -1) { - ret = ICFG_NO_PLUMB_ARP; - goto done; - } - /* - * PLINK the IP and ARP streams so that ifconfig can exit - * without tearing down the stream. - */ - if ((ip_muxid = ioctl(mux_fd, I_PLINK, ip_fd)) == -1) { - ret = ICFG_NO_PLUMB_IP; - goto done; - } - - if (ioctl(mux_fd, I_PLINK, arp_fd) == -1) { - (void) ioctl(mux_fd, I_PUNLINK, ip_muxid); - ret = ICFG_NO_PLUMB_ARP; - } - -done: - /* dlpi_close() may change errno, so save it */ - saved_errno = errno; - - dlpi_close(dh_ip); - if (dh_arp_ret == DLPI_SUCCESS) - dlpi_close(dh_arp); - - if (mux_fd != -1) - (void) close(mux_fd); - if (ret != ICFG_SUCCESS) - errno = saved_errno; - - return (ret); -} - -static boolean_t -ifaddr_down(ifaddrlistx_t *ifaddrp) -{ - icfg_handle_t addrh; - icfg_if_t addrif; - uint64_t addrflags; - boolean_t ret; - - addrif.if_protocol = ifaddrp->ia_flags & IFF_IPV6 ? AF_INET6 : AF_INET; - (void) strlcpy(addrif.if_name, ifaddrp->ia_name, - sizeof (addrif.if_name)); - if (icfg_open(&addrh, &addrif) != ICFG_SUCCESS) - return (B_FALSE); - - if (icfg_get_flags(addrh, &addrflags) != ICFG_SUCCESS) - return (B_FALSE); - - addrflags &= ~IFF_UP; - if (icfg_set_flags(addrh, addrflags) != ICFG_SUCCESS) { - ret = B_FALSE; - goto done; - } - - /* - * Make sure that DAD activity (observable by IFF_DUPLICATE) - * has also been stopped. If we were successful in downing - * the address, the get_flags will fail, as the addr will no - * longer exist. - */ - if ((icfg_get_flags(addrh, &addrflags) == ICFG_SUCCESS) && - addrflags & IFF_DUPLICATE) { - struct sockaddr_storage ss; - socklen_t alen = sizeof (ss); - int plen; - /* - * getting/setting the address resets DAD; and since - * we've already turned off IFF_UP, DAD will remain - * disabled. - */ - if ((icfg_get_addr(addrh, (struct sockaddr *)&ss, &alen, &plen, - B_FALSE) != ICFG_SUCCESS) || - (icfg_set_addr(addrh, (struct sockaddr *)&ss, alen) - != ICFG_SUCCESS)) { - ret = B_FALSE; - goto done; - } - } - ret = B_TRUE; -done: - icfg_close(addrh); - return (ret); -} - -/* - * If this is a physical interface then remove it. - * If it is a logical interface name use SIOCLIFREMOVEIF to - * remove it. In both cases fail if it doesn't exist. - * - * Returns: ICFG_SUCCESS, ICFG_EXISTS, ICFG_NO_EXIST, ICFG_BAD_ADDR, - * ICFG_FAILURE, ICFG_NO_UNPLUMB_IP, ICFG_NO_UNPLUMB_ARP, - * ICFG_INVALID_ARG, ICFG_NO_IP_MUX - * - * Same as inetunplumb() in usr/src/cmd/cmd-inet/usr.sbin/ifconfig/ifconfig.c - */ -int -icfg_unplumb(icfg_handle_t handle) -{ - int ip_muxid, arp_muxid; - int mux_fd; - int muxid_fd; - char *udp_dev_name; - uint64_t flags; - boolean_t changed_arp_muxid = B_FALSE; - int save_errno; - struct lifreq lifr; - int ret = ICFG_SUCCESS; - boolean_t v6 = (icfg_if_protocol(handle) == AF_INET6); - - /* Make sure interface exists to start with */ - if ((ret = icfg_get_flags(handle, &flags)) != ICFG_SUCCESS) { - return (ret); - } - - if (icfg_is_loopback(handle) || icfg_is_logical(handle)) { - char *strptr = strchr(icfg_if_name(handle), ICFG_LOGICAL_SEP); - - /* Can't unplumb logical interface zero */ - if (strptr != NULL && strcmp(strptr, ":0") == 0) - return (ICFG_INVALID_ARG); - - return (icfg_remove_addr(handle, NULL, 0)); - } - - /* - * We used /dev/udp or udp6 to set up the mux. So we have to use - * the same now for PUNLINK also. - */ - if (v6) - udp_dev_name = UDP6_DEV_NAME; - else - udp_dev_name = UDP_DEV_NAME; - - if ((muxid_fd = open(udp_dev_name, O_RDWR)) == -1) - return (ICFG_NO_UNPLUMB_ARP); - - if ((mux_fd = open_arp_on_udp(udp_dev_name)) == -1) { - ret = ICFG_NO_UNPLUMB_ARP; - goto done; - } - - (void) strlcpy(lifr.lifr_name, icfg_if_name(handle), - sizeof (lifr.lifr_name)); - if (ioctl(muxid_fd, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) { - ret = ICFG_FAILURE; - goto done; - } - flags = lifr.lifr_flags; - - /* - * libinetcfg's only current consumer is nwamd; and we expect it to - * be replaced before any other consumers come along. NWAM does not - * currently support creation of IPMP groups, so icfg_plumb(), for - * example, does not do any IPMP-specific handling. However, it's - * possible nwamd might need to unplumb an IPMP group, so we include - * IPMP group handling here. - */ -again: - if (flags & IFF_IPMP) { - lifgroupinfo_t lifgr; - ifaddrlistx_t *ifaddrs, *ifaddrp; - - /* - * There are two reasons the I_PUNLINK can fail with EBUSY: - * (1) if IP interfaces are in the group, or (2) if IPMP data - * addresses are administratively up. For case (1), we fail - * here with a specific error message. For case (2), we bring - * down the addresses prior to doing the I_PUNLINK. If the - * I_PUNLINK still fails with EBUSY then the configuration - * must have changed after our checks, in which case we branch - * back up to `again' and rerun this logic. The net effect is - * that unplumbing an IPMP interface will only fail with EBUSY - * if IP interfaces are in the group. - */ - ret = icfg_get_groupname(handle, lifgr.gi_grname, LIFGRNAMSIZ); - if (ret != ICFG_SUCCESS) - return (ret); - - ret = icfg_get_groupinfo(handle, &lifgr); - if (ret != ICFG_SUCCESS) - return (ret); - - /* make sure the group is empty */ - if ((v6 && lifgr.gi_nv6 != 0) || (!v6 && lifgr.gi_nv4 != 0)) - return (ICFG_INVALID_ARG); - - /* - * The kernel will fail the I_PUNLINK if the IPMP interface - * has administratively up addresses; bring 'em down. - */ - if (ifaddrlistx(icfg_if_name(handle), IFF_UP|IFF_DUPLICATE, - 0, &ifaddrs) == -1) - return (ICFG_FAILURE); - - ifaddrp = ifaddrs; - for (; ifaddrp != NULL; ifaddrp = ifaddrp->ia_next) { - if (((ifaddrp->ia_flags & IFF_IPV6) && !v6) || - (!(ifaddrp->ia_flags && IFF_IPV6) && v6)) - continue; - - if (!ifaddr_down(ifaddrp)) { - ifaddrlistx_free(ifaddrs); - return (ICFG_FAILURE); - } - } - ifaddrlistx_free(ifaddrs); - } - - if (ioctl(muxid_fd, SIOCGLIFMUXID, (caddr_t)&lifr) < 0) { - ret = ICFG_NO_IP_MUX; - goto done; - } - arp_muxid = lifr.lifr_arp_muxid; - ip_muxid = lifr.lifr_ip_muxid; - /* - * We don't have a good way of knowing whether the arp stream is - * plumbed. We can't rely on IFF_NOARP because someone could - * have turned it off later using "ifconfig xxx -arp". - */ - if (arp_muxid != 0) { - if (ioctl(mux_fd, I_PUNLINK, arp_muxid) < 0) { - /* - * See the comment before the icfg_get_groupname() call. - */ - if (errno == EBUSY && (flags & IFF_IPMP)) - goto again; - - if ((errno == EINVAL) && - (flags & (IFF_NOARP | IFF_IPV6))) { - /* - * Some plumbing utilities set the muxid to - * -1 or some invalid value to signify that - * there is no arp stream. Set the muxid to 0 - * before trying to unplumb the IP stream. - * IP does not allow the IP stream to be - * unplumbed if it sees a non-null arp muxid, - * for consistency of IP-ARP streams. - */ - lifr.lifr_arp_muxid = 0; - (void) ioctl(muxid_fd, SIOCSLIFMUXID, - (caddr_t)&lifr); - changed_arp_muxid = B_TRUE; - } else { - ret = ICFG_NO_UNPLUMB_ARP; - } - } - } - - if (ioctl(mux_fd, I_PUNLINK, ip_muxid) < 0) { - if (changed_arp_muxid) { - /* - * Some error occurred, and we need to restore - * everything back to what it was. - */ - save_errno = errno; - lifr.lifr_arp_muxid = arp_muxid; - lifr.lifr_ip_muxid = ip_muxid; - (void) ioctl(muxid_fd, SIOCSLIFMUXID, (caddr_t)&lifr); - errno = save_errno; - } - - /* - * See the comment before the icfg_get_groupname() call. - */ - if (errno == EBUSY && (flags && IFF_IPMP)) - goto again; - - ret = ICFG_NO_UNPLUMB_IP; - } -done: - /* close() may change errno, so save it */ - save_errno = errno; - - (void) close(muxid_fd); - if (mux_fd != -1) - (void) close(mux_fd); - - if (ret != ICFG_SUCCESS) - errno = save_errno; - - return (ret); -} diff --git a/usr/src/lib/libinetcfg/common/inetcfg.h b/usr/src/lib/libinetcfg/common/inetcfg.h deleted file mode 100644 index 5f3d8db0bff3..000000000000 --- a/usr/src/lib/libinetcfg/common/inetcfg.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _INETCFG_H -#define _INETCFG_H - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* error codes */ -typedef enum { - ICFG_SUCCESS, /* No error occurred */ - ICFG_FAILURE, /* Generic failure */ - ICFG_NO_MEMORY, /* Insufficient memory */ - ICFG_NOT_TUNNEL, /* Tunnel operation attempted on non-tunnel */ - ICFG_NOT_SET, /* Could not return non-existent value */ - ICFG_BAD_ADDR, /* Invalid address */ - ICFG_BAD_PROTOCOL, /* Wrong protocol family for operation */ - ICFG_DAD_FAILED, /* Duplicate address detection failure */ - ICFG_DAD_FOUND, /* Duplicate address detected */ - ICFG_IF_UP, /* Interface is up */ - ICFG_EXISTS, /* Interface already exists */ - ICFG_NO_EXIST, /* Interface does not exist */ - ICFG_INVALID_ARG, /* Invalid argument */ - ICFG_INVALID_NAME, /* Invalid name */ - ICFG_DLPI_INVALID_LINK, /* Invalid DLPI link */ - ICFG_DLPI_FAILURE, /* Generic DLPI failure */ - ICFG_NO_PLUMB_IP, /* Could not plumb IP stream */ - ICFG_NO_PLUMB_ARP, /* Could not plumb ARP stream */ - ICFG_NO_UNPLUMB_IP, /* Could not unplumb IP stream */ - ICFG_NO_UNPLUMB_ARP, /* Could not unplumb ARP stream */ - ICFG_NO_IP_MUX /* No IP mux set on the interface */ -} icfg_error_t; - -/* valid types for icfg_get_if_list() */ -#define ICFG_PLUMBED 0 -#define ICFG_INSTALLED 1 - -typedef struct icfg_if { - char if_name[LIFNAMSIZ]; /* name of interface (eg., hme0) */ - sa_family_t if_protocol; /* IP protocol version */ -} icfg_if_t; - -typedef struct icfg_handle { - int ifh_sock; /* socket to interface */ - icfg_if_t ifh_interface; /* interface definition */ -} *icfg_handle_t; - -/* retrieve error string */ -extern const char *icfg_errmsg(int); - -/* handle functions */ -extern int icfg_open(icfg_handle_t *, const icfg_if_t *); -extern void icfg_close(icfg_handle_t); -extern boolean_t icfg_is_logical(icfg_handle_t); - -/* get interface name */ -extern const char *icfg_if_name(icfg_handle_t); - -/* set interface properties */ -extern int icfg_set_flags(icfg_handle_t, uint64_t); -extern int icfg_set_metric(icfg_handle_t, int); -extern int icfg_set_mtu(icfg_handle_t, uint_t); -extern int icfg_set_index(icfg_handle_t, int); -extern int icfg_set_netmask(icfg_handle_t, const struct sockaddr_in *); -extern int icfg_set_broadcast(icfg_handle_t, const struct sockaddr_in *); -extern int icfg_set_prefixlen(icfg_handle_t, int); -extern int icfg_set_addr(icfg_handle_t, const struct sockaddr *, socklen_t); -extern int icfg_set_token(icfg_handle_t, const struct sockaddr_in6 *, int); -extern int icfg_set_subnet(icfg_handle_t, const struct sockaddr *, socklen_t, - int); -extern int icfg_set_dest_addr(icfg_handle_t, const struct sockaddr *, - socklen_t); - -/* get interface properties */ -extern int icfg_get_addr(icfg_handle_t, struct sockaddr *, socklen_t *, int *, - boolean_t); -extern int icfg_get_token(icfg_handle_t, struct sockaddr_in6 *, int *, - boolean_t); -extern int icfg_get_subnet(icfg_handle_t, struct sockaddr *, socklen_t *, - int *, boolean_t); -extern int icfg_get_netmask(icfg_handle_t, struct sockaddr_in *); -extern int icfg_get_broadcast(icfg_handle_t, struct sockaddr_in *); -extern int icfg_get_dest_addr(icfg_handle_t, struct sockaddr *, socklen_t *); -extern int icfg_get_groupname(icfg_handle_t, char *, size_t); -extern int icfg_get_flags(icfg_handle_t, uint64_t *); -extern int icfg_get_metric(icfg_handle_t, int *); -extern int icfg_get_mtu(icfg_handle_t, uint_t *); -extern int icfg_get_index(icfg_handle_t, int *); - -/* retrieve interface list or iterate over all interface lists */ -extern int icfg_get_if_list(icfg_if_t **, int *, int, int); -extern void icfg_free_if_list(icfg_if_t *); -extern int icfg_iterate_if(int, int, void *, int (*)(icfg_if_t *, void *)); - -extern int icfg_sockaddr_to_str(sa_family_t, const struct sockaddr *, - char *, size_t); -extern int icfg_str_to_sockaddr(sa_family_t, const char *, struct sockaddr *, - socklen_t *); - -/* plumb or unplumb interfaces, add or remove IP */ -extern int icfg_add_addr(icfg_handle_t, icfg_handle_t *, - const struct sockaddr *, socklen_t); -extern int icfg_remove_addr(icfg_handle_t, const struct sockaddr *, socklen_t); - -extern int icfg_plumb(icfg_handle_t); -extern int icfg_unplumb(icfg_handle_t); - -#ifdef __cplusplus -} -#endif - -#endif /* _INETCFG_H */ diff --git a/usr/src/lib/libinetcfg/common/llib-linetcfg b/usr/src/lib/libinetcfg/common/llib-linetcfg deleted file mode 100644 index e7c3e33679e1..000000000000 --- a/usr/src/lib/libinetcfg/common/llib-linetcfg +++ /dev/null @@ -1,29 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* LINTLIBRARY */ -/* PROTOLIB1 */ - -#include diff --git a/usr/src/lib/libinetcfg/common/mapfile-vers b/usr/src/lib/libinetcfg/common/mapfile-vers deleted file mode 100644 index c331872916f0..000000000000 --- a/usr/src/lib/libinetcfg/common/mapfile-vers +++ /dev/null @@ -1,79 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -SUNWprivate_1.1 { - global: - icfg_add_addr; - icfg_close; - icfg_errmsg; - icfg_free_if_list; - icfg_get_addr; - icfg_get_broadcast; - icfg_get_dest_addr; - icfg_get_flags; - icfg_get_groupname; - icfg_get_if_list; - icfg_get_index; - icfg_get_metric; - icfg_get_mtu; - icfg_get_netmask; - icfg_get_subnet; - icfg_get_token; - icfg_if_name; - icfg_is_logical; - icfg_iterate_if; - icfg_open; - icfg_plumb; - icfg_remove_addr; - icfg_set_addr; - icfg_set_broadcast; - icfg_set_dest_addr; - icfg_set_flags; - icfg_set_index; - icfg_set_metric; - icfg_set_mtu; - icfg_set_netmask; - icfg_set_prefixlen; - icfg_set_subnet; - icfg_set_token; - icfg_sockaddr_to_str; - icfg_str_to_sockaddr; - icfg_unplumb; - local: - *; -}; diff --git a/usr/src/lib/libinetcfg/i386/Makefile b/usr/src/lib/libinetcfg/i386/Makefile deleted file mode 100644 index 81c248309867..000000000000 --- a/usr/src/lib/libinetcfg/i386/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2002 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# lib/libinetcfg/i386/Makefile - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libinetcfg/libinetcfg.xcl b/usr/src/lib/libinetcfg/libinetcfg.xcl deleted file mode 100644 index ede501b7c79b..000000000000 --- a/usr/src/lib/libinetcfg/libinetcfg.xcl +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2002 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -msgid "255.255.255.255" -msgid "%s%d" - diff --git a/usr/src/lib/libinetcfg/sparc/Makefile b/usr/src/lib/libinetcfg/sparc/Makefile deleted file mode 100644 index 33927ea5fff1..000000000000 --- a/usr/src/lib/libinetcfg/sparc/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2002 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# lib/libinetcfg/sparc/Makefile - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libipadm/common/ipadm_addr.c b/usr/src/lib/libipadm/common/ipadm_addr.c index 5c7b7ee2c0c9..b647abf0b148 100644 --- a/usr/src/lib/libipadm/common/ipadm_addr.c +++ b/usr/src/lib/libipadm/common/ipadm_addr.c @@ -1746,6 +1746,21 @@ ipadm_set_addr(ipadm_addrobj_t ipaddr, const char *astr, sa_family_t af) return (status); } +/* + * Gets the static source address from the address object in `ipaddr'. + * Memory for `addr' should be already allocated by the caller. + */ +ipadm_status_t +ipadm_get_addr(const ipadm_addrobj_t ipaddr, struct sockaddr_storage *addr) +{ + if (ipaddr == NULL || ipaddr->ipadm_atype != IPADM_ADDR_STATIC || + addr == NULL) { + return (IPADM_INVALID_ARG); + } + *addr = ipaddr->ipadm_static_addr; + + return (IPADM_SUCCESS); +} /* * Set up tunnel destination address in ipaddr by contacting DNS. * The function works similar to ipadm_set_addr(). @@ -2206,6 +2221,20 @@ ipadm_create_addrobj(ipadm_addr_type_t type, const char *aobjname, return (status); } +/* + * Returns `aobjname' from the address object in `ipaddr'. + */ +ipadm_status_t +ipadm_get_aobjname(const ipadm_addrobj_t ipaddr, char *aobjname, size_t len) +{ + if (ipaddr == NULL || aobjname == NULL) + return (IPADM_INVALID_ARG); + if (strlcpy(aobjname, ipaddr->ipadm_aobjname, len) >= len) + return (IPADM_INVALID_ARG); + + return (IPADM_SUCCESS); +} + /* * Frees the address object in `ipaddr'. */ @@ -2355,6 +2384,10 @@ i_ipadm_get_db_addr(ipadm_handle_t iph, const char *ifname, * if provided, will be ignored and replaced with the newly generated name. * The interface name provided has to be a logical interface name that * already exists. No new logical interface will be added in this function. + * + * If IPADM_OPT_V46 is passed in the flags, then both IPv4 and IPv6 interfaces + * are plumbed (if they haven't been already). Otherwise, just the interface + * specified in `addr' is plumbed. */ ipadm_status_t ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags) @@ -2435,7 +2468,7 @@ ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags) } if (status == IPADM_SUCCESS) created_af = B_TRUE; - if (!is_6to4 && !legacy) { + if (!is_6to4 && !legacy && (flags & IPADM_OPT_V46)) { other_af = (af == AF_INET ? AF_INET6 : AF_INET); status = i_ipadm_create_if(iph, ifname, other_af, flags); if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) { @@ -2672,7 +2705,7 @@ i_ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t ipaddr, uint32_t flags) * in the address object will be removed from the physical interface. * If the address type is IPADM_ADDR_DHCP, the flag IPADM_OPT_RELEASE specifies * whether the lease should be released. If IPADM_OPT_RELEASE is not - * specified, the lease will be dropped. This option is ignored + * specified, the lease will be dropped. This option is not supported * for other address types. * * If the address type is IPADM_ADDR_IPV6_ADDRCONF, the link-local address and @@ -3329,7 +3362,7 @@ i_ipadm_validate_create_addr(ipadm_handle_t iph, ipadm_addrobj_t ipaddr, boolean_t af_exists, other_af_exists, a_exists; if (ipaddr == NULL || flags == 0 || flags == IPADM_OPT_PERSIST || - (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP))) { + (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP|IPADM_OPT_V46))) { return (IPADM_INVALID_ARG); } diff --git a/usr/src/lib/libipadm/common/libipadm.c b/usr/src/lib/libipadm/common/libipadm.c index 2c18331a7b37..4103ebbd85a1 100644 --- a/usr/src/lib/libipadm/common/libipadm.c +++ b/usr/src/lib/libipadm/common/libipadm.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include @@ -858,6 +857,7 @@ ipadm_door_call(ipadm_handle_t iph, void *arg, size_t asize, void **rbufp, door_arg_t darg; int err; ipmgmt_retval_t rval, *rvalp; + boolean_t reopen = B_FALSE; if (rbufp == NULL) { rvalp = &rval; @@ -872,6 +872,7 @@ ipadm_door_call(ipadm_handle_t iph, void *arg, size_t asize, void **rbufp, darg.rbuf = *rbufp; darg.rsize = rsize; +reopen: (void) pthread_mutex_lock(&iph->iph_lock); /* The door descriptor is opened if it isn't already */ if (iph->iph_door_fd == -1) { @@ -883,8 +884,20 @@ ipadm_door_call(ipadm_handle_t iph, void *arg, size_t asize, void **rbufp, } (void) pthread_mutex_unlock(&iph->iph_lock); - if (door_call(iph->iph_door_fd, &darg) == -1) + if (door_call(iph->iph_door_fd, &darg) == -1) { + /* + * Stale door descriptor is possible if ipmgmtd was restarted + * since last iph_door_fd was opened, so try re-opening door + * descriptor. + */ + if (!reopen && errno == EBADF) { + (void) close(iph->iph_door_fd); + iph->iph_door_fd = -1; + reopen = B_TRUE; + goto reopen; + } return (errno); + } err = ((ipmgmt_retval_t *)(void *)(darg.rbuf))->ir_err; if (darg.rbuf != *rbufp) { /* diff --git a/usr/src/lib/libipadm/common/libipadm.h b/usr/src/lib/libipadm/common/libipadm.h index 8ef516e814d5..32fb89e2e829 100644 --- a/usr/src/lib/libipadm/common/libipadm.h +++ b/usr/src/lib/libipadm/common/libipadm.h @@ -138,6 +138,9 @@ typedef enum { * * - IPADM_OPT_UP * Used to bring up a static address on creation + * + * - IPADM_OPT_V46 + * Used to plumb both IPv4 and IPv6 interfaces by ipadm_create_addr() */ #define IPADM_OPT_PERSIST 0x00000001 #define IPADM_OPT_ACTIVE 0x00000002 @@ -152,6 +155,7 @@ typedef enum { #define IPADM_OPT_RELEASE 0x00000400 #define IPADM_OPT_INFORM 0x00000800 #define IPADM_OPT_UP 0x00001000 +#define IPADM_OPT_V46 0x00002000 /* IPADM property class */ #define IPADMPROP_CLASS_MODULE 0x00000001 /* on 'protocol' only */ @@ -284,12 +288,16 @@ extern ipadm_status_t ipadm_delete_addr(ipadm_handle_t, const char *, extern ipadm_status_t ipadm_create_addrobj(ipadm_addr_type_t, const char *, ipadm_addrobj_t *); extern void ipadm_destroy_addrobj(ipadm_addrobj_t); +extern ipadm_status_t ipadm_get_aobjname(const ipadm_addrobj_t, char *, + size_t); /* Functions to set fields in addrobj for static addresses */ extern ipadm_status_t ipadm_set_addr(ipadm_addrobj_t, const char *, sa_family_t); extern ipadm_status_t ipadm_set_dst_addr(ipadm_addrobj_t, const char *, sa_family_t); +extern ipadm_status_t ipadm_get_addr(const ipadm_addrobj_t, + struct sockaddr_storage *); /* Functions to set fields in addrobj for IPv6 addrconf */ extern ipadm_status_t ipadm_set_interface_id(ipadm_addrobj_t, const char *); diff --git a/usr/src/lib/libipadm/common/mapfile-vers b/usr/src/lib/libipadm/common/mapfile-vers index cb835c126620..9d8cdf55927d 100644 --- a/usr/src/lib/libipadm/common/mapfile-vers +++ b/usr/src/lib/libipadm/common/mapfile-vers @@ -56,7 +56,9 @@ SUNWprivate_1.1 { ipadm_enable_if; ipadm_free_addr_info; ipadm_free_if_info; + ipadm_get_addr; ipadm_get_addrprop; + ipadm_get_aobjname; ipadm_get_ifprop; ipadm_get_prop; ipadm_if_enabled; diff --git a/usr/src/lib/libnwam/common/libnwam.h b/usr/src/lib/libnwam/common/libnwam.h index b049d630c250..3cc7c724b534 100644 --- a/usr/src/lib/libnwam/common/libnwam.h +++ b/usr/src/lib/libnwam/common/libnwam.h @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -1019,11 +1018,10 @@ struct nwam_event { struct nwam_event_if_state { char nwe_name[NWAM_MAX_NAME_LEN]; uint32_t nwe_flags; - uint32_t nwe_index; uint32_t nwe_addr_valid; /* boolean */ uint32_t nwe_addr_added; /* boolean */ struct sockaddr_storage nwe_addr; - /* might be longer then sizeof(if_state) for addr */ + struct sockaddr_storage nwe_netmask; } nwe_if_state; struct nwam_event_link_state { diff --git a/usr/src/pkg/manifests/system-library.mf b/usr/src/pkg/manifests/system-library.mf index ad7eb927c5b9..29c02112f607 100644 --- a/usr/src/pkg/manifests/system-library.mf +++ b/usr/src/pkg/manifests/system-library.mf @@ -182,7 +182,6 @@ file path=lib/libelf.so.1 file path=lib/libelfsign.so.1 $(i386_ONLY)file path=lib/libfdisk.so.1 file path=lib/libgen.so.1 -file path=lib/libinetcfg.so.1 file path=lib/libinetutil.so.1 file path=lib/libintl.so.1 file path=lib/libipadm.so.1 @@ -982,7 +981,6 @@ link path=usr/lib/libgen.so target=../../lib/libgen.so.1 link path=usr/lib/libgen.so.1 target=../../lib/libgen.so.1 link path=usr/lib/libhotplug.so target=./libhotplug.so.1 link path=usr/lib/libidmap.so target=./libidmap.so.1 -link path=usr/lib/libinetcfg.so.1 target=../../lib/libinetcfg.so.1 link path=usr/lib/libinetutil.so.1 target=../../lib/libinetutil.so.1 link path=usr/lib/libintl.so target=../../lib/libintl.so.1 link path=usr/lib/libintl.so.1 target=../../lib/libintl.so.1 diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index a60b62a8ee0a..8c1f50dc7021 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -6595,7 +6595,6 @@ mondo_loop() { $usr/lib/libgen.a \ $usr/lib/libgenIO.a \ $usr/lib/libike.a \ - $usr/lib/libinetcfg.a \ $usr/lib/libinetutil.a \ $usr/lib/libintl.a \ $usr/lib/libkstat.a \