17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5392b1d6eSyz147064 * Common Development and Distribution License (the "License"). 6392b1d6eSyz147064 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*64639aafSDarren Reed * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 267c478bd9Sstevel@tonic-gate * This RCM module adds support to the RCM framework for IP managed 277c478bd9Sstevel@tonic-gate * interfaces. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <assert.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <synch.h> 367c478bd9Sstevel@tonic-gate #include <libintl.h> 377c478bd9Sstevel@tonic-gate #include <errno.h> 387c478bd9Sstevel@tonic-gate #include <fcntl.h> 397c478bd9Sstevel@tonic-gate #include <sys/types.h> 40e11c3f44Smeem #include <sys/wait.h> 417c478bd9Sstevel@tonic-gate #include <sys/stat.h> 427c478bd9Sstevel@tonic-gate #include <sys/socket.h> 437c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 447c478bd9Sstevel@tonic-gate #include <net/if.h> 457c478bd9Sstevel@tonic-gate #include <netinet/in.h> 467c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 477c478bd9Sstevel@tonic-gate #include <stropts.h> 487c478bd9Sstevel@tonic-gate #include <strings.h> 49e11c3f44Smeem #include <sys/sysmacros.h> 50ff550d0eSmasputra #include <inet/ip.h> 51595aa6e4Smeem #include <libinetutil.h> 52d62bc4baSyz147064 #include <libdllink.h> 53e11c3f44Smeem #include <libgen.h> 54e11c3f44Smeem #include <ipmp_admin.h> 556e91bba0SGirish Moodalbail #include <libipadm.h> 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #include "rcm_module.h" 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Definitions 617c478bd9Sstevel@tonic-gate */ 627c478bd9Sstevel@tonic-gate #ifndef lint 637c478bd9Sstevel@tonic-gate #define _(x) gettext(x) 647c478bd9Sstevel@tonic-gate #else 657c478bd9Sstevel@tonic-gate #define _(x) x 667c478bd9Sstevel@tonic-gate #endif 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* Some generic well-knowns and defaults used in this module */ 697c478bd9Sstevel@tonic-gate #define ARP_MOD_NAME "arp" /* arp module */ 707c478bd9Sstevel@tonic-gate #define IP_MAX_MODS 9 /* max modules pushed on intr */ 717c478bd9Sstevel@tonic-gate #define MAX_RECONFIG_SIZE 1024 /* Max. reconfig string size */ 727c478bd9Sstevel@tonic-gate 73d62bc4baSyz147064 #define RCM_LINK_PREFIX "SUNW_datalink" /* RCM datalink name prefix */ 74d62bc4baSyz147064 #define RCM_LINK_RESOURCE_MAX (13 + LINKID_STR_WIDTH) 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate #define RCM_STR_SUNW_IP "SUNW_ip/" /* IP address export prefix */ 777c478bd9Sstevel@tonic-gate 78e11c3f44Smeem #define SBIN_IFCONFIG "/sbin/ifconfig" /* ifconfig command */ 79e11c3f44Smeem #define SBIN_IFPARSE "/sbin/ifparse" /* ifparse command */ 80e11c3f44Smeem #define DHCPFILE_FMT "/etc/dhcp.%s" /* DHCP config file */ 81e11c3f44Smeem #define CFGFILE_FMT_IPV4 "/etc/hostname.%s" /* IPV4 config file */ 82e11c3f44Smeem #define CFGFILE_FMT_IPV6 "/etc/hostname6.%s" /* IPV6 config file */ 837c478bd9Sstevel@tonic-gate #define CFG_CMDS_STD " netmask + broadcast + up" /* Normal config string */ 84e11c3f44Smeem #define CFG_DHCP_CMD "dhcp wait 0" /* command to start DHCP */ 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* Some useful macros */ 877c478bd9Sstevel@tonic-gate #define ISSPACE(c) ((c) == ' ' || (c) == '\t') 887c478bd9Sstevel@tonic-gate #define ISEOL(c) ((c) == '\n' || (c) == '\r' || (c) == '\0') 897c478bd9Sstevel@tonic-gate #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* Interface Cache state flags */ 927c478bd9Sstevel@tonic-gate #define CACHE_IF_STALE 0x1 /* stale cached data */ 937c478bd9Sstevel@tonic-gate #define CACHE_IF_NEW 0x2 /* new cached interface */ 947c478bd9Sstevel@tonic-gate #define CACHE_IF_OFFLINED 0x4 /* interface offlined */ 95392b1d6eSyz147064 #define CACHE_IF_IGNORE 0x8 /* state held elsewhere */ 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* Network Cache lookup options */ 987c478bd9Sstevel@tonic-gate #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */ 997c478bd9Sstevel@tonic-gate #define CACHE_REFRESH 0x2 /* refresh cache */ 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* RCM IPMP Module specific property definitions */ 1027c478bd9Sstevel@tonic-gate #define RCM_IPMP_MIN_REDUNDANCY 1 /* default min. redundancy */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* Stream module operations */ 1057c478bd9Sstevel@tonic-gate #define MOD_INSERT 0 /* Insert a mid-stream module */ 1067c478bd9Sstevel@tonic-gate #define MOD_REMOVE 1 /* Remove a mid-stream module */ 1077c478bd9Sstevel@tonic-gate #define MOD_CHECK 2 /* Check mid-stream module safety */ 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * IP module data types 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* Physical interface representation */ 1147c478bd9Sstevel@tonic-gate typedef struct ip_pif { 115e11c3f44Smeem char pi_ifname[LIFNAMSIZ]; /* interface name */ 116e11c3f44Smeem char pi_grname[LIFGRNAMSIZ]; /* IPMP group name */ 1177c478bd9Sstevel@tonic-gate struct ip_lif *pi_lifs; /* ptr to logical interfaces */ 1187c478bd9Sstevel@tonic-gate } ip_pif_t; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* Logical interface representation */ 1217c478bd9Sstevel@tonic-gate typedef struct ip_lif 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate struct ip_lif *li_next; /* ptr to next lif */ 1247c478bd9Sstevel@tonic-gate struct ip_lif *li_prev; /* previous next ptr */ 1257c478bd9Sstevel@tonic-gate ip_pif_t *li_pif; /* back ptr to phy int */ 1267c478bd9Sstevel@tonic-gate ushort_t li_ifnum; /* interface number */ 1277c478bd9Sstevel@tonic-gate union { 1287c478bd9Sstevel@tonic-gate sa_family_t family; 1297c478bd9Sstevel@tonic-gate struct sockaddr_storage storage; 1307c478bd9Sstevel@tonic-gate struct sockaddr_in ip4; /* IPv4 */ 1317c478bd9Sstevel@tonic-gate struct sockaddr_in6 ip6; /* IPv6 */ 1327c478bd9Sstevel@tonic-gate } li_addr; 1337c478bd9Sstevel@tonic-gate uint64_t li_ifflags; /* current IFF_* flags */ 1347c478bd9Sstevel@tonic-gate int li_modcnt; /* # of modules */ 1357c478bd9Sstevel@tonic-gate char *li_modules[IP_MAX_MODS]; /* module list pushed */ 1367c478bd9Sstevel@tonic-gate char *li_reconfig; /* Reconfiguration string */ 1377c478bd9Sstevel@tonic-gate int32_t li_cachestate; /* cache state flags */ 1387c478bd9Sstevel@tonic-gate } ip_lif_t; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* Cache element */ 1417c478bd9Sstevel@tonic-gate typedef struct ip_cache 1427c478bd9Sstevel@tonic-gate { 1437c478bd9Sstevel@tonic-gate struct ip_cache *ip_next; /* next cached resource */ 1447c478bd9Sstevel@tonic-gate struct ip_cache *ip_prev; /* prev cached resource */ 1457c478bd9Sstevel@tonic-gate char *ip_resource; /* resource name */ 1467c478bd9Sstevel@tonic-gate ip_pif_t *ip_pif; /* ptr to phy int */ 1477c478bd9Sstevel@tonic-gate int32_t ip_ifred; /* min. redundancy */ 1487c478bd9Sstevel@tonic-gate int ip_cachestate; /* cache state flags */ 1497c478bd9Sstevel@tonic-gate } ip_cache_t; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * Global cache for network interfaces 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate static ip_cache_t cache_head; 1557c478bd9Sstevel@tonic-gate static ip_cache_t cache_tail; 1567c478bd9Sstevel@tonic-gate static mutex_t cache_lock; 1577c478bd9Sstevel@tonic-gate static int events_registered = 0; 1587c478bd9Sstevel@tonic-gate 1594ac67f02SAnurag S. Maskey static dladm_handle_t dld_handle = NULL; 1606e91bba0SGirish Moodalbail static ipadm_handle_t ip_handle = NULL; 1614ac67f02SAnurag S. Maskey 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * RCM module interface prototypes 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate static int ip_register(rcm_handle_t *); 1667c478bd9Sstevel@tonic-gate static int ip_unregister(rcm_handle_t *); 1677c478bd9Sstevel@tonic-gate static int ip_get_info(rcm_handle_t *, char *, id_t, uint_t, 1687c478bd9Sstevel@tonic-gate char **, char **, nvlist_t *, rcm_info_t **); 1697c478bd9Sstevel@tonic-gate static int ip_suspend(rcm_handle_t *, char *, id_t, 1707c478bd9Sstevel@tonic-gate timespec_t *, uint_t, char **, rcm_info_t **); 1717c478bd9Sstevel@tonic-gate static int ip_resume(rcm_handle_t *, char *, id_t, uint_t, 1727c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 1737c478bd9Sstevel@tonic-gate static int ip_offline(rcm_handle_t *, char *, id_t, uint_t, 1747c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 1757c478bd9Sstevel@tonic-gate static int ip_undo_offline(rcm_handle_t *, char *, id_t, uint_t, 1767c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 1777c478bd9Sstevel@tonic-gate static int ip_remove(rcm_handle_t *, char *, id_t, uint_t, 1787c478bd9Sstevel@tonic-gate char **, rcm_info_t **); 1797c478bd9Sstevel@tonic-gate static int ip_notify_event(rcm_handle_t *, char *, id_t, uint_t, 1807c478bd9Sstevel@tonic-gate char **, nvlist_t *, rcm_info_t **); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* Module private routines */ 1837c478bd9Sstevel@tonic-gate static void free_cache(); 1847c478bd9Sstevel@tonic-gate static int update_cache(rcm_handle_t *); 1857c478bd9Sstevel@tonic-gate static void cache_remove(ip_cache_t *); 1867c478bd9Sstevel@tonic-gate static ip_cache_t *cache_lookup(rcm_handle_t *, char *, char); 1877c478bd9Sstevel@tonic-gate static void free_node(ip_cache_t *); 1887c478bd9Sstevel@tonic-gate static void cache_insert(ip_cache_t *); 1897c478bd9Sstevel@tonic-gate static char *ip_usage(ip_cache_t *); 1906e91bba0SGirish Moodalbail static int update_pif(rcm_handle_t *, int, int, struct ifaddrs *); 191e11c3f44Smeem static int ip_ipmp_offline(ip_cache_t *); 1927c478bd9Sstevel@tonic-gate static int ip_ipmp_undo_offline(ip_cache_t *); 1937c478bd9Sstevel@tonic-gate static int if_cfginfo(ip_cache_t *, uint_t); 1947c478bd9Sstevel@tonic-gate static int if_unplumb(ip_cache_t *); 1957c478bd9Sstevel@tonic-gate static int if_replumb(ip_cache_t *); 1967c478bd9Sstevel@tonic-gate static void ip_log_err(ip_cache_t *, char **, char *); 197d62bc4baSyz147064 static char *get_link_resource(const char *); 1987c478bd9Sstevel@tonic-gate static void clr_cfg_state(ip_pif_t *); 1997c478bd9Sstevel@tonic-gate static int modop(char *, char *, int, char); 2007c478bd9Sstevel@tonic-gate static int get_modlist(char *, ip_lif_t *); 201fc80c0dfSnordmark static int ip_domux2fd(int *, int *, int *, struct lifreq *); 202fc80c0dfSnordmark static int ip_plink(int, int, int, struct lifreq *); 2037c478bd9Sstevel@tonic-gate static int ip_onlinelist(rcm_handle_t *, ip_cache_t *, char **, uint_t, 2047c478bd9Sstevel@tonic-gate rcm_info_t **); 2057c478bd9Sstevel@tonic-gate static int ip_offlinelist(rcm_handle_t *, ip_cache_t *, char **, uint_t, 2067c478bd9Sstevel@tonic-gate rcm_info_t **); 2077c478bd9Sstevel@tonic-gate static char **ip_get_addrlist(ip_cache_t *); 2087c478bd9Sstevel@tonic-gate static void ip_free_addrlist(char **); 209d62bc4baSyz147064 static void ip_consumer_notify(rcm_handle_t *, datalink_id_t, char **, 210d62bc4baSyz147064 uint_t, rcm_info_t **); 211e11c3f44Smeem static boolean_t ip_addrstr(ip_lif_t *, char *, size_t); 2127c478bd9Sstevel@tonic-gate 2136e91bba0SGirish Moodalbail static int if_configure_hostname(datalink_id_t); 2146e91bba0SGirish Moodalbail static int if_configure_ipadm(datalink_id_t); 2156e91bba0SGirish Moodalbail static boolean_t if_hostname_exists(char *, sa_family_t); 216e11c3f44Smeem static boolean_t isgrouped(const char *); 217e11c3f44Smeem static int if_config_inst(const char *, FILE *, int, boolean_t); 218e11c3f44Smeem static uint_t ntok(const char *cp); 219e11c3f44Smeem static boolean_t ifconfig(const char *, const char *, const char *, boolean_t); 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* Module-Private data */ 2227c478bd9Sstevel@tonic-gate static struct rcm_mod_ops ip_ops = 2237c478bd9Sstevel@tonic-gate { 2247c478bd9Sstevel@tonic-gate RCM_MOD_OPS_VERSION, 2257c478bd9Sstevel@tonic-gate ip_register, 2267c478bd9Sstevel@tonic-gate ip_unregister, 2277c478bd9Sstevel@tonic-gate ip_get_info, 2287c478bd9Sstevel@tonic-gate ip_suspend, 2297c478bd9Sstevel@tonic-gate ip_resume, 2307c478bd9Sstevel@tonic-gate ip_offline, 2317c478bd9Sstevel@tonic-gate ip_undo_offline, 2327c478bd9Sstevel@tonic-gate ip_remove, 2337c478bd9Sstevel@tonic-gate NULL, 2347c478bd9Sstevel@tonic-gate NULL, 2357c478bd9Sstevel@tonic-gate ip_notify_event 2367c478bd9Sstevel@tonic-gate }; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * rcm_mod_init() - Update registrations, and return the ops structure. 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate struct rcm_mod_ops * 2427c478bd9Sstevel@tonic-gate rcm_mod_init(void) 2437c478bd9Sstevel@tonic-gate { 244d4d1f7bfSVasumathi Sundaram - Sun Microsystems char errmsg[DLADM_STRSIZE]; 245d4d1f7bfSVasumathi Sundaram - Sun Microsystems dladm_status_t status; 2466e91bba0SGirish Moodalbail ipadm_status_t iph_status; 247d4d1f7bfSVasumathi Sundaram - Sun Microsystems 2487c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: mod_init\n"); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate cache_head.ip_next = &cache_tail; 2517c478bd9Sstevel@tonic-gate cache_head.ip_prev = NULL; 2527c478bd9Sstevel@tonic-gate cache_tail.ip_prev = &cache_head; 2537c478bd9Sstevel@tonic-gate cache_tail.ip_next = NULL; 2547c478bd9Sstevel@tonic-gate (void) mutex_init(&cache_lock, NULL, NULL); 2557c478bd9Sstevel@tonic-gate 256d4d1f7bfSVasumathi Sundaram - Sun Microsystems if ((status = dladm_open(&dld_handle)) != DLADM_STATUS_OK) { 257d4d1f7bfSVasumathi Sundaram - Sun Microsystems rcm_log_message(RCM_WARNING, 258d4d1f7bfSVasumathi Sundaram - Sun Microsystems "IP: mod_init failed: cannot get datalink handle: %s\n", 259d4d1f7bfSVasumathi Sundaram - Sun Microsystems dladm_status2str(status, errmsg)); 260d4d1f7bfSVasumathi Sundaram - Sun Microsystems return (NULL); 261d4d1f7bfSVasumathi Sundaram - Sun Microsystems } 2624ac67f02SAnurag S. Maskey 2636e91bba0SGirish Moodalbail if ((iph_status = ipadm_open(&ip_handle, 0)) != IPADM_SUCCESS) { 2646e91bba0SGirish Moodalbail rcm_log_message(RCM_ERROR, 2656e91bba0SGirish Moodalbail "IP: mod_init failed: cannot get IP handle: %s\n", 2666e91bba0SGirish Moodalbail ipadm_status2str(iph_status)); 2676e91bba0SGirish Moodalbail dladm_close(dld_handle); 2686e91bba0SGirish Moodalbail dld_handle = NULL; 2696e91bba0SGirish Moodalbail return (NULL); 2706e91bba0SGirish Moodalbail } 2716e91bba0SGirish Moodalbail 2727c478bd9Sstevel@tonic-gate /* Return the ops vectors */ 2737c478bd9Sstevel@tonic-gate return (&ip_ops); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * rcm_mod_info() - Return a string describing this module. 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate const char * 2807c478bd9Sstevel@tonic-gate rcm_mod_info(void) 2817c478bd9Sstevel@tonic-gate { 2827c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: mod_info\n"); 2837c478bd9Sstevel@tonic-gate 284648495d6Svikram return ("IP Multipathing module version 1.23"); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate /* 2887c478bd9Sstevel@tonic-gate * rcm_mod_fini() - Destroy the network interfaces cache. 2897c478bd9Sstevel@tonic-gate */ 2907c478bd9Sstevel@tonic-gate int 2917c478bd9Sstevel@tonic-gate rcm_mod_fini(void) 2927c478bd9Sstevel@tonic-gate { 2937c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: mod_fini\n"); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate free_cache(); 2967c478bd9Sstevel@tonic-gate (void) mutex_destroy(&cache_lock); 2974ac67f02SAnurag S. Maskey 2984ac67f02SAnurag S. Maskey dladm_close(dld_handle); 2996e91bba0SGirish Moodalbail ipadm_close(ip_handle); 3007c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate /* 3047c478bd9Sstevel@tonic-gate * ip_register() - Make sure the cache is properly sync'ed, and its 3057c478bd9Sstevel@tonic-gate * registrations are in order. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate static int 3087c478bd9Sstevel@tonic-gate ip_register(rcm_handle_t *hd) 3097c478bd9Sstevel@tonic-gate { 3107c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: register\n"); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 3137c478bd9Sstevel@tonic-gate assert(hd != NULL); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (update_cache(hd) < 0) 3167c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate /* 3197c478bd9Sstevel@tonic-gate * Need to register interest in all new resources 3207c478bd9Sstevel@tonic-gate * getting attached, so we get attach event notifications 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate if (!events_registered) { 323d62bc4baSyz147064 if (rcm_register_event(hd, RCM_RESOURCE_LINK_NEW, 0, NULL) 3247c478bd9Sstevel@tonic-gate != RCM_SUCCESS) { 3257c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 3267c478bd9Sstevel@tonic-gate _("IP: failed to register %s\n"), 327d62bc4baSyz147064 RCM_RESOURCE_LINK_NEW); 3287c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3297c478bd9Sstevel@tonic-gate } else { 3307c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "IP: registered %s\n", 331d62bc4baSyz147064 RCM_RESOURCE_LINK_NEW); 3327c478bd9Sstevel@tonic-gate events_registered++; 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * ip_unregister() - Walk the cache, unregistering all the networks. 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate static int 3437c478bd9Sstevel@tonic-gate ip_unregister(rcm_handle_t *hd) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate ip_cache_t *probe; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: unregister\n"); 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 3507c478bd9Sstevel@tonic-gate assert(hd != NULL); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* Walk the cache, unregistering everything */ 3537c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 3547c478bd9Sstevel@tonic-gate probe = cache_head.ip_next; 3557c478bd9Sstevel@tonic-gate while (probe != &cache_tail) { 3567c478bd9Sstevel@tonic-gate if (rcm_unregister_interest(hd, probe->ip_resource, 0) 3577c478bd9Sstevel@tonic-gate != RCM_SUCCESS) { 3587c478bd9Sstevel@tonic-gate /* unregister failed for whatever reason */ 3597c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 3607c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate cache_remove(probe); 3637c478bd9Sstevel@tonic-gate free_node(probe); 3647c478bd9Sstevel@tonic-gate probe = cache_head.ip_next; 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * Need to unregister interest in all new resources 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate if (events_registered) { 372d62bc4baSyz147064 if (rcm_unregister_event(hd, RCM_RESOURCE_LINK_NEW, 0) 3737c478bd9Sstevel@tonic-gate != RCM_SUCCESS) { 3747c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 3757c478bd9Sstevel@tonic-gate _("IP: failed to unregister %s\n"), 376d62bc4baSyz147064 RCM_RESOURCE_LINK_NEW); 3777c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 3787c478bd9Sstevel@tonic-gate } else { 3797c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "IP: unregistered %s\n", 380d62bc4baSyz147064 RCM_RESOURCE_LINK_NEW); 3817c478bd9Sstevel@tonic-gate events_registered--; 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* 3897c478bd9Sstevel@tonic-gate * ip_offline() - Offline an interface. 3907c478bd9Sstevel@tonic-gate */ 3917c478bd9Sstevel@tonic-gate static int 3927c478bd9Sstevel@tonic-gate ip_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 3937c478bd9Sstevel@tonic-gate char **errorp, rcm_info_t **depend_info) 3947c478bd9Sstevel@tonic-gate { 3957c478bd9Sstevel@tonic-gate ip_cache_t *node; 3967c478bd9Sstevel@tonic-gate ip_pif_t *pif; 397e11c3f44Smeem boolean_t detachable = B_FALSE; 398e11c3f44Smeem boolean_t ipmp; 399e11c3f44Smeem int retval; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: offline(%s)\n", rsrc); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 4047c478bd9Sstevel@tonic-gate assert(hd != NULL); 4057c478bd9Sstevel@tonic-gate assert(rsrc != NULL); 4067c478bd9Sstevel@tonic-gate assert(id == (id_t)0); 4077c478bd9Sstevel@tonic-gate assert(errorp != NULL); 4087c478bd9Sstevel@tonic-gate assert(depend_info != NULL); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* Lock the cache and lookup the resource */ 4117c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 4127c478bd9Sstevel@tonic-gate node = cache_lookup(hd, rsrc, CACHE_REFRESH); 4137c478bd9Sstevel@tonic-gate if (node == NULL) { 4147c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, "Unrecognized resource"); 4157c478bd9Sstevel@tonic-gate errno = ENOENT; 4167c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 4177c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate pif = node->ip_pif; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* Establish default detachability criteria */ 423e11c3f44Smeem if (flags & RCM_FORCE) 424e11c3f44Smeem detachable = B_TRUE; 4257c478bd9Sstevel@tonic-gate 426e11c3f44Smeem /* Check if the interface is under IPMP */ 427e11c3f44Smeem ipmp = (pif->pi_grname[0] != '\0'); 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate /* 430e11c3f44Smeem * Even if the interface is not under IPMP, it's possible that it's 431e11c3f44Smeem * still okay to offline it as long as there are higher-level failover 432e11c3f44Smeem * mechanisms for the addresses it owns (e.g., clustering). In this 433e11c3f44Smeem * case, ip_offlinelist() will return RCM_SUCCESS, and we charge on. 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate if (!ipmp && !detachable) { 4367c478bd9Sstevel@tonic-gate /* Inform consumers of IP addresses being offlined */ 4377c478bd9Sstevel@tonic-gate if (ip_offlinelist(hd, node, errorp, flags, depend_info) == 4387c478bd9Sstevel@tonic-gate RCM_SUCCESS) { 4397c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, 4407c478bd9Sstevel@tonic-gate "IP: consumers agree on detach"); 4417c478bd9Sstevel@tonic-gate } else { 4427c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, 4437c478bd9Sstevel@tonic-gate "Device consumers prohibit offline"); 4447c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 4457c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate /* Check if it's a query */ 4507c478bd9Sstevel@tonic-gate if (flags & RCM_QUERY) { 4517c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: offline query success(%s)\n", 4527c478bd9Sstevel@tonic-gate rsrc); 4537c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 4547c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate /* Check detachability, save configuration if detachable */ 4587c478bd9Sstevel@tonic-gate if (if_cfginfo(node, (flags & RCM_FORCE)) < 0) { 4597c478bd9Sstevel@tonic-gate node->ip_cachestate |= CACHE_IF_IGNORE; 4607c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: Ignoring node(%s)\n", rsrc); 4617c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 4627c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* standalone detachable device */ 4667c478bd9Sstevel@tonic-gate if (!ipmp) { 4677c478bd9Sstevel@tonic-gate if (if_unplumb(node) < 0) { 4687c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, 4697c478bd9Sstevel@tonic-gate "Failed to unplumb the device"); 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate errno = EIO; 4727c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 4737c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate node->ip_cachestate |= CACHE_IF_OFFLINED; 4777c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: Offline success(%s)\n", rsrc); 4787c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 4797c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* 483e11c3f44Smeem * This is an IPMP interface that can be offlined. 484e11c3f44Smeem * Request in.mpathd(1M) to offline the physical interface. 4857c478bd9Sstevel@tonic-gate */ 486e11c3f44Smeem if ((retval = ip_ipmp_offline(node)) != IPMP_SUCCESS) 487e11c3f44Smeem ip_log_err(node, errorp, "in.mpathd offline failed"); 4887c478bd9Sstevel@tonic-gate 489e11c3f44Smeem if (retval == IPMP_EMINRED && !detachable) { 4907c478bd9Sstevel@tonic-gate /* 491e11c3f44Smeem * in.mpathd(1M) could not offline the device because it was 492e11c3f44Smeem * the last interface in the group. However, it's possible 493e11c3f44Smeem * that it's still okay to offline it as long as there are 494e11c3f44Smeem * higher-level failover mechanisms for the addresses it owns 495e11c3f44Smeem * (e.g., clustering). In this case, ip_offlinelist() will 496e11c3f44Smeem * return RCM_SUCCESS, and we charge on. 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate /* Inform consumers of IP addresses being offlined */ 4997c478bd9Sstevel@tonic-gate if (ip_offlinelist(hd, node, errorp, flags, 5007c478bd9Sstevel@tonic-gate depend_info) == RCM_SUCCESS) { 5017c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, 5027c478bd9Sstevel@tonic-gate "IP: consumers agree on detach"); 5037c478bd9Sstevel@tonic-gate } else { 5047c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, 5057c478bd9Sstevel@tonic-gate "Device consumers prohibit offline"); 5067c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5077c478bd9Sstevel@tonic-gate errno = EBUSY; 5087c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate if (if_unplumb(node) < 0) { 5137c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 5147c478bd9Sstevel@tonic-gate _("IP: Unplumb failed (%s)\n"), 5157c478bd9Sstevel@tonic-gate pif->pi_ifname); 5167c478bd9Sstevel@tonic-gate 517e11c3f44Smeem /* Request in.mpathd to undo the offline */ 518e11c3f44Smeem if (ip_ipmp_undo_offline(node) != IPMP_SUCCESS) { 5197c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, "Undo offline failed"); 5207c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5217c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5247c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 5257c478bd9Sstevel@tonic-gate } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate node->ip_cachestate |= CACHE_IF_OFFLINED; 5287c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: offline success(%s)\n", rsrc); 5297c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5307c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate /* 5347c478bd9Sstevel@tonic-gate * ip_undo_offline() - Undo offline of a previously offlined device. 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5377c478bd9Sstevel@tonic-gate static int 5387c478bd9Sstevel@tonic-gate ip_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 5397c478bd9Sstevel@tonic-gate char **errorp, rcm_info_t **depend_info) 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate ip_cache_t *node; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: online(%s)\n", rsrc); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 5467c478bd9Sstevel@tonic-gate assert(hd != NULL); 5477c478bd9Sstevel@tonic-gate assert(rsrc != NULL); 5487c478bd9Sstevel@tonic-gate assert(id == (id_t)0); 5497c478bd9Sstevel@tonic-gate assert(errorp != NULL); 5507c478bd9Sstevel@tonic-gate assert(depend_info != NULL); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 5537c478bd9Sstevel@tonic-gate node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate if (node == NULL) { 5567c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, "No such device"); 5577c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5587c478bd9Sstevel@tonic-gate errno = ENOENT; 5597c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate /* Check if no attempt should be made to online the device here */ 5637c478bd9Sstevel@tonic-gate if (node->ip_cachestate & CACHE_IF_IGNORE) { 5647c478bd9Sstevel@tonic-gate node->ip_cachestate &= ~(CACHE_IF_IGNORE); 5657c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5667c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate /* Check if the interface was previously offlined */ 5707c478bd9Sstevel@tonic-gate if (!(node->ip_cachestate & CACHE_IF_OFFLINED)) { 5717c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, "Device not offlined"); 5727c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5737c478bd9Sstevel@tonic-gate errno = ENOTSUP; 5747c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (if_replumb(node) == -1) { 5787c478bd9Sstevel@tonic-gate /* re-plumb failed */ 5797c478bd9Sstevel@tonic-gate ip_log_err(node, errorp, "Replumb failed"); 5807c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5817c478bd9Sstevel@tonic-gate errno = EIO; 5827c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate /* Inform consumers about IP addresses being un-offlined */ 5877c478bd9Sstevel@tonic-gate (void) ip_onlinelist(hd, node, errorp, flags, depend_info); 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate node->ip_cachestate &= ~(CACHE_IF_OFFLINED); 5907c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: online success(%s)\n", rsrc); 5917c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 5927c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate /* 5967c478bd9Sstevel@tonic-gate * ip_get_info() - Gather usage information for this resource. 5977c478bd9Sstevel@tonic-gate */ 5987c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5997c478bd9Sstevel@tonic-gate int 6007c478bd9Sstevel@tonic-gate ip_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 6017c478bd9Sstevel@tonic-gate char **usagep, char **errorp, nvlist_t *props, rcm_info_t **depend_info) 6027c478bd9Sstevel@tonic-gate { 6037c478bd9Sstevel@tonic-gate ip_cache_t *node; 6047c478bd9Sstevel@tonic-gate char *infostr; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 6077c478bd9Sstevel@tonic-gate assert(hd != NULL); 6087c478bd9Sstevel@tonic-gate assert(rsrc != NULL); 6097c478bd9Sstevel@tonic-gate assert(id == (id_t)0); 6107c478bd9Sstevel@tonic-gate assert(usagep != NULL); 6117c478bd9Sstevel@tonic-gate assert(errorp != NULL); 6127c478bd9Sstevel@tonic-gate assert(depend_info != NULL); 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: get_info(%s)\n", rsrc); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 6177c478bd9Sstevel@tonic-gate node = cache_lookup(hd, rsrc, CACHE_REFRESH); 6187c478bd9Sstevel@tonic-gate if (!node) { 6197c478bd9Sstevel@tonic-gate rcm_log_message(RCM_INFO, 6207c478bd9Sstevel@tonic-gate _("IP: get_info(%s) unrecognized resource\n"), rsrc); 6217c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 6227c478bd9Sstevel@tonic-gate errno = ENOENT; 6237c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate infostr = ip_usage(node); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate if (infostr == NULL) { 6297c478bd9Sstevel@tonic-gate /* most likely malloc failure */ 6307c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 6317c478bd9Sstevel@tonic-gate _("IP: get_info(%s) malloc failure\n"), rsrc); 6327c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 6337c478bd9Sstevel@tonic-gate errno = ENOMEM; 6347c478bd9Sstevel@tonic-gate *errorp = NULL; 6357c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate /* Set client/role properties */ 6397c478bd9Sstevel@tonic-gate (void) nvlist_add_string(props, RCM_CLIENT_NAME, "IP"); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate /* Set usage property, infostr will be freed by caller */ 6427c478bd9Sstevel@tonic-gate *usagep = infostr; 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: get_info(%s) info = %s \n", 6457c478bd9Sstevel@tonic-gate rsrc, infostr); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 6487c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate /* 6527c478bd9Sstevel@tonic-gate * ip_suspend() - Nothing to do, always okay 6537c478bd9Sstevel@tonic-gate */ 6547c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6557c478bd9Sstevel@tonic-gate static int 6567c478bd9Sstevel@tonic-gate ip_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval, 6577c478bd9Sstevel@tonic-gate uint_t flags, char **errorp, rcm_info_t **depend_info) 6587c478bd9Sstevel@tonic-gate { 6597c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 6607c478bd9Sstevel@tonic-gate assert(hd != NULL); 6617c478bd9Sstevel@tonic-gate assert(rsrc != NULL); 6627c478bd9Sstevel@tonic-gate assert(id == (id_t)0); 6637c478bd9Sstevel@tonic-gate assert(interval != NULL); 6647c478bd9Sstevel@tonic-gate assert(errorp != NULL); 6657c478bd9Sstevel@tonic-gate assert(depend_info != NULL); 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: suspend(%s)\n", rsrc); 6687c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * ip_resume() - Nothing to do, always okay 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6757c478bd9Sstevel@tonic-gate static int 6767c478bd9Sstevel@tonic-gate ip_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 6777c478bd9Sstevel@tonic-gate char **errorp, rcm_info_t ** depend_info) 6787c478bd9Sstevel@tonic-gate { 6797c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 6807c478bd9Sstevel@tonic-gate assert(hd != NULL); 6817c478bd9Sstevel@tonic-gate assert(rsrc != NULL); 6827c478bd9Sstevel@tonic-gate assert(id == (id_t)0); 6837c478bd9Sstevel@tonic-gate assert(errorp != NULL); 6847c478bd9Sstevel@tonic-gate assert(depend_info != NULL); 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: resume(%s)\n", rsrc); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate /* 6927c478bd9Sstevel@tonic-gate * ip_remove() - remove a resource from cache 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6957c478bd9Sstevel@tonic-gate static int 6967c478bd9Sstevel@tonic-gate ip_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 6977c478bd9Sstevel@tonic-gate char **errorp, rcm_info_t **depend_info) 6987c478bd9Sstevel@tonic-gate { 6997c478bd9Sstevel@tonic-gate ip_cache_t *node; 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate /* Guard against bad arguments */ 7027c478bd9Sstevel@tonic-gate assert(hd != NULL); 7037c478bd9Sstevel@tonic-gate assert(rsrc != NULL); 7047c478bd9Sstevel@tonic-gate assert(id == (id_t)0); 7057c478bd9Sstevel@tonic-gate assert(errorp != NULL); 7067c478bd9Sstevel@tonic-gate assert(depend_info != NULL); 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: remove(%s)\n", rsrc); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 7117c478bd9Sstevel@tonic-gate node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 7127c478bd9Sstevel@tonic-gate if (!node) { 7137c478bd9Sstevel@tonic-gate rcm_log_message(RCM_INFO, 7147c478bd9Sstevel@tonic-gate _("IP: remove(%s) unrecognized resource\n"), rsrc); 7157c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 7167c478bd9Sstevel@tonic-gate errno = ENOENT; 7177c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate /* remove the cached entry for the resource */ 7217c478bd9Sstevel@tonic-gate cache_remove(node); 722392b1d6eSyz147064 free_node(node); 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 7257c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate /* 7297c478bd9Sstevel@tonic-gate * ip_notify_event - Project private implementation to receive new resource 7307c478bd9Sstevel@tonic-gate * events. It intercepts all new resource events. If the 7317c478bd9Sstevel@tonic-gate * new resource is a network resource, pass up a notify 7327c478bd9Sstevel@tonic-gate * for it too. The new resource need not be cached, since 7337c478bd9Sstevel@tonic-gate * it is done at register again. 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7367c478bd9Sstevel@tonic-gate static int 7377c478bd9Sstevel@tonic-gate ip_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 7387c478bd9Sstevel@tonic-gate char **errorp, nvlist_t *nvl, rcm_info_t **depend_info) 7397c478bd9Sstevel@tonic-gate { 740d62bc4baSyz147064 datalink_id_t linkid; 741d62bc4baSyz147064 nvpair_t *nvp = NULL; 742d62bc4baSyz147064 uint64_t id64; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate assert(hd != NULL); 7457c478bd9Sstevel@tonic-gate assert(rsrc != NULL); 7467c478bd9Sstevel@tonic-gate assert(id == (id_t)0); 7477c478bd9Sstevel@tonic-gate assert(nvl != NULL); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: notify_event(%s)\n", rsrc); 7507c478bd9Sstevel@tonic-gate 751d62bc4baSyz147064 if (!STREQ(rsrc, RCM_RESOURCE_LINK_NEW)) { 7527c478bd9Sstevel@tonic-gate rcm_log_message(RCM_INFO, 7537c478bd9Sstevel@tonic-gate _("IP: unrecognized event for %s\n"), rsrc); 7547c478bd9Sstevel@tonic-gate ip_log_err(NULL, errorp, "unrecognized event"); 7557c478bd9Sstevel@tonic-gate errno = EINVAL; 7567c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* Update cache to reflect latest interfaces */ 7607c478bd9Sstevel@tonic-gate if (update_cache(hd) < 0) { 7617c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: update_cache failed\n")); 7627c478bd9Sstevel@tonic-gate ip_log_err(NULL, errorp, "Private Cache update failed"); 7637c478bd9Sstevel@tonic-gate return (RCM_FAILURE); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 766d62bc4baSyz147064 rcm_log_message(RCM_TRACE1, "IP: process_nvlist\n"); 767d62bc4baSyz147064 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 768d62bc4baSyz147064 if (STREQ(nvpair_name(nvp), RCM_NV_LINKID)) { 769d62bc4baSyz147064 if (nvpair_value_uint64(nvp, &id64) != 0) { 7707c478bd9Sstevel@tonic-gate rcm_log_message(RCM_WARNING, 771d62bc4baSyz147064 _("IP: cannot get linkid\n")); 772d62bc4baSyz147064 return (RCM_FAILURE); 7737c478bd9Sstevel@tonic-gate } 774d62bc4baSyz147064 linkid = (datalink_id_t)id64; 7756e91bba0SGirish Moodalbail /* 7766e91bba0SGirish Moodalbail * Grovel through /etc/hostname* files and configure 7776e91bba0SGirish Moodalbail * interface in the same way that they would be handled 7786e91bba0SGirish Moodalbail * by network/physical. 7796e91bba0SGirish Moodalbail */ 7806e91bba0SGirish Moodalbail if (if_configure_hostname(linkid) != 0) { 7816e91bba0SGirish Moodalbail rcm_log_message(RCM_ERROR, 7826e91bba0SGirish Moodalbail _("IP: Configuration failed (%u)\n"), 7836e91bba0SGirish Moodalbail linkid); 7846e91bba0SGirish Moodalbail ip_log_err(NULL, errorp, 7856e91bba0SGirish Moodalbail "Failed configuring one or more IP " 7866e91bba0SGirish Moodalbail "addresses"); 7876e91bba0SGirish Moodalbail } 7886e91bba0SGirish Moodalbail 7896e91bba0SGirish Moodalbail /* 7906e91bba0SGirish Moodalbail * Query libipadm for persistent configuration info 7916e91bba0SGirish Moodalbail * and resurrect that persistent configuration. 7926e91bba0SGirish Moodalbail */ 7936e91bba0SGirish Moodalbail if (if_configure_ipadm(linkid) != 0) { 7947c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 795d62bc4baSyz147064 _("IP: Configuration failed (%u)\n"), 796d62bc4baSyz147064 linkid); 7977c478bd9Sstevel@tonic-gate ip_log_err(NULL, errorp, 798d62bc4baSyz147064 "Failed configuring one or more IP " 799d62bc4baSyz147064 "addresses"); 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate 802d62bc4baSyz147064 /* Notify all IP address consumers */ 803d62bc4baSyz147064 ip_consumer_notify(hd, linkid, errorp, flags, 8047c478bd9Sstevel@tonic-gate depend_info); 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, 8097c478bd9Sstevel@tonic-gate "IP: notify_event: device configuration complete\n"); 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* 8157c478bd9Sstevel@tonic-gate * ip_usage - Determine the usage of a device. Call with cache_lock held. 8167c478bd9Sstevel@tonic-gate * The returned buffer is owned by caller, and the caller 8177c478bd9Sstevel@tonic-gate * must free it up when done. 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate static char * 8207c478bd9Sstevel@tonic-gate ip_usage(ip_cache_t *node) 8217c478bd9Sstevel@tonic-gate { 8227c478bd9Sstevel@tonic-gate ip_lif_t *lif; 823e11c3f44Smeem uint_t numup; 824e11c3f44Smeem char *sep, *buf, *linkidstr; 825d62bc4baSyz147064 datalink_id_t linkid; 826e11c3f44Smeem const char *msg; 827d62bc4baSyz147064 char link[MAXLINKNAMELEN]; 8287c478bd9Sstevel@tonic-gate char addrstr[INET6_ADDRSTRLEN]; 829d62bc4baSyz147064 char errmsg[DLADM_STRSIZE]; 830d62bc4baSyz147064 dladm_status_t status; 831e11c3f44Smeem boolean_t offline, ipmp; 832e11c3f44Smeem size_t bufsz = 0; 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: usage(%s)\n", node->ip_resource); 8357c478bd9Sstevel@tonic-gate 836d62bc4baSyz147064 /* 837d62bc4baSyz147064 * Note that node->ip_resource is in the form of SUNW_datalink/<linkid> 838d62bc4baSyz147064 */ 839d62bc4baSyz147064 linkidstr = strchr(node->ip_resource, '/'); 840d62bc4baSyz147064 assert(linkidstr != NULL); 841d62bc4baSyz147064 linkidstr = linkidstr ? linkidstr + 1 : node->ip_resource; 842d62bc4baSyz147064 843d62bc4baSyz147064 errno = 0; 844d62bc4baSyz147064 linkid = strtol(linkidstr, &buf, 10); 845d62bc4baSyz147064 if (errno != 0 || *buf != '\0') { 846d62bc4baSyz147064 rcm_log_message(RCM_ERROR, 847d62bc4baSyz147064 _("IP: usage(%s) parse linkid failure (%s)\n"), 848d62bc4baSyz147064 node->ip_resource, strerror(errno)); 849d62bc4baSyz147064 return (NULL); 850d62bc4baSyz147064 } 851d62bc4baSyz147064 8524ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(dld_handle, linkid, NULL, NULL, 8534ac67f02SAnurag S. Maskey NULL, link, sizeof (link))) != DLADM_STATUS_OK) { 854d62bc4baSyz147064 rcm_log_message(RCM_ERROR, 855d62bc4baSyz147064 _("IP: usage(%s) get link name failure(%s)\n"), 856d62bc4baSyz147064 node->ip_resource, dladm_status2str(status, errmsg)); 857d62bc4baSyz147064 return (NULL); 858d62bc4baSyz147064 } 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* TRANSLATION_NOTE: separator used between IP addresses */ 8617c478bd9Sstevel@tonic-gate sep = _(", "); 8627c478bd9Sstevel@tonic-gate 863e11c3f44Smeem numup = 0; 864e11c3f44Smeem for (lif = node->ip_pif->pi_lifs; lif != NULL; lif = lif->li_next) 865e11c3f44Smeem if (lif->li_ifflags & IFF_UP) 866e11c3f44Smeem numup++; 8677c478bd9Sstevel@tonic-gate 868e11c3f44Smeem ipmp = (node->ip_pif->pi_grname[0] != '\0'); 869e11c3f44Smeem offline = ((node->ip_cachestate & CACHE_IF_OFFLINED) != 0); 8707c478bd9Sstevel@tonic-gate 871e11c3f44Smeem if (offline) { 872e11c3f44Smeem msg = _("offlined"); 873e11c3f44Smeem } else if (numup == 0) { 874e11c3f44Smeem msg = _("plumbed but down"); 8757c478bd9Sstevel@tonic-gate } else { 876e11c3f44Smeem if (ipmp) { 877e11c3f44Smeem msg = _("providing connectivity for IPMP group "); 878e11c3f44Smeem bufsz += LIFGRNAMSIZ; 879e11c3f44Smeem } else { 880e11c3f44Smeem msg = _("hosts IP addresses: "); 881e11c3f44Smeem bufsz += (numup * (INET6_ADDRSTRLEN + strlen(sep))); 882e11c3f44Smeem } 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate 885e11c3f44Smeem bufsz += strlen(link) + strlen(msg) + 1; 8867c478bd9Sstevel@tonic-gate if ((buf = malloc(bufsz)) == NULL) { 8877c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 8887c478bd9Sstevel@tonic-gate _("IP: usage(%s) malloc failure(%s)\n"), 8897c478bd9Sstevel@tonic-gate node->ip_resource, strerror(errno)); 8907c478bd9Sstevel@tonic-gate return (NULL); 8917c478bd9Sstevel@tonic-gate } 892e11c3f44Smeem (void) snprintf(buf, bufsz, "%s: %s", link, msg); 8937c478bd9Sstevel@tonic-gate 894e11c3f44Smeem if (!offline && numup > 0) { 895e11c3f44Smeem if (ipmp) { 896e11c3f44Smeem (void) strlcat(buf, node->ip_pif->pi_grname, bufsz); 897e11c3f44Smeem } else { 898e11c3f44Smeem lif = node->ip_pif->pi_lifs; 899e11c3f44Smeem for (; lif != NULL; lif = lif->li_next) { 900e11c3f44Smeem if (!(lif->li_ifflags & IFF_UP)) 901e11c3f44Smeem continue; 902e11c3f44Smeem 903e11c3f44Smeem if (!ip_addrstr(lif, addrstr, sizeof (addrstr))) 904e11c3f44Smeem continue; 905e11c3f44Smeem 906e11c3f44Smeem (void) strlcat(buf, addrstr, bufsz); 907e11c3f44Smeem if (--numup > 0) 908e11c3f44Smeem (void) strlcat(buf, sep, bufsz); 909e11c3f44Smeem } 910e11c3f44Smeem } 911e11c3f44Smeem } 912e11c3f44Smeem 9137c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: usage (%s) info = %s\n", 9147c478bd9Sstevel@tonic-gate node->ip_resource, buf); 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate return (buf); 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 919e11c3f44Smeem static boolean_t 920e11c3f44Smeem ip_addrstr(ip_lif_t *lif, char *addrstr, size_t addrsize) 921e11c3f44Smeem { 922e11c3f44Smeem int af = lif->li_addr.family; 9237c478bd9Sstevel@tonic-gate void *addr; 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate if (af == AF_INET6) { 9267c478bd9Sstevel@tonic-gate addr = &lif->li_addr.ip6.sin6_addr; 9277c478bd9Sstevel@tonic-gate } else if (af == AF_INET) { 9287c478bd9Sstevel@tonic-gate addr = &lif->li_addr.ip4.sin_addr; 9297c478bd9Sstevel@tonic-gate } else { 9307c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, 931e11c3f44Smeem "IP: unknown addr family %d, assuming AF_INET\n", af); 9327c478bd9Sstevel@tonic-gate af = AF_INET; 9337c478bd9Sstevel@tonic-gate addr = &lif->li_addr.ip4.sin_addr; 9347c478bd9Sstevel@tonic-gate } 935e11c3f44Smeem if (inet_ntop(af, addr, addrstr, addrsize) == NULL) { 9367c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 9377c478bd9Sstevel@tonic-gate _("IP: inet_ntop: %s\n"), strerror(errno)); 938e11c3f44Smeem return (B_FALSE); 9397c478bd9Sstevel@tonic-gate } 940e11c3f44Smeem 9417c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "IP addr := %s\n", addrstr); 942e11c3f44Smeem return (B_TRUE); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate /* 9467c478bd9Sstevel@tonic-gate * Cache management routines, all cache management functions should be 9477c478bd9Sstevel@tonic-gate * be called with cache_lock held. 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* 951d62bc4baSyz147064 * cache_lookup() - Get a cache node for a resource. 9527c478bd9Sstevel@tonic-gate * Call with cache lock held. 9537c478bd9Sstevel@tonic-gate * 9547c478bd9Sstevel@tonic-gate * This ensures that the cache is consistent with the system state and 9557c478bd9Sstevel@tonic-gate * returns a pointer to the cache element corresponding to the resource. 9567c478bd9Sstevel@tonic-gate */ 9577c478bd9Sstevel@tonic-gate static ip_cache_t * 9587c478bd9Sstevel@tonic-gate cache_lookup(rcm_handle_t *hd, char *rsrc, char options) 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate ip_cache_t *probe; 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: cache lookup(%s)\n", rsrc); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate if ((options & CACHE_REFRESH) && (hd != NULL)) { 9657c478bd9Sstevel@tonic-gate /* drop lock since update locks cache again */ 9667c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 9677c478bd9Sstevel@tonic-gate (void) update_cache(hd); 9687c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate probe = cache_head.ip_next; 9727c478bd9Sstevel@tonic-gate while (probe != &cache_tail) { 9737c478bd9Sstevel@tonic-gate if (probe->ip_resource && 974d62bc4baSyz147064 STREQ(rsrc, probe->ip_resource)) { 9757c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, 9767c478bd9Sstevel@tonic-gate "IP: cache lookup success(%s)\n", rsrc); 9777c478bd9Sstevel@tonic-gate return (probe); 9787c478bd9Sstevel@tonic-gate } 9797c478bd9Sstevel@tonic-gate probe = probe->ip_next; 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate return (NULL); 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate /* 9857c478bd9Sstevel@tonic-gate * free_node - Free a node from the cache 9867c478bd9Sstevel@tonic-gate * Call with cache_lock held. 9877c478bd9Sstevel@tonic-gate */ 9887c478bd9Sstevel@tonic-gate static void 9897c478bd9Sstevel@tonic-gate free_node(ip_cache_t *node) 9907c478bd9Sstevel@tonic-gate { 9917c478bd9Sstevel@tonic-gate ip_pif_t *pif; 9927c478bd9Sstevel@tonic-gate ip_lif_t *lif, *tmplif; 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate if (node) { 9957c478bd9Sstevel@tonic-gate if (node->ip_resource) { 9967c478bd9Sstevel@tonic-gate free(node->ip_resource); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate /* free the pif */ 10007c478bd9Sstevel@tonic-gate pif = node->ip_pif; 10017c478bd9Sstevel@tonic-gate if (pif) { 10027c478bd9Sstevel@tonic-gate /* free logical interfaces */ 10037c478bd9Sstevel@tonic-gate lif = pif->pi_lifs; 10047c478bd9Sstevel@tonic-gate while (lif) { 10057c478bd9Sstevel@tonic-gate tmplif = lif->li_next; 10067c478bd9Sstevel@tonic-gate free(lif); 10077c478bd9Sstevel@tonic-gate lif = tmplif; 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate free(pif); 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate free(node); 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate /* 10167c478bd9Sstevel@tonic-gate * cache_insert - Insert a resource node in cache 10177c478bd9Sstevel@tonic-gate * Call with the cache_lock held. 10187c478bd9Sstevel@tonic-gate */ 10197c478bd9Sstevel@tonic-gate static void 10207c478bd9Sstevel@tonic-gate cache_insert(ip_cache_t *node) 10217c478bd9Sstevel@tonic-gate { 1022d62bc4baSyz147064 rcm_log_message(RCM_TRACE2, "IP: cache insert(%s)\n", 1023d62bc4baSyz147064 node->ip_resource); 1024d62bc4baSyz147064 10257c478bd9Sstevel@tonic-gate /* insert at the head for best performance */ 10267c478bd9Sstevel@tonic-gate node->ip_next = cache_head.ip_next; 10277c478bd9Sstevel@tonic-gate node->ip_prev = &cache_head; 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate node->ip_next->ip_prev = node; 10307c478bd9Sstevel@tonic-gate node->ip_prev->ip_next = node; 10317c478bd9Sstevel@tonic-gate } 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate /* 10347c478bd9Sstevel@tonic-gate * cache_remove() - Remove a resource node from cache. 10357c478bd9Sstevel@tonic-gate * Call with the cache_lock held. 10367c478bd9Sstevel@tonic-gate */ 10377c478bd9Sstevel@tonic-gate static void 10387c478bd9Sstevel@tonic-gate cache_remove(ip_cache_t *node) 10397c478bd9Sstevel@tonic-gate { 1040d62bc4baSyz147064 rcm_log_message(RCM_TRACE2, "IP: cache remove(%s)\n", 1041d62bc4baSyz147064 node->ip_resource); 1042d62bc4baSyz147064 10437c478bd9Sstevel@tonic-gate node->ip_next->ip_prev = node->ip_prev; 10447c478bd9Sstevel@tonic-gate node->ip_prev->ip_next = node->ip_next; 10457c478bd9Sstevel@tonic-gate node->ip_next = NULL; 10467c478bd9Sstevel@tonic-gate node->ip_prev = NULL; 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate /* 10507c478bd9Sstevel@tonic-gate * update_pif() - Update physical interface properties 10517c478bd9Sstevel@tonic-gate * Call with cache_lock held 10527c478bd9Sstevel@tonic-gate */ 10536e91bba0SGirish Moodalbail int 10546e91bba0SGirish Moodalbail update_pif(rcm_handle_t *hd, int af, int sock, struct ifaddrs *ifa) 10557c478bd9Sstevel@tonic-gate { 1056d62bc4baSyz147064 char *rsrc; 1057595aa6e4Smeem ifspec_t ifspec; 10587c478bd9Sstevel@tonic-gate ushort_t ifnumber = 0; 10597c478bd9Sstevel@tonic-gate ip_cache_t *probe; 10607c478bd9Sstevel@tonic-gate ip_pif_t pif; 10617c478bd9Sstevel@tonic-gate ip_pif_t *probepif; 10627c478bd9Sstevel@tonic-gate ip_lif_t *probelif; 10637c478bd9Sstevel@tonic-gate struct lifreq lifreq; 10647c478bd9Sstevel@tonic-gate struct sockaddr_storage ifaddr; 10657c478bd9Sstevel@tonic-gate uint64_t ifflags; 10667c478bd9Sstevel@tonic-gate int lif_listed = 0; 10677c478bd9Sstevel@tonic-gate 10686e91bba0SGirish Moodalbail rcm_log_message(RCM_TRACE1, "IP: update_pif(%s)\n", ifa->ifa_name); 10697c478bd9Sstevel@tonic-gate 10706e91bba0SGirish Moodalbail if (!ifparse_ifspec(ifa->ifa_name, &ifspec)) { 1071595aa6e4Smeem rcm_log_message(RCM_ERROR, _("IP: bad network interface: %s\n"), 10726e91bba0SGirish Moodalbail ifa->ifa_name); 10737c478bd9Sstevel@tonic-gate return (-1); 10747c478bd9Sstevel@tonic-gate } 10757c478bd9Sstevel@tonic-gate 1076595aa6e4Smeem (void) snprintf(pif.pi_ifname, sizeof (pif.pi_ifname), "%s%d", 1077595aa6e4Smeem ifspec.ifsp_devnm, ifspec.ifsp_ppa); 1078595aa6e4Smeem if (ifspec.ifsp_lunvalid) 1079595aa6e4Smeem ifnumber = ifspec.ifsp_lun; 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate /* Get the interface flags */ 10826e91bba0SGirish Moodalbail ifflags = ifa->ifa_flags; 10837c478bd9Sstevel@tonic-gate 10848de9d095Syz147064 /* 10858de9d095Syz147064 * Ignore interfaces that are always incapable of DR: 10868de9d095Syz147064 * - IFF_VIRTUAL: e.g., loopback and vni 10878de9d095Syz147064 * - IFF_POINTOPOINT: e.g., sppp and ip.tun 10888de9d095Syz147064 * - !IFF_MULTICAST: e.g., ip.6to4tun 1089e11c3f44Smeem * - IFF_IPMP: IPMP meta-interfaces 10908de9d095Syz147064 * 10918de9d095Syz147064 * Note: The !IFF_MULTICAST check can be removed once iptun is 10928de9d095Syz147064 * implemented as a datalink. 10938de9d095Syz147064 */ 10948de9d095Syz147064 if (!(ifflags & IFF_MULTICAST) || 1095e11c3f44Smeem (ifflags & (IFF_POINTOPOINT | IFF_VIRTUAL | IFF_IPMP))) { 1096595aa6e4Smeem rcm_log_message(RCM_TRACE3, "IP: if ignored (%s)\n", 1097595aa6e4Smeem pif.pi_ifname); 10987c478bd9Sstevel@tonic-gate return (0); 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate /* Get the interface group name for this interface */ 11026e91bba0SGirish Moodalbail bzero(&lifreq, sizeof (lifreq)); 11036e91bba0SGirish Moodalbail (void) strncpy(lifreq.lifr_name, ifa->ifa_name, LIFNAMSIZ); 11046e91bba0SGirish Moodalbail 11057c478bd9Sstevel@tonic-gate if (ioctl(sock, SIOCGLIFGROUPNAME, (char *)&lifreq) < 0) { 1106e11c3f44Smeem if (errno != ENXIO) { 11077c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 11087c478bd9Sstevel@tonic-gate _("IP: SIOCGLIFGROUPNAME(%s): %s\n"), 11097c478bd9Sstevel@tonic-gate lifreq.lifr_name, strerror(errno)); 1110e11c3f44Smeem } 11117c478bd9Sstevel@tonic-gate return (-1); 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate /* copy the group name */ 1115e11c3f44Smeem (void) strlcpy(pif.pi_grname, lifreq.lifr_groupname, 1116e11c3f44Smeem sizeof (pif.pi_grname)); 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate /* Get the interface address for this interface */ 1119*64639aafSDarren Reed (void) memcpy(&ifaddr, ifa->ifa_addr, sizeof (ifaddr)); 11207c478bd9Sstevel@tonic-gate 1121d62bc4baSyz147064 rsrc = get_link_resource(pif.pi_ifname); 1122d62bc4baSyz147064 if (rsrc == NULL) { 1123d62bc4baSyz147064 rcm_log_message(RCM_ERROR, 1124d62bc4baSyz147064 _("IP: get_link_resource(%s) failed\n"), 1125d62bc4baSyz147064 lifreq.lifr_name); 1126d62bc4baSyz147064 return (-1); 1127d62bc4baSyz147064 } 11287c478bd9Sstevel@tonic-gate 1129d62bc4baSyz147064 probe = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 11307c478bd9Sstevel@tonic-gate if (probe != NULL) { 1131d62bc4baSyz147064 free(rsrc); 11327c478bd9Sstevel@tonic-gate probe->ip_cachestate &= ~(CACHE_IF_STALE); 11337c478bd9Sstevel@tonic-gate } else { 11347c478bd9Sstevel@tonic-gate if ((probe = calloc(1, sizeof (ip_cache_t))) == NULL) { 11357c478bd9Sstevel@tonic-gate /* malloc errors are bad */ 1136d62bc4baSyz147064 free(rsrc); 11377c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: calloc: %s\n"), 11387c478bd9Sstevel@tonic-gate strerror(errno)); 11397c478bd9Sstevel@tonic-gate return (-1); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate 1142d62bc4baSyz147064 probe->ip_resource = rsrc; 11437c478bd9Sstevel@tonic-gate probe->ip_pif = NULL; 11447c478bd9Sstevel@tonic-gate probe->ip_ifred = RCM_IPMP_MIN_REDUNDANCY; 11457c478bd9Sstevel@tonic-gate probe->ip_cachestate |= CACHE_IF_NEW; 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate cache_insert(probe); 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate probepif = probe->ip_pif; 11517c478bd9Sstevel@tonic-gate if (probepif != NULL) { 11527c478bd9Sstevel@tonic-gate /* Check if lifs need to be updated */ 11537c478bd9Sstevel@tonic-gate probelif = probepif->pi_lifs; 11547c478bd9Sstevel@tonic-gate while (probelif != NULL) { 11557c478bd9Sstevel@tonic-gate if ((probelif->li_ifnum == ifnumber) && 11567c478bd9Sstevel@tonic-gate (probelif->li_addr.family == ifaddr.ss_family)) { 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, 11597c478bd9Sstevel@tonic-gate "IP: refreshing lifs for %s, ifnum=%d\n", 11607c478bd9Sstevel@tonic-gate pif.pi_ifname, probelif->li_ifnum); 11617c478bd9Sstevel@tonic-gate 11627c478bd9Sstevel@tonic-gate /* refresh lif properties */ 11637c478bd9Sstevel@tonic-gate (void) memcpy(&probelif->li_addr, &ifaddr, 11647c478bd9Sstevel@tonic-gate sizeof (probelif->li_addr)); 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate probelif->li_ifflags = ifflags; 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate lif_listed++; 11697c478bd9Sstevel@tonic-gate probelif->li_cachestate &= ~(CACHE_IF_STALE); 11707c478bd9Sstevel@tonic-gate break; 11717c478bd9Sstevel@tonic-gate } 11727c478bd9Sstevel@tonic-gate probelif = probelif->li_next; 11737c478bd9Sstevel@tonic-gate } 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate if (probepif == NULL) { 11777c478bd9Sstevel@tonic-gate if ((probepif = calloc(1, sizeof (ip_pif_t))) == NULL) { 11787c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: malloc: %s\n"), 11797c478bd9Sstevel@tonic-gate strerror(errno)); 11807c478bd9Sstevel@tonic-gate if (probe->ip_pif == NULL) { 11817c478bd9Sstevel@tonic-gate /* we created it, so clean it up */ 11827c478bd9Sstevel@tonic-gate free(probe); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate return (-1); 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate probe->ip_pif = probepif; 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate /* Save interface name */ 11907c478bd9Sstevel@tonic-gate (void) memcpy(&probepif->pi_ifname, &pif.pi_ifname, 11917c478bd9Sstevel@tonic-gate sizeof (pif.pi_ifname)); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate 1194e11c3f44Smeem /* save the group name */ 1195e11c3f44Smeem (void) strlcpy(probepif->pi_grname, pif.pi_grname, 1196e11c3f44Smeem sizeof (pif.pi_grname)); 11977c478bd9Sstevel@tonic-gate 11987c478bd9Sstevel@tonic-gate /* add lif, if this is a lif and it is not in cache */ 11997c478bd9Sstevel@tonic-gate if (!lif_listed) { 12007c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: adding lifs to %s\n", 12017c478bd9Sstevel@tonic-gate pif.pi_ifname); 12027c478bd9Sstevel@tonic-gate 12037c478bd9Sstevel@tonic-gate if ((probelif = calloc(1, sizeof (ip_lif_t))) == NULL) { 12047c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: malloc: %s\n"), 12057c478bd9Sstevel@tonic-gate strerror(errno)); 12067c478bd9Sstevel@tonic-gate return (-1); 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate /* save lif properties */ 12107c478bd9Sstevel@tonic-gate (void) memcpy(&probelif->li_addr, &ifaddr, 12117c478bd9Sstevel@tonic-gate sizeof (probelif->li_addr)); 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate probelif->li_ifnum = ifnumber; 12147c478bd9Sstevel@tonic-gate probelif->li_ifflags = ifflags; 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate /* insert us at the head of the lif list */ 12177c478bd9Sstevel@tonic-gate probelif->li_next = probepif->pi_lifs; 12187c478bd9Sstevel@tonic-gate if (probelif->li_next != NULL) { 12197c478bd9Sstevel@tonic-gate probelif->li_next->li_prev = probelif; 12207c478bd9Sstevel@tonic-gate } 12217c478bd9Sstevel@tonic-gate probelif->li_prev = NULL; 12227c478bd9Sstevel@tonic-gate probelif->li_pif = probepif; 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate probepif->pi_lifs = probelif; 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE3, "IP: update_pif: (%s) success\n", 12287c478bd9Sstevel@tonic-gate probe->ip_resource); 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate return (0); 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate /* 12347c478bd9Sstevel@tonic-gate * update_ipifs() - Determine all network interfaces in the system 12357c478bd9Sstevel@tonic-gate * Call with cache_lock held 12367c478bd9Sstevel@tonic-gate */ 12377c478bd9Sstevel@tonic-gate static int 12387c478bd9Sstevel@tonic-gate update_ipifs(rcm_handle_t *hd, int af) 12397c478bd9Sstevel@tonic-gate { 12407c478bd9Sstevel@tonic-gate 12416e91bba0SGirish Moodalbail struct ifaddrs *ifa; 12426e91bba0SGirish Moodalbail ipadm_addr_info_t *ainfo; 12436e91bba0SGirish Moodalbail ipadm_addr_info_t *ptr; 12446e91bba0SGirish Moodalbail ipadm_status_t status; 12456e91bba0SGirish Moodalbail int sock; 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if ((sock = socket(af, SOCK_DGRAM, 0)) == -1) { 12487c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 12497c478bd9Sstevel@tonic-gate _("IP: failure opening %s socket: %s\n"), 12507c478bd9Sstevel@tonic-gate af == AF_INET6 ? "IPv6" : "IPv4", strerror(errno)); 12517c478bd9Sstevel@tonic-gate return (-1); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate 12546e91bba0SGirish Moodalbail status = ipadm_addr_info(ip_handle, NULL, &ainfo, IPADM_OPT_ZEROADDR, 12556e91bba0SGirish Moodalbail LIFC_UNDER_IPMP); 12566e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) { 12577c478bd9Sstevel@tonic-gate (void) close(sock); 12587c478bd9Sstevel@tonic-gate return (-1); 12597c478bd9Sstevel@tonic-gate } 12606e91bba0SGirish Moodalbail for (ptr = ainfo; ptr; ptr = IA_NEXT(ptr)) { 12616e91bba0SGirish Moodalbail ifa = &ptr->ia_ifa; 12626e91bba0SGirish Moodalbail if (ptr->ia_state != IFA_DISABLED && 1263*64639aafSDarren Reed af == ifa->ifa_addr->sa_family) 12646e91bba0SGirish Moodalbail (void) update_pif(hd, af, sock, ifa); 12657c478bd9Sstevel@tonic-gate } 12667c478bd9Sstevel@tonic-gate (void) close(sock); 12676e91bba0SGirish Moodalbail ipadm_free_addr_info(ainfo); 12687c478bd9Sstevel@tonic-gate return (0); 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate /* 12727c478bd9Sstevel@tonic-gate * update_cache() - Update cache with latest interface info 12737c478bd9Sstevel@tonic-gate */ 12747c478bd9Sstevel@tonic-gate static int 12757c478bd9Sstevel@tonic-gate update_cache(rcm_handle_t *hd) 12767c478bd9Sstevel@tonic-gate { 12777c478bd9Sstevel@tonic-gate ip_cache_t *probe; 12787c478bd9Sstevel@tonic-gate struct ip_lif *lif; 12797c478bd9Sstevel@tonic-gate struct ip_lif *nextlif; 12807c478bd9Sstevel@tonic-gate int rv; 12817c478bd9Sstevel@tonic-gate int i; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: update_cache\n"); 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate /* first we walk the entire cache, marking each entry stale */ 12887c478bd9Sstevel@tonic-gate probe = cache_head.ip_next; 12897c478bd9Sstevel@tonic-gate while (probe != &cache_tail) { 12907c478bd9Sstevel@tonic-gate probe->ip_cachestate |= CACHE_IF_STALE; 12917c478bd9Sstevel@tonic-gate if ((probe->ip_pif != NULL) && 12927c478bd9Sstevel@tonic-gate ((lif = probe->ip_pif->pi_lifs) != NULL)) { 12937c478bd9Sstevel@tonic-gate while (lif != NULL) { 12947c478bd9Sstevel@tonic-gate lif->li_cachestate |= CACHE_IF_STALE; 12957c478bd9Sstevel@tonic-gate lif = lif->li_next; 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate probe = probe->ip_next; 12997c478bd9Sstevel@tonic-gate } 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: scanning IPv4 interfaces\n"); 13027c478bd9Sstevel@tonic-gate if (update_ipifs(hd, AF_INET) < 0) { 13037c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 13047c478bd9Sstevel@tonic-gate return (-1); 13057c478bd9Sstevel@tonic-gate } 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: scanning IPv6 interfaces\n"); 13087c478bd9Sstevel@tonic-gate if (update_ipifs(hd, AF_INET6) < 0) { 13097c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 13107c478bd9Sstevel@tonic-gate return (-1); 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate probe = cache_head.ip_next; 13147c478bd9Sstevel@tonic-gate /* unregister devices that are not offlined and still in cache */ 13157c478bd9Sstevel@tonic-gate while (probe != &cache_tail) { 13167c478bd9Sstevel@tonic-gate ip_cache_t *freeit; 13177c478bd9Sstevel@tonic-gate if ((probe->ip_pif != NULL) && 13187c478bd9Sstevel@tonic-gate ((lif = probe->ip_pif->pi_lifs) != NULL)) { 13197c478bd9Sstevel@tonic-gate /* clear stale lifs */ 13207c478bd9Sstevel@tonic-gate while (lif != NULL) { 13217c478bd9Sstevel@tonic-gate if (lif->li_cachestate & CACHE_IF_STALE) { 13227c478bd9Sstevel@tonic-gate nextlif = lif->li_next; 13237c478bd9Sstevel@tonic-gate if (lif->li_prev != NULL) 13247c478bd9Sstevel@tonic-gate lif->li_prev->li_next = nextlif; 13257c478bd9Sstevel@tonic-gate if (nextlif != NULL) 13267c478bd9Sstevel@tonic-gate nextlif->li_prev = lif->li_prev; 13277c478bd9Sstevel@tonic-gate if (probe->ip_pif->pi_lifs == lif) 13287c478bd9Sstevel@tonic-gate probe->ip_pif->pi_lifs = 13297c478bd9Sstevel@tonic-gate nextlif; 13307c478bd9Sstevel@tonic-gate for (i = 0; i < IP_MAX_MODS; i++) { 13317c478bd9Sstevel@tonic-gate free(lif->li_modules[i]); 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate free(lif->li_reconfig); 13347c478bd9Sstevel@tonic-gate free(lif); 13357c478bd9Sstevel@tonic-gate lif = nextlif; 13367c478bd9Sstevel@tonic-gate } else { 13377c478bd9Sstevel@tonic-gate lif = lif->li_next; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate if ((probe->ip_cachestate & CACHE_IF_STALE) && 13427c478bd9Sstevel@tonic-gate !(probe->ip_cachestate & CACHE_IF_OFFLINED)) { 13437c478bd9Sstevel@tonic-gate (void) rcm_unregister_interest(hd, probe->ip_resource, 13447c478bd9Sstevel@tonic-gate 0); 13457c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "IP: unregistered %s\n", 13467c478bd9Sstevel@tonic-gate probe->ip_resource); 13477c478bd9Sstevel@tonic-gate freeit = probe; 13487c478bd9Sstevel@tonic-gate probe = probe->ip_next; 13497c478bd9Sstevel@tonic-gate cache_remove(freeit); 13507c478bd9Sstevel@tonic-gate free_node(freeit); 13517c478bd9Sstevel@tonic-gate continue; 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate if (!(probe->ip_cachestate & CACHE_IF_NEW)) { 13557c478bd9Sstevel@tonic-gate probe = probe->ip_next; 13567c478bd9Sstevel@tonic-gate continue; 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate rv = rcm_register_interest(hd, probe->ip_resource, 0, NULL); 13607c478bd9Sstevel@tonic-gate if (rv != RCM_SUCCESS) { 13617c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 13627c478bd9Sstevel@tonic-gate _("IP: failed to register %s\n"), 13637c478bd9Sstevel@tonic-gate probe->ip_resource); 13647c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 13657c478bd9Sstevel@tonic-gate return (-1); 13667c478bd9Sstevel@tonic-gate } else { 13677c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "IP: registered %s\n", 13687c478bd9Sstevel@tonic-gate probe->ip_resource); 13697c478bd9Sstevel@tonic-gate probe->ip_cachestate &= ~(CACHE_IF_NEW); 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate probe = probe->ip_next; 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 13757c478bd9Sstevel@tonic-gate return (0); 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate 13787c478bd9Sstevel@tonic-gate /* 13797c478bd9Sstevel@tonic-gate * free_cache() - Empty the cache 13807c478bd9Sstevel@tonic-gate */ 13817c478bd9Sstevel@tonic-gate static void 13827c478bd9Sstevel@tonic-gate free_cache() 13837c478bd9Sstevel@tonic-gate { 13847c478bd9Sstevel@tonic-gate ip_cache_t *probe; 13857c478bd9Sstevel@tonic-gate 13867c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: free_cache\n"); 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 13897c478bd9Sstevel@tonic-gate probe = cache_head.ip_next; 13907c478bd9Sstevel@tonic-gate while (probe != &cache_tail) { 13917c478bd9Sstevel@tonic-gate cache_remove(probe); 13927c478bd9Sstevel@tonic-gate free_node(probe); 13937c478bd9Sstevel@tonic-gate probe = cache_head.ip_next; 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate * ip_log_err() - RCM error log wrapper 14007c478bd9Sstevel@tonic-gate */ 14017c478bd9Sstevel@tonic-gate static void 14027c478bd9Sstevel@tonic-gate ip_log_err(ip_cache_t *node, char **errorp, char *errmsg) 14037c478bd9Sstevel@tonic-gate { 1404d62bc4baSyz147064 char *ifname = NULL; 1405e11c3f44Smeem int size; 14067c478bd9Sstevel@tonic-gate const char *errfmt; 1407e11c3f44Smeem char *error = NULL; 14087c478bd9Sstevel@tonic-gate 14097c478bd9Sstevel@tonic-gate if ((node != NULL) && (node->ip_pif != NULL) && 14107c478bd9Sstevel@tonic-gate (node->ip_pif->pi_ifname != NULL)) { 1411d62bc4baSyz147064 ifname = node->ip_pif->pi_ifname; 14127c478bd9Sstevel@tonic-gate } 14137c478bd9Sstevel@tonic-gate 1414d62bc4baSyz147064 if (ifname == NULL) { 14157c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: %s\n"), errmsg); 14167c478bd9Sstevel@tonic-gate errfmt = _("IP: %s"); 1417e11c3f44Smeem size = strlen(errfmt) + strlen(errmsg) + 1; 1418e11c3f44Smeem if (errorp != NULL && (error = malloc(size)) != NULL) 1419e11c3f44Smeem (void) snprintf(error, size, errfmt, errmsg); 14207c478bd9Sstevel@tonic-gate } else { 1421d62bc4baSyz147064 rcm_log_message(RCM_ERROR, _("IP: %s(%s)\n"), errmsg, ifname); 14227c478bd9Sstevel@tonic-gate errfmt = _("IP: %s(%s)"); 1423e11c3f44Smeem size = strlen(errfmt) + strlen(errmsg) + strlen(ifname) + 1; 1424e11c3f44Smeem if (errorp != NULL && (error = malloc(size)) != NULL) 1425e11c3f44Smeem (void) snprintf(error, size, errfmt, errmsg, ifname); 14267c478bd9Sstevel@tonic-gate } 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate if (errorp != NULL) 14297c478bd9Sstevel@tonic-gate *errorp = error; 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate 14327c478bd9Sstevel@tonic-gate /* 14337c478bd9Sstevel@tonic-gate * if_cfginfo() - Save off the config info for all interfaces 14347c478bd9Sstevel@tonic-gate */ 14357c478bd9Sstevel@tonic-gate static int 14367c478bd9Sstevel@tonic-gate if_cfginfo(ip_cache_t *node, uint_t force) 14377c478bd9Sstevel@tonic-gate { 14387c478bd9Sstevel@tonic-gate ip_lif_t *lif; 14397c478bd9Sstevel@tonic-gate ip_pif_t *pif; 14407c478bd9Sstevel@tonic-gate int i; 14417c478bd9Sstevel@tonic-gate FILE *fp; 14427c478bd9Sstevel@tonic-gate char syscmd[MAX_RECONFIG_SIZE + LIFNAMSIZ]; 14437c478bd9Sstevel@tonic-gate char buf[MAX_RECONFIG_SIZE]; 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: if_cfginfo(%s)\n", node->ip_resource); 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate pif = node->ip_pif; 14487c478bd9Sstevel@tonic-gate lif = pif->pi_lifs; 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate while (lif != NULL) { 14517c478bd9Sstevel@tonic-gate /* Make a list of modules pushed and save */ 14527c478bd9Sstevel@tonic-gate if (lif->li_ifnum == 0) { /* physical instance */ 14537c478bd9Sstevel@tonic-gate if (get_modlist(pif->pi_ifname, lif) == -1) { 14547c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 14557c478bd9Sstevel@tonic-gate _("IP: get modlist error (%s) %s\n"), 14567c478bd9Sstevel@tonic-gate pif->pi_ifname, strerror(errno)); 1457e11c3f44Smeem clr_cfg_state(pif); 14587c478bd9Sstevel@tonic-gate return (-1); 14597c478bd9Sstevel@tonic-gate } 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate if (!force) { 14627c478bd9Sstevel@tonic-gate /* Look if unknown modules have been inserted */ 14637c478bd9Sstevel@tonic-gate for (i = (lif->li_modcnt - 2); i > 0; i--) { 14647c478bd9Sstevel@tonic-gate if (modop(pif->pi_ifname, 14657c478bd9Sstevel@tonic-gate lif->li_modules[i], 14667c478bd9Sstevel@tonic-gate i, MOD_CHECK) == -1) { 14677c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 14687c478bd9Sstevel@tonic-gate _("IP: module %s@%d\n"), 14697c478bd9Sstevel@tonic-gate lif->li_modules[i], i); 1470e11c3f44Smeem clr_cfg_state(pif); 14717c478bd9Sstevel@tonic-gate return (-1); 14727c478bd9Sstevel@tonic-gate } 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate /* Last module is the device driver, so ignore that */ 14777c478bd9Sstevel@tonic-gate for (i = (lif->li_modcnt - 2); i > 0; i--) { 14787c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, 14797c478bd9Sstevel@tonic-gate "IP: modremove Pos = %d, Module = %s \n", 14807c478bd9Sstevel@tonic-gate i, lif->li_modules[i]); 14817c478bd9Sstevel@tonic-gate if (modop(pif->pi_ifname, lif->li_modules[i], 14827c478bd9Sstevel@tonic-gate i, MOD_REMOVE) == -1) { 14837c478bd9Sstevel@tonic-gate while (i != (lif->li_modcnt - 2)) { 14847c478bd9Sstevel@tonic-gate if (modop(pif->pi_ifname, 14857c478bd9Sstevel@tonic-gate lif->li_modules[i], 14867c478bd9Sstevel@tonic-gate i, MOD_INSERT) == -1) { 14877c478bd9Sstevel@tonic-gate /* Gross error */ 14887c478bd9Sstevel@tonic-gate rcm_log_message( 14897c478bd9Sstevel@tonic-gate RCM_ERROR, 14907c478bd9Sstevel@tonic-gate _("IP: if_cfginfo" 14917c478bd9Sstevel@tonic-gate "(%s) %s\n"), 14927c478bd9Sstevel@tonic-gate pif->pi_ifname, 14937c478bd9Sstevel@tonic-gate strerror(errno)); 14947c478bd9Sstevel@tonic-gate clr_cfg_state(pif); 14957c478bd9Sstevel@tonic-gate return (-1); 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate i++; 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate rcm_log_message( 15007c478bd9Sstevel@tonic-gate RCM_ERROR, 15017c478bd9Sstevel@tonic-gate _("IP: if_cfginfo(%s): modremove " 15027c478bd9Sstevel@tonic-gate "%s failed: %s\n"), pif->pi_ifname, 15037c478bd9Sstevel@tonic-gate lif->li_modules[i], 15047c478bd9Sstevel@tonic-gate strerror(errno)); 15057c478bd9Sstevel@tonic-gate clr_cfg_state(pif); 15067c478bd9Sstevel@tonic-gate return (-1); 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate /* Save reconfiguration information */ 15127c478bd9Sstevel@tonic-gate if (lif->li_ifflags & IFF_IPV4) { 15137c478bd9Sstevel@tonic-gate (void) snprintf(syscmd, sizeof (syscmd), 1514e11c3f44Smeem "%s %s:%d configinfo\n", SBIN_IFCONFIG, 15157c478bd9Sstevel@tonic-gate pif->pi_ifname, lif->li_ifnum); 15167c478bd9Sstevel@tonic-gate } else if (lif->li_ifflags & IFF_IPV6) { 15177c478bd9Sstevel@tonic-gate (void) snprintf(syscmd, sizeof (syscmd), 1518e11c3f44Smeem "%s %s:%d inet6 configinfo\n", SBIN_IFCONFIG, 15197c478bd9Sstevel@tonic-gate pif->pi_ifname, lif->li_ifnum); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: %s\n", syscmd); 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate /* open a pipe to retrieve reconfiguration info */ 15247c478bd9Sstevel@tonic-gate if ((fp = popen(syscmd, "r")) == NULL) { 15257c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 15267c478bd9Sstevel@tonic-gate _("IP: ifconfig configinfo error (%s:%d) %s\n"), 15277c478bd9Sstevel@tonic-gate pif->pi_ifname, lif->li_ifnum, strerror(errno)); 1528e11c3f44Smeem clr_cfg_state(pif); 15297c478bd9Sstevel@tonic-gate return (-1); 15307c478bd9Sstevel@tonic-gate } 15317c478bd9Sstevel@tonic-gate bzero(buf, MAX_RECONFIG_SIZE); 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if (fgets(buf, MAX_RECONFIG_SIZE, fp) == NULL) { 15347c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 15357c478bd9Sstevel@tonic-gate _("IP: ifconfig configinfo error (%s:%d) %s\n"), 15367c478bd9Sstevel@tonic-gate pif->pi_ifname, lif->li_ifnum, strerror(errno)); 15377c478bd9Sstevel@tonic-gate (void) pclose(fp); 1538e11c3f44Smeem clr_cfg_state(pif); 15397c478bd9Sstevel@tonic-gate return (-1); 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate (void) pclose(fp); 15427c478bd9Sstevel@tonic-gate 1543e11c3f44Smeem if ((lif->li_reconfig = strdup(buf)) == NULL) { 15447c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 15457c478bd9Sstevel@tonic-gate _("IP: malloc error (%s) %s\n"), 15467c478bd9Sstevel@tonic-gate pif->pi_ifname, strerror(errno)); 1547e11c3f44Smeem clr_cfg_state(pif); 15487c478bd9Sstevel@tonic-gate return (-1); 15497c478bd9Sstevel@tonic-gate } 15507c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, 15517c478bd9Sstevel@tonic-gate "IP: if_cfginfo: reconfig string(%s:%d) = %s\n", 15527c478bd9Sstevel@tonic-gate pif->pi_ifname, lif->li_ifnum, lif->li_reconfig); 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate lif = lif->li_next; 15557c478bd9Sstevel@tonic-gate } 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate return (0); 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate /* 15617c478bd9Sstevel@tonic-gate * if_unplumb() - Unplumb the interface 15627c478bd9Sstevel@tonic-gate * Save off the modlist, ifconfig options and unplumb. 15637c478bd9Sstevel@tonic-gate * Fail, if an unknown module lives between IP and driver and 15647c478bd9Sstevel@tonic-gate * force is not set 15657c478bd9Sstevel@tonic-gate * Call with cache_lock held 15667c478bd9Sstevel@tonic-gate */ 15677c478bd9Sstevel@tonic-gate static int 15687c478bd9Sstevel@tonic-gate if_unplumb(ip_cache_t *node) 15697c478bd9Sstevel@tonic-gate { 15707c478bd9Sstevel@tonic-gate ip_lif_t *lif; 1571e11c3f44Smeem ip_pif_t *pif = node->ip_pif; 1572e11c3f44Smeem boolean_t ipv4 = B_FALSE; 1573e11c3f44Smeem boolean_t ipv6 = B_FALSE; 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: if_unplumb(%s)\n", node->ip_resource); 15767c478bd9Sstevel@tonic-gate 1577e11c3f44Smeem for (lif = pif->pi_lifs; lif != NULL; lif = lif->li_next) { 15787c478bd9Sstevel@tonic-gate if (lif->li_ifflags & IFF_IPV4) { 1579e11c3f44Smeem ipv4 = B_TRUE; 15807c478bd9Sstevel@tonic-gate } else if (lif->li_ifflags & IFF_IPV6) { 1581e11c3f44Smeem ipv6 = B_TRUE; 15827c478bd9Sstevel@tonic-gate } else { 15837c478bd9Sstevel@tonic-gate /* Unlikely case */ 15847c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, 1585d62bc4baSyz147064 "IP: Unplumb ignored (%s:%d)\n", 15867c478bd9Sstevel@tonic-gate pif->pi_ifname, lif->li_ifnum); 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate 1590e11c3f44Smeem if (ipv4 && !ifconfig(pif->pi_ifname, "inet", "unplumb", B_FALSE)) { 1591e11c3f44Smeem rcm_log_message(RCM_ERROR, _("IP: Cannot unplumb (%s) %s\n"), 15927c478bd9Sstevel@tonic-gate pif->pi_ifname, strerror(errno)); 15937c478bd9Sstevel@tonic-gate return (-1); 15947c478bd9Sstevel@tonic-gate } 1595e11c3f44Smeem 1596e11c3f44Smeem if (ipv6 && !ifconfig(pif->pi_ifname, "inet6", "unplumb", B_FALSE)) { 1597e11c3f44Smeem rcm_log_message(RCM_ERROR, _("IP: Cannot unplumb (%s) %s\n"), 15987c478bd9Sstevel@tonic-gate pif->pi_ifname, strerror(errno)); 15997c478bd9Sstevel@tonic-gate return (-1); 16007c478bd9Sstevel@tonic-gate } 1601e11c3f44Smeem 16027c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: if_unplumb(%s) success\n", 16037c478bd9Sstevel@tonic-gate node->ip_resource); 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate return (0); 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate /* 16097c478bd9Sstevel@tonic-gate * if_replumb() - Undo previous unplumb i.e. plumb back the physical interface 16107c478bd9Sstevel@tonic-gate * instances and the logical interfaces in order, restoring 16117c478bd9Sstevel@tonic-gate * all ifconfig options 16127c478bd9Sstevel@tonic-gate * Call with cache_lock held 16137c478bd9Sstevel@tonic-gate */ 16147c478bd9Sstevel@tonic-gate static int 16157c478bd9Sstevel@tonic-gate if_replumb(ip_cache_t *node) 16167c478bd9Sstevel@tonic-gate { 16177c478bd9Sstevel@tonic-gate ip_lif_t *lif; 16187c478bd9Sstevel@tonic-gate ip_pif_t *pif; 16197c478bd9Sstevel@tonic-gate int i; 1620e11c3f44Smeem boolean_t success, ipmp; 1621e11c3f44Smeem const char *fstr; 1622e11c3f44Smeem char lifname[LIFNAMSIZ]; 1623e11c3f44Smeem char buf[MAX_RECONFIG_SIZE]; 1624e11c3f44Smeem int max_lifnum = 0; 16257c478bd9Sstevel@tonic-gate 16267c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: if_replumb(%s)\n", node->ip_resource); 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate /* 16297c478bd9Sstevel@tonic-gate * Be extra careful about bringing up the interfaces in the 16307c478bd9Sstevel@tonic-gate * correct order: 16317c478bd9Sstevel@tonic-gate * - First plumb in the physical interface instances 16327c478bd9Sstevel@tonic-gate * - modinsert the necessary modules@pos 16337c478bd9Sstevel@tonic-gate * - Next, add the logical interfaces being careful about 16347c478bd9Sstevel@tonic-gate * the order, (follow the cached interface number li_ifnum order) 16357c478bd9Sstevel@tonic-gate */ 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate pif = node->ip_pif; 1638e11c3f44Smeem ipmp = (node->ip_pif->pi_grname[0] != '\0'); 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate /* 16417c478bd9Sstevel@tonic-gate * Make a first pass to plumb in physical interfaces and get a count 16427c478bd9Sstevel@tonic-gate * of the max logical interfaces 16437c478bd9Sstevel@tonic-gate */ 1644e11c3f44Smeem for (lif = pif->pi_lifs; lif != NULL; lif = lif->li_next) { 1645e11c3f44Smeem max_lifnum = MAX(lif->li_ifnum, max_lifnum); 16467c478bd9Sstevel@tonic-gate if (lif->li_ifflags & IFF_IPV4) { 1647e11c3f44Smeem fstr = "inet"; 16487c478bd9Sstevel@tonic-gate } else if (lif->li_ifflags & IFF_IPV6) { 1649e11c3f44Smeem fstr = "inet6"; 16507c478bd9Sstevel@tonic-gate } else { 16517c478bd9Sstevel@tonic-gate /* Unlikely case */ 16527c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, 1653d62bc4baSyz147064 "IP: Re-plumb ignored (%s:%d)\n", 16547c478bd9Sstevel@tonic-gate pif->pi_ifname, lif->li_ifnum); 16557c478bd9Sstevel@tonic-gate continue; 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate 1658e11c3f44Smeem /* ignore logical interface instances */ 1659e11c3f44Smeem if (lif->li_ifnum != 0) 1660e11c3f44Smeem continue; 1661e11c3f44Smeem 1662e11c3f44Smeem if ((lif->li_ifflags & IFF_NOFAILOVER) || !ipmp) { 1663e11c3f44Smeem success = ifconfig("", "", lif->li_reconfig, B_FALSE); 1664e11c3f44Smeem } else { 1665e11c3f44Smeem (void) snprintf(buf, sizeof (buf), "plumb group %s", 1666e11c3f44Smeem pif->pi_grname); 1667e11c3f44Smeem success = ifconfig(pif->pi_ifname, fstr, buf, B_FALSE); 16687c478bd9Sstevel@tonic-gate } 16697c478bd9Sstevel@tonic-gate 1670e11c3f44Smeem if (!success) { 16717c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 1672e11c3f44Smeem _("IP: Cannot plumb (%s) %s\n"), pif->pi_ifname, 1673e11c3f44Smeem strerror(errno)); 1674e11c3f44Smeem return (-1); 1675e11c3f44Smeem } 1676e11c3f44Smeem 1677e11c3f44Smeem /* 1678e11c3f44Smeem * Restart DHCP if necessary. 1679e11c3f44Smeem */ 1680e11c3f44Smeem if ((lif->li_ifflags & IFF_DHCPRUNNING) && 1681e11c3f44Smeem !ifconfig(pif->pi_ifname, fstr, CFG_DHCP_CMD, B_FALSE)) { 1682e11c3f44Smeem rcm_log_message(RCM_ERROR, _("IP: Cannot start DHCP " 1683e11c3f44Smeem "(%s) %s\n"), pif->pi_ifname, strerror(errno)); 16847c478bd9Sstevel@tonic-gate return (-1); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, 16887c478bd9Sstevel@tonic-gate "IP: if_replumb: Modcnt = %d\n", lif->li_modcnt); 16897c478bd9Sstevel@tonic-gate /* modinsert modules in order, ignore driver(last) */ 16907c478bd9Sstevel@tonic-gate for (i = 0; i < (lif->li_modcnt - 1); i++) { 16917c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, 16927c478bd9Sstevel@tonic-gate "IP: modinsert: Pos = %d Mod = %s\n", 16937c478bd9Sstevel@tonic-gate i, lif->li_modules[i]); 16947c478bd9Sstevel@tonic-gate if (modop(pif->pi_ifname, lif->li_modules[i], i, 16957c478bd9Sstevel@tonic-gate MOD_INSERT) == -1) { 16967c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 16977c478bd9Sstevel@tonic-gate _("IP: modinsert error(%s)\n"), 16987c478bd9Sstevel@tonic-gate pif->pi_ifname); 16997c478bd9Sstevel@tonic-gate return (-1); 17007c478bd9Sstevel@tonic-gate } 17017c478bd9Sstevel@tonic-gate } 17027c478bd9Sstevel@tonic-gate } 17037c478bd9Sstevel@tonic-gate 17047c478bd9Sstevel@tonic-gate /* Now, add all the logical interfaces in the correct order */ 1705e11c3f44Smeem for (i = 1; i <= max_lifnum; i++) { 1706e11c3f44Smeem (void) snprintf(lifname, LIFNAMSIZ, "%s:%d", pif->pi_ifname, i); 1707e11c3f44Smeem 17087c478bd9Sstevel@tonic-gate /* reset lif through every iteration */ 1709e11c3f44Smeem for (lif = pif->pi_lifs; lif != NULL; lif = lif->li_next) { 1710e11c3f44Smeem /* 1711e11c3f44Smeem * Process entries in order. If the interface is 1712e11c3f44Smeem * using IPMP, only process test addresses. 1713e11c3f44Smeem */ 1714e11c3f44Smeem if (lif->li_ifnum != i || 1715e11c3f44Smeem (ipmp && !(lif->li_ifflags & IFF_NOFAILOVER))) 1716e11c3f44Smeem continue; 1717e11c3f44Smeem 1718e11c3f44Smeem if (!ifconfig("", "", lif->li_reconfig, B_FALSE)) { 17197c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 1720e11c3f44Smeem _("IP: Cannot addif (%s) %s\n"), lifname, 1721e11c3f44Smeem strerror(errno)); 17227c478bd9Sstevel@tonic-gate return (-1); 17237c478bd9Sstevel@tonic-gate } 1724e11c3f44Smeem 1725e11c3f44Smeem /* 1726e11c3f44Smeem * Restart DHCP if necessary. 1727e11c3f44Smeem */ 1728e11c3f44Smeem if ((lif->li_ifflags & IFF_DHCPRUNNING) && 1729e11c3f44Smeem !ifconfig(lifname, fstr, CFG_DHCP_CMD, B_FALSE)) { 1730e11c3f44Smeem rcm_log_message(RCM_ERROR, 1731e11c3f44Smeem _("IP: Cannot start DHCP (%s) %s\n"), 1732e11c3f44Smeem lifname, strerror(errno)); 1733e11c3f44Smeem return (-1); 17347c478bd9Sstevel@tonic-gate } 17357c478bd9Sstevel@tonic-gate } 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: if_replumb(%s) success \n", 17397c478bd9Sstevel@tonic-gate node->ip_resource); 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate return (0); 17427c478bd9Sstevel@tonic-gate } 17437c478bd9Sstevel@tonic-gate 17447c478bd9Sstevel@tonic-gate /* 17457c478bd9Sstevel@tonic-gate * clr_cfg_state() - Cleanup after errors in unplumb 17467c478bd9Sstevel@tonic-gate */ 17477c478bd9Sstevel@tonic-gate static void 17487c478bd9Sstevel@tonic-gate clr_cfg_state(ip_pif_t *pif) 17497c478bd9Sstevel@tonic-gate { 17507c478bd9Sstevel@tonic-gate ip_lif_t *lif; 17517c478bd9Sstevel@tonic-gate int i; 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate lif = pif->pi_lifs; 17547c478bd9Sstevel@tonic-gate 17557c478bd9Sstevel@tonic-gate while (lif != NULL) { 17567c478bd9Sstevel@tonic-gate lif->li_modcnt = 0; 17577c478bd9Sstevel@tonic-gate free(lif->li_reconfig); 17587c478bd9Sstevel@tonic-gate lif->li_reconfig = NULL; 17597c478bd9Sstevel@tonic-gate for (i = 0; i < IP_MAX_MODS; i++) { 17607c478bd9Sstevel@tonic-gate free(lif->li_modules[i]); 17617c478bd9Sstevel@tonic-gate lif->li_modules[i] = NULL; 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate lif = lif->li_next; 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate /* 1768e11c3f44Smeem * Attempt to offline ip_cache_t `node'; returns an IPMP error code. 17697c478bd9Sstevel@tonic-gate */ 17707c478bd9Sstevel@tonic-gate static int 1771e11c3f44Smeem ip_ipmp_offline(ip_cache_t *node) 17727c478bd9Sstevel@tonic-gate { 1773e11c3f44Smeem int retval; 1774e11c3f44Smeem ipmp_handle_t handle; 17757c478bd9Sstevel@tonic-gate 17767c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: ip_ipmp_offline\n"); 17777c478bd9Sstevel@tonic-gate 1778e11c3f44Smeem if ((retval = ipmp_open(&handle)) != IPMP_SUCCESS) { 17797c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 1780e11c3f44Smeem _("IP: cannot create ipmp handle: %s\n"), 1781e11c3f44Smeem ipmp_errmsg(retval)); 1782e11c3f44Smeem return (retval); 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate 1785e11c3f44Smeem retval = ipmp_offline(handle, node->ip_pif->pi_ifname, node->ip_ifred); 1786e11c3f44Smeem if (retval != IPMP_SUCCESS) { 1787e11c3f44Smeem rcm_log_message(RCM_ERROR, _("IP: ipmp_offline error: %s\n"), 1788e11c3f44Smeem ipmp_errmsg(retval)); 1789e11c3f44Smeem } else { 1790e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: ipmp_offline success\n"); 1791e11c3f44Smeem } 1792e11c3f44Smeem 1793e11c3f44Smeem ipmp_close(handle); 1794e11c3f44Smeem return (retval); 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate /* 1798e11c3f44Smeem * Attempt to undo the offline ip_cache_t `node'; returns an IPMP error code. 17997c478bd9Sstevel@tonic-gate */ 18007c478bd9Sstevel@tonic-gate static int 18017c478bd9Sstevel@tonic-gate ip_ipmp_undo_offline(ip_cache_t *node) 18027c478bd9Sstevel@tonic-gate { 1803e11c3f44Smeem int retval; 1804e11c3f44Smeem ipmp_handle_t handle; 18057c478bd9Sstevel@tonic-gate 1806e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: ip_ipmp_undo_offline\n"); 18077c478bd9Sstevel@tonic-gate 1808e11c3f44Smeem if ((retval = ipmp_open(&handle)) != IPMP_SUCCESS) { 18097c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 1810e11c3f44Smeem _("IP: cannot create ipmp handle: %s\n"), 1811e11c3f44Smeem ipmp_errmsg(retval)); 1812e11c3f44Smeem return (retval); 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate 1815e11c3f44Smeem retval = ipmp_undo_offline(handle, node->ip_pif->pi_ifname); 1816e11c3f44Smeem if (retval != IPMP_SUCCESS) { 1817e11c3f44Smeem rcm_log_message(RCM_ERROR, 1818e11c3f44Smeem _("IP: ipmp_undo_offline error: %s\n"), 1819e11c3f44Smeem ipmp_errmsg(retval)); 1820e11c3f44Smeem } else { 1821e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: ipmp_undo_offline success\n"); 1822e11c3f44Smeem } 1823e11c3f44Smeem 1824e11c3f44Smeem ipmp_close(handle); 1825e11c3f44Smeem return (retval); 18267c478bd9Sstevel@tonic-gate } 18277c478bd9Sstevel@tonic-gate 18287c478bd9Sstevel@tonic-gate /* 1829d62bc4baSyz147064 * get_link_resource() - Convert a link name (e.g., net0, hme1000) into a 1830d62bc4baSyz147064 * dynamically allocated string containing the associated link resource 1831d62bc4baSyz147064 * name ("SUNW_datalink/<linkid>"). 18327c478bd9Sstevel@tonic-gate */ 18337c478bd9Sstevel@tonic-gate static char * 1834d62bc4baSyz147064 get_link_resource(const char *link) 18357c478bd9Sstevel@tonic-gate { 1836d62bc4baSyz147064 char errmsg[DLADM_STRSIZE]; 1837d62bc4baSyz147064 datalink_id_t linkid; 1838d62bc4baSyz147064 uint32_t flags; 1839d62bc4baSyz147064 char *resource; 1840d62bc4baSyz147064 dladm_status_t status; 18417c478bd9Sstevel@tonic-gate 1842e11c3f44Smeem status = dladm_name2info(dld_handle, link, &linkid, &flags, NULL, NULL); 1843e11c3f44Smeem if (status != DLADM_STATUS_OK) 1844d62bc4baSyz147064 goto fail; 18457c478bd9Sstevel@tonic-gate 1846d62bc4baSyz147064 if (!(flags & DLADM_OPT_ACTIVE)) { 1847d62bc4baSyz147064 status = DLADM_STATUS_FAILED; 1848d62bc4baSyz147064 goto fail; 1849d62bc4baSyz147064 } 1850d62bc4baSyz147064 1851d62bc4baSyz147064 resource = malloc(RCM_LINK_RESOURCE_MAX); 1852d62bc4baSyz147064 if (resource == NULL) { 1853595aa6e4Smeem rcm_log_message(RCM_ERROR, _("IP: malloc error(%s): %s\n"), 1854d62bc4baSyz147064 strerror(errno), link); 18557c478bd9Sstevel@tonic-gate return (NULL); 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate 1858d62bc4baSyz147064 (void) snprintf(resource, RCM_LINK_RESOURCE_MAX, "%s/%u", 1859d62bc4baSyz147064 RCM_LINK_PREFIX, linkid); 18607c478bd9Sstevel@tonic-gate 1861d62bc4baSyz147064 return (resource); 1862d62bc4baSyz147064 1863d62bc4baSyz147064 fail: 1864d62bc4baSyz147064 rcm_log_message(RCM_ERROR, 1865d62bc4baSyz147064 _("IP: get_link_resource for %s error(%s)\n"), 1866d62bc4baSyz147064 link, dladm_status2str(status, errmsg)); 1867d62bc4baSyz147064 return (NULL); 18687c478bd9Sstevel@tonic-gate } 18697c478bd9Sstevel@tonic-gate 18707c478bd9Sstevel@tonic-gate /* 18717c478bd9Sstevel@tonic-gate * modop() - Remove/insert a module 18727c478bd9Sstevel@tonic-gate */ 18737c478bd9Sstevel@tonic-gate static int 18747c478bd9Sstevel@tonic-gate modop(char *name, char *arg, int pos, char op) 18757c478bd9Sstevel@tonic-gate { 18767c478bd9Sstevel@tonic-gate char syscmd[LIFNAMSIZ+MAXPATHLEN]; /* must be big enough */ 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: modop(%s)\n", name); 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate /* Nothing to do with "ip", "arp" */ 18817c478bd9Sstevel@tonic-gate if ((arg == NULL) || (strcmp(arg, "") == 0) || 18827c478bd9Sstevel@tonic-gate STREQ(arg, IP_MOD_NAME) || STREQ(arg, ARP_MOD_NAME)) { 18837c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: modop success\n"); 18847c478bd9Sstevel@tonic-gate return (0); 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate if (op == MOD_CHECK) { 18887c478bd9Sstevel@tonic-gate /* 18897c478bd9Sstevel@tonic-gate * No known good modules (yet) apart from ip and arp 18907c478bd9Sstevel@tonic-gate * which are handled above 18917c478bd9Sstevel@tonic-gate */ 18927c478bd9Sstevel@tonic-gate return (-1); 18937c478bd9Sstevel@tonic-gate } 18947c478bd9Sstevel@tonic-gate 18957c478bd9Sstevel@tonic-gate if (op == MOD_REMOVE) { 18967c478bd9Sstevel@tonic-gate (void) snprintf(syscmd, sizeof (syscmd), 1897e11c3f44Smeem "%s %s modremove %s@%d\n", SBIN_IFCONFIG, name, arg, pos); 18987c478bd9Sstevel@tonic-gate } else if (op == MOD_INSERT) { 18997c478bd9Sstevel@tonic-gate (void) snprintf(syscmd, sizeof (syscmd), 1900e11c3f44Smeem "%s %s modinsert %s@%d\n", SBIN_IFCONFIG, name, arg, pos); 19017c478bd9Sstevel@tonic-gate } else { 19027c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 19037c478bd9Sstevel@tonic-gate _("IP: modop(%s): unknown operation\n"), name); 19047c478bd9Sstevel@tonic-gate return (-1); 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: modop(%s): %s\n", name, syscmd); 19087c478bd9Sstevel@tonic-gate if (rcm_exec_cmd(syscmd) == -1) { 19097c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 19107c478bd9Sstevel@tonic-gate _("IP: modop(%s): %s\n"), name, strerror(errno)); 19117c478bd9Sstevel@tonic-gate return (-1); 19127c478bd9Sstevel@tonic-gate } 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: modop success\n"); 19157c478bd9Sstevel@tonic-gate return (0); 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate /* 19197c478bd9Sstevel@tonic-gate * get_modlist() - return a list of pushed mid-stream modules 19207c478bd9Sstevel@tonic-gate * Required memory is malloced to construct the list, 19217c478bd9Sstevel@tonic-gate * Caller must free this memory list 19227c478bd9Sstevel@tonic-gate * Call with cache_lock held 19237c478bd9Sstevel@tonic-gate */ 19247c478bd9Sstevel@tonic-gate static int 19257c478bd9Sstevel@tonic-gate get_modlist(char *name, ip_lif_t *lif) 19267c478bd9Sstevel@tonic-gate { 1927fc80c0dfSnordmark int mux_fd; 1928fc80c0dfSnordmark int muxid_fd; 19297c478bd9Sstevel@tonic-gate int fd; 19307c478bd9Sstevel@tonic-gate int i; 19317c478bd9Sstevel@tonic-gate int num_mods; 19327c478bd9Sstevel@tonic-gate struct lifreq lifr; 1933e11c3f44Smeem struct str_list strlist = { 0 }; 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: getmodlist(%s)\n", name); 19367c478bd9Sstevel@tonic-gate 1937e11c3f44Smeem (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name)); 19387c478bd9Sstevel@tonic-gate lifr.lifr_flags = lif->li_ifflags; 1939fc80c0dfSnordmark if (ip_domux2fd(&mux_fd, &muxid_fd, &fd, &lifr) < 0) { 19407c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: ip_domux2fd(%s)\n"), name); 19417c478bd9Sstevel@tonic-gate return (-1); 19427c478bd9Sstevel@tonic-gate } 19437c478bd9Sstevel@tonic-gate 19447c478bd9Sstevel@tonic-gate if ((num_mods = ioctl(fd, I_LIST, NULL)) < 0) { 19457c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 19467c478bd9Sstevel@tonic-gate _("IP: get_modlist(%s): I_LIST(%s) \n"), 19477c478bd9Sstevel@tonic-gate name, strerror(errno)); 1948e11c3f44Smeem goto fail; 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate 19517c478bd9Sstevel@tonic-gate strlist.sl_nmods = num_mods; 19527c478bd9Sstevel@tonic-gate strlist.sl_modlist = malloc(sizeof (struct str_mlist) * num_mods); 19537c478bd9Sstevel@tonic-gate if (strlist.sl_modlist == NULL) { 19547c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: get_modlist(%s): %s\n"), 19557c478bd9Sstevel@tonic-gate name, strerror(errno)); 1956e11c3f44Smeem goto fail; 19577c478bd9Sstevel@tonic-gate } 19587c478bd9Sstevel@tonic-gate 19597c478bd9Sstevel@tonic-gate if (ioctl(fd, I_LIST, (caddr_t)&strlist) < 0) { 19607c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 19617c478bd9Sstevel@tonic-gate _("IP: get_modlist(%s): I_LIST error: %s\n"), 19627c478bd9Sstevel@tonic-gate name, strerror(errno)); 1963e11c3f44Smeem goto fail; 19647c478bd9Sstevel@tonic-gate } 19657c478bd9Sstevel@tonic-gate 19667c478bd9Sstevel@tonic-gate for (i = 0; i < strlist.sl_nmods; i++) { 1967e11c3f44Smeem lif->li_modules[i] = strdup(strlist.sl_modlist[i].l_name); 19687c478bd9Sstevel@tonic-gate if (lif->li_modules[i] == NULL) { 19697c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 19707c478bd9Sstevel@tonic-gate _("IP: get_modlist(%s): %s\n"), 19717c478bd9Sstevel@tonic-gate name, strerror(errno)); 1972e11c3f44Smeem while (i > 0) 1973e11c3f44Smeem free(lif->li_modules[--i]); 1974e11c3f44Smeem goto fail; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate } 19777c478bd9Sstevel@tonic-gate 19787c478bd9Sstevel@tonic-gate lif->li_modcnt = strlist.sl_nmods; 19797c478bd9Sstevel@tonic-gate free(strlist.sl_modlist); 19807c478bd9Sstevel@tonic-gate 19817c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: getmodlist(%s) success\n", name); 1982fc80c0dfSnordmark return (ip_plink(mux_fd, muxid_fd, fd, &lifr)); 1983e11c3f44Smeem fail: 1984e11c3f44Smeem free(strlist.sl_modlist); 1985e11c3f44Smeem (void) ip_plink(mux_fd, muxid_fd, fd, &lifr); 1986e11c3f44Smeem return (-1); 19877c478bd9Sstevel@tonic-gate } 19887c478bd9Sstevel@tonic-gate 19897c478bd9Sstevel@tonic-gate /* 19907c478bd9Sstevel@tonic-gate * ip_domux2fd() - Helper function for mod*() functions 19917c478bd9Sstevel@tonic-gate * Stolen from ifconfig.c 19927c478bd9Sstevel@tonic-gate */ 19937c478bd9Sstevel@tonic-gate static int 1994fc80c0dfSnordmark ip_domux2fd(int *mux_fd, int *muxid_fdp, int *fd, struct lifreq *lifr) 19957c478bd9Sstevel@tonic-gate { 1996fc80c0dfSnordmark int muxid_fd; 19977c478bd9Sstevel@tonic-gate char *udp_dev_name; 19987c478bd9Sstevel@tonic-gate 19997c478bd9Sstevel@tonic-gate if (lifr->lifr_flags & IFF_IPV6) { 20007c478bd9Sstevel@tonic-gate udp_dev_name = UDP6_DEV_NAME; 20017c478bd9Sstevel@tonic-gate } else { 20027c478bd9Sstevel@tonic-gate udp_dev_name = UDP_DEV_NAME; 20037c478bd9Sstevel@tonic-gate } 20047c478bd9Sstevel@tonic-gate 2005fc80c0dfSnordmark if ((muxid_fd = open(udp_dev_name, O_RDWR)) < 0) { 20067c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: ip_domux2fd: open(%s) %s\n"), 20077c478bd9Sstevel@tonic-gate udp_dev_name, strerror(errno)); 20087c478bd9Sstevel@tonic-gate return (-1); 20097c478bd9Sstevel@tonic-gate } 2010fc80c0dfSnordmark if ((*mux_fd = open(udp_dev_name, O_RDWR)) < 0) { 2011fc80c0dfSnordmark rcm_log_message(RCM_ERROR, _("IP: ip_domux2fd: open(%s) %s\n"), 2012fc80c0dfSnordmark udp_dev_name, strerror(errno)); 2013fc80c0dfSnordmark (void) close(muxid_fd); 2014fc80c0dfSnordmark return (-1); 2015fc80c0dfSnordmark } 2016fc80c0dfSnordmark if (ioctl(muxid_fd, SIOCGLIFMUXID, (caddr_t)lifr) < 0) { 20177c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 20187c478bd9Sstevel@tonic-gate _("IP: ip_domux2fd: SIOCGLIFMUXID(%s): %s\n"), 2019fc80c0dfSnordmark udp_dev_name, strerror(errno)); 2020fc80c0dfSnordmark (void) close(*mux_fd); 2021fc80c0dfSnordmark (void) close(muxid_fd); 20227c478bd9Sstevel@tonic-gate return (-1); 20237c478bd9Sstevel@tonic-gate } 20247c478bd9Sstevel@tonic-gate 20257c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, 20267c478bd9Sstevel@tonic-gate "IP: ip_domux2fd: ARP_muxid %d IP_muxid %d\n", 20277c478bd9Sstevel@tonic-gate lifr->lifr_arp_muxid, lifr->lifr_ip_muxid); 20287c478bd9Sstevel@tonic-gate 2029fc80c0dfSnordmark if ((*fd = ioctl(*mux_fd, _I_MUXID2FD, lifr->lifr_ip_muxid)) < 0) { 20307c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 20317c478bd9Sstevel@tonic-gate _("IP: ip_domux2fd: _I_MUXID2FD(%s): %s\n"), 20327c478bd9Sstevel@tonic-gate udp_dev_name, strerror(errno)); 2033fc80c0dfSnordmark (void) close(*mux_fd); 2034fc80c0dfSnordmark (void) close(muxid_fd); 20357c478bd9Sstevel@tonic-gate return (-1); 20367c478bd9Sstevel@tonic-gate } 2037fc80c0dfSnordmark if (ioctl(*mux_fd, I_PUNLINK, lifr->lifr_ip_muxid) < 0) { 20387c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 20397c478bd9Sstevel@tonic-gate _("IP: ip_domux2fd: I_PUNLINK(%s): %s\n"), 20407c478bd9Sstevel@tonic-gate udp_dev_name, strerror(errno)); 2041fc80c0dfSnordmark (void) close(*mux_fd); 2042fc80c0dfSnordmark (void) close(muxid_fd); 20437c478bd9Sstevel@tonic-gate return (-1); 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate 2046fc80c0dfSnordmark /* Note: mux_fd and muxid_fd are closed in ip_plink below */ 2047fc80c0dfSnordmark *muxid_fdp = muxid_fd; 20487c478bd9Sstevel@tonic-gate return (0); 20497c478bd9Sstevel@tonic-gate } 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate /* 20527c478bd9Sstevel@tonic-gate * ip_plink() - Helper function for mod*() functions. 20537c478bd9Sstevel@tonic-gate * Stolen from ifconfig.c 20547c478bd9Sstevel@tonic-gate */ 20557c478bd9Sstevel@tonic-gate static int 2056fc80c0dfSnordmark ip_plink(int mux_fd, int muxid_fd, int fd, struct lifreq *lifr) 20577c478bd9Sstevel@tonic-gate { 20587c478bd9Sstevel@tonic-gate int mux_id; 20597c478bd9Sstevel@tonic-gate 2060fc80c0dfSnordmark if ((mux_id = ioctl(mux_fd, I_PLINK, fd)) < 0) { 20617c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, _("IP: ip_plink I_PLINK(%s): %s\n"), 20627c478bd9Sstevel@tonic-gate UDP_DEV_NAME, strerror(errno)); 2063fc80c0dfSnordmark (void) close(mux_fd); 2064fc80c0dfSnordmark (void) close(muxid_fd); 20657c478bd9Sstevel@tonic-gate (void) close(fd); 20667c478bd9Sstevel@tonic-gate return (-1); 20677c478bd9Sstevel@tonic-gate } 20687c478bd9Sstevel@tonic-gate 20697c478bd9Sstevel@tonic-gate lifr->lifr_ip_muxid = mux_id; 2070fc80c0dfSnordmark if (ioctl(muxid_fd, SIOCSLIFMUXID, (caddr_t)lifr) < 0) { 20717c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 20727c478bd9Sstevel@tonic-gate _("IP: ip_plink SIOCSLIFMUXID(%s): %s\n"), 20737c478bd9Sstevel@tonic-gate UDP_DEV_NAME, strerror(errno)); 2074fc80c0dfSnordmark (void) close(mux_fd); 2075fc80c0dfSnordmark (void) close(muxid_fd); 20767c478bd9Sstevel@tonic-gate (void) close(fd); 20777c478bd9Sstevel@tonic-gate return (-1); 20787c478bd9Sstevel@tonic-gate } 20797c478bd9Sstevel@tonic-gate 2080fc80c0dfSnordmark (void) close(mux_fd); 2081fc80c0dfSnordmark (void) close(muxid_fd); 20827c478bd9Sstevel@tonic-gate (void) close(fd); 20837c478bd9Sstevel@tonic-gate return (0); 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate 20867c478bd9Sstevel@tonic-gate /* 20877c478bd9Sstevel@tonic-gate * ip_onlinelist() 20887c478bd9Sstevel@tonic-gate * 20897c478bd9Sstevel@tonic-gate * Notify online to IP address consumers. 20907c478bd9Sstevel@tonic-gate */ 2091e11c3f44Smeem /*ARGSUSED*/ 20927c478bd9Sstevel@tonic-gate static int 20937c478bd9Sstevel@tonic-gate ip_onlinelist(rcm_handle_t *hd, ip_cache_t *node, char **errorp, uint_t flags, 20947c478bd9Sstevel@tonic-gate rcm_info_t **depend_info) 20957c478bd9Sstevel@tonic-gate { 20967c478bd9Sstevel@tonic-gate char **addrlist; 20977c478bd9Sstevel@tonic-gate int ret = RCM_SUCCESS; 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_onlinelist\n"); 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate addrlist = ip_get_addrlist(node); 21027c478bd9Sstevel@tonic-gate if (addrlist == NULL || addrlist[0] == NULL) { 21037c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_onlinelist none\n"); 21047c478bd9Sstevel@tonic-gate ip_free_addrlist(addrlist); 21057c478bd9Sstevel@tonic-gate return (ret); 21067c478bd9Sstevel@tonic-gate } 21077c478bd9Sstevel@tonic-gate 21087c478bd9Sstevel@tonic-gate ret = rcm_notify_online_list(hd, addrlist, 0, depend_info); 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate ip_free_addrlist(addrlist); 21117c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_onlinelist done\n"); 21127c478bd9Sstevel@tonic-gate return (ret); 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate /* 21167c478bd9Sstevel@tonic-gate * ip_offlinelist() 21177c478bd9Sstevel@tonic-gate * 21187c478bd9Sstevel@tonic-gate * Offline IP address consumers. 21197c478bd9Sstevel@tonic-gate */ 2120e11c3f44Smeem /*ARGSUSED*/ 21217c478bd9Sstevel@tonic-gate static int 21227c478bd9Sstevel@tonic-gate ip_offlinelist(rcm_handle_t *hd, ip_cache_t *node, char **errorp, uint_t flags, 21237c478bd9Sstevel@tonic-gate rcm_info_t **depend_info) 21247c478bd9Sstevel@tonic-gate { 21257c478bd9Sstevel@tonic-gate char **addrlist; 21267c478bd9Sstevel@tonic-gate int ret = RCM_SUCCESS; 21277c478bd9Sstevel@tonic-gate 21287c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_offlinelist\n"); 21297c478bd9Sstevel@tonic-gate 21307c478bd9Sstevel@tonic-gate addrlist = ip_get_addrlist(node); 21317c478bd9Sstevel@tonic-gate if (addrlist == NULL || addrlist[0] == NULL) { 21327c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_offlinelist none\n"); 21337c478bd9Sstevel@tonic-gate ip_free_addrlist(addrlist); 21347c478bd9Sstevel@tonic-gate return (RCM_SUCCESS); 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate 21377c478bd9Sstevel@tonic-gate if ((ret = rcm_request_offline_list(hd, addrlist, flags, depend_info)) 21387c478bd9Sstevel@tonic-gate != RCM_SUCCESS) { 21397c478bd9Sstevel@tonic-gate if (ret == RCM_FAILURE) 21407c478bd9Sstevel@tonic-gate (void) rcm_notify_online_list(hd, addrlist, 0, NULL); 21417c478bd9Sstevel@tonic-gate 21427c478bd9Sstevel@tonic-gate ret = RCM_FAILURE; 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate ip_free_addrlist(addrlist); 21467c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_offlinelist done\n"); 21477c478bd9Sstevel@tonic-gate return (ret); 21487c478bd9Sstevel@tonic-gate } 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate /* 2151e11c3f44Smeem * ip_get_addrlist() - Get the list of IP addresses on this interface (node); 2152e11c3f44Smeem * This routine malloc()s required memory for the list. 2153e11c3f44Smeem * Returns the list on success, NULL on failure. 21547c478bd9Sstevel@tonic-gate * Call with cache_lock held. 21557c478bd9Sstevel@tonic-gate */ 21567c478bd9Sstevel@tonic-gate static char ** 21577c478bd9Sstevel@tonic-gate ip_get_addrlist(ip_cache_t *node) 21587c478bd9Sstevel@tonic-gate { 21597c478bd9Sstevel@tonic-gate ip_lif_t *lif; 21607c478bd9Sstevel@tonic-gate char **addrlist = NULL; 2161e11c3f44Smeem int i, numifs; 2162e11c3f44Smeem size_t addrlistsize; 21637c478bd9Sstevel@tonic-gate char addrstr[INET6_ADDRSTRLEN]; 21647c478bd9Sstevel@tonic-gate 21657c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_get_addrlist(%s)\n", 21667c478bd9Sstevel@tonic-gate node->ip_resource); 21677c478bd9Sstevel@tonic-gate 21687c478bd9Sstevel@tonic-gate numifs = 0; 21697c478bd9Sstevel@tonic-gate for (lif = node->ip_pif->pi_lifs; lif != NULL; lif = lif->li_next) { 21707c478bd9Sstevel@tonic-gate numifs++; 21717c478bd9Sstevel@tonic-gate } 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate /* 21747c478bd9Sstevel@tonic-gate * Allocate space for resource names list; add 1 and use calloc() 21757c478bd9Sstevel@tonic-gate * so that the list is NULL-terminated. 21767c478bd9Sstevel@tonic-gate */ 21777c478bd9Sstevel@tonic-gate if ((addrlist = calloc(numifs + 1, sizeof (char *))) == NULL) { 21787c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 21797c478bd9Sstevel@tonic-gate _("IP: ip_get_addrlist(%s) malloc failure(%s)\n"), 21807c478bd9Sstevel@tonic-gate node->ip_resource, strerror(errno)); 21817c478bd9Sstevel@tonic-gate return (NULL); 21827c478bd9Sstevel@tonic-gate } 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate for (lif = node->ip_pif->pi_lifs, i = 0; lif != NULL; 21857c478bd9Sstevel@tonic-gate lif = lif->li_next, i++) { 21867c478bd9Sstevel@tonic-gate 2187e11c3f44Smeem if (!ip_addrstr(lif, addrstr, sizeof (addrstr))) { 21887c478bd9Sstevel@tonic-gate ip_free_addrlist(addrlist); 21897c478bd9Sstevel@tonic-gate return (NULL); 21907c478bd9Sstevel@tonic-gate } 21917c478bd9Sstevel@tonic-gate 2192e11c3f44Smeem addrlistsize = strlen(addrstr) + sizeof (RCM_STR_SUNW_IP); 2193e11c3f44Smeem if ((addrlist[i] = malloc(addrlistsize)) == NULL) { 21947c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 21957c478bd9Sstevel@tonic-gate _("IP: ip_get_addrlist(%s) malloc failure(%s)\n"), 21967c478bd9Sstevel@tonic-gate node->ip_resource, strerror(errno)); 21977c478bd9Sstevel@tonic-gate ip_free_addrlist(addrlist); 21987c478bd9Sstevel@tonic-gate return (NULL); 21997c478bd9Sstevel@tonic-gate } 2200e11c3f44Smeem (void) snprintf(addrlist[i], addrlistsize, "%s%s", 2201e11c3f44Smeem RCM_STR_SUNW_IP, addrstr); 22027c478bd9Sstevel@tonic-gate 22037c478bd9Sstevel@tonic-gate rcm_log_message(RCM_DEBUG, "Anon Address: %s\n", addrlist[i]); 22047c478bd9Sstevel@tonic-gate } 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: get_addrlist (%s) done\n", 22077c478bd9Sstevel@tonic-gate node->ip_resource); 22087c478bd9Sstevel@tonic-gate 22097c478bd9Sstevel@tonic-gate return (addrlist); 22107c478bd9Sstevel@tonic-gate } 22117c478bd9Sstevel@tonic-gate 22127c478bd9Sstevel@tonic-gate static void 22137c478bd9Sstevel@tonic-gate ip_free_addrlist(char **addrlist) 22147c478bd9Sstevel@tonic-gate { 22157c478bd9Sstevel@tonic-gate int i; 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate if (addrlist == NULL) 22187c478bd9Sstevel@tonic-gate return; 22197c478bd9Sstevel@tonic-gate 22207c478bd9Sstevel@tonic-gate for (i = 0; addrlist[i] != NULL; i++) 22217c478bd9Sstevel@tonic-gate free(addrlist[i]); 22227c478bd9Sstevel@tonic-gate free(addrlist); 22237c478bd9Sstevel@tonic-gate } 22247c478bd9Sstevel@tonic-gate 22257c478bd9Sstevel@tonic-gate /* 22267c478bd9Sstevel@tonic-gate * ip_consumer_notify() - Notify consumers of IP addresses coming back online. 22277c478bd9Sstevel@tonic-gate */ 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate static void 2230d62bc4baSyz147064 ip_consumer_notify(rcm_handle_t *hd, datalink_id_t linkid, char **errorp, 2231d62bc4baSyz147064 uint_t flags, rcm_info_t **depend_info) 22327c478bd9Sstevel@tonic-gate { 2233d62bc4baSyz147064 char cached_name[RCM_LINK_RESOURCE_MAX]; 22347c478bd9Sstevel@tonic-gate ip_cache_t *node; 22357c478bd9Sstevel@tonic-gate 2236d62bc4baSyz147064 assert(linkid != DATALINK_INVALID_LINKID); 22377c478bd9Sstevel@tonic-gate 2238d62bc4baSyz147064 rcm_log_message(RCM_TRACE1, _("IP: ip_consumer_notify(%u)\n"), linkid); 22397c478bd9Sstevel@tonic-gate 22407c478bd9Sstevel@tonic-gate /* Check for the interface in the cache */ 2241d62bc4baSyz147064 (void) snprintf(cached_name, sizeof (cached_name), "%s/%u", 2242d62bc4baSyz147064 RCM_LINK_PREFIX, linkid); 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 22457c478bd9Sstevel@tonic-gate if ((node = cache_lookup(hd, cached_name, CACHE_REFRESH)) == NULL) { 2246d62bc4baSyz147064 rcm_log_message(RCM_TRACE1, _("IP: Skipping interface(%u)\n"), 2247d62bc4baSyz147064 linkid); 22487c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 22497c478bd9Sstevel@tonic-gate return; 22507c478bd9Sstevel@tonic-gate } 22517c478bd9Sstevel@tonic-gate /* 2252e11c3f44Smeem * Inform anonymous consumers about IP addresses being onlined. 22537c478bd9Sstevel@tonic-gate */ 22547c478bd9Sstevel@tonic-gate (void) ip_onlinelist(hd, node, errorp, flags, depend_info); 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE2, "IP: ip_consumer_notify success\n"); 22597c478bd9Sstevel@tonic-gate } 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate /* 22626e91bba0SGirish Moodalbail * Gets the interface name for the given linkid. Returns -1 if there is 22636e91bba0SGirish Moodalbail * any error. It fills in the interface name in `ifinst' if the interface 22646e91bba0SGirish Moodalbail * is not already configured. Otherwise, it puts a null string in `ifinst'. 22657c478bd9Sstevel@tonic-gate */ 22667c478bd9Sstevel@tonic-gate static int 22676e91bba0SGirish Moodalbail if_configure_get_linkid(datalink_id_t linkid, char *ifinst, size_t len) 22687c478bd9Sstevel@tonic-gate { 2269d62bc4baSyz147064 char cached_name[RCM_LINK_RESOURCE_MAX]; 22707c478bd9Sstevel@tonic-gate ip_cache_t *node; 22717c478bd9Sstevel@tonic-gate 22727c478bd9Sstevel@tonic-gate /* Check for the interface in the cache */ 2273d62bc4baSyz147064 (void) snprintf(cached_name, sizeof (cached_name), "%s/%u", 2274d62bc4baSyz147064 RCM_LINK_PREFIX, linkid); 22757c478bd9Sstevel@tonic-gate 2276e11c3f44Smeem /* Check if the interface is new or was not previously offlined */ 22777c478bd9Sstevel@tonic-gate (void) mutex_lock(&cache_lock); 22787c478bd9Sstevel@tonic-gate if (((node = cache_lookup(NULL, cached_name, CACHE_REFRESH)) != NULL) && 22797c478bd9Sstevel@tonic-gate (!(node->ip_cachestate & CACHE_IF_OFFLINED))) { 22807c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, 2281d62bc4baSyz147064 _("IP: Skipping configured interface(%u)\n"), linkid); 22827c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 22836e91bba0SGirish Moodalbail *ifinst = '\0'; 22847c478bd9Sstevel@tonic-gate return (0); 22857c478bd9Sstevel@tonic-gate } 22867c478bd9Sstevel@tonic-gate (void) mutex_unlock(&cache_lock); 22877c478bd9Sstevel@tonic-gate 22884ac67f02SAnurag S. Maskey if (dladm_datalink_id2info(dld_handle, linkid, NULL, NULL, NULL, ifinst, 22896e91bba0SGirish Moodalbail len) != DLADM_STATUS_OK) { 2290d62bc4baSyz147064 rcm_log_message(RCM_ERROR, 2291d62bc4baSyz147064 _("IP: get %u link name failed\n"), linkid); 2292d62bc4baSyz147064 return (-1); 2293d62bc4baSyz147064 } 22946e91bba0SGirish Moodalbail return (0); 22956e91bba0SGirish Moodalbail } 22966e91bba0SGirish Moodalbail 22976e91bba0SGirish Moodalbail /* 22986e91bba0SGirish Moodalbail * if_configure_hostname() - Configure a physical interface after attach 22996e91bba0SGirish Moodalbail * based on the information in /etc/hostname.* 23006e91bba0SGirish Moodalbail */ 23016e91bba0SGirish Moodalbail static int 23026e91bba0SGirish Moodalbail if_configure_hostname(datalink_id_t linkid) 23036e91bba0SGirish Moodalbail { 23046e91bba0SGirish Moodalbail FILE *hostfp, *host6fp; 23056e91bba0SGirish Moodalbail boolean_t ipmp = B_FALSE; 23066e91bba0SGirish Moodalbail char ifinst[MAXLINKNAMELEN]; 23076e91bba0SGirish Moodalbail char cfgfile[MAXPATHLEN]; 23086e91bba0SGirish Moodalbail 23096e91bba0SGirish Moodalbail assert(linkid != DATALINK_INVALID_LINKID); 23106e91bba0SGirish Moodalbail rcm_log_message(RCM_TRACE1, _("IP: if_configure_hostname(%u)\n"), 23116e91bba0SGirish Moodalbail linkid); 23126e91bba0SGirish Moodalbail 23136e91bba0SGirish Moodalbail if (if_configure_get_linkid(linkid, ifinst, sizeof (ifinst)) != 0) 23146e91bba0SGirish Moodalbail return (-1); 23156e91bba0SGirish Moodalbail 23166e91bba0SGirish Moodalbail /* Check if the interface is already configured. */ 23176e91bba0SGirish Moodalbail if (ifinst[0] == '\0') 23186e91bba0SGirish Moodalbail return (0); 2319d62bc4baSyz147064 2320e11c3f44Smeem /* 2321e11c3f44Smeem * Scan the IPv4 and IPv6 hostname files to see if (a) they exist 2322e11c3f44Smeem * and (b) if either one places the interface into an IPMP group. 2323e11c3f44Smeem */ 2324e11c3f44Smeem (void) snprintf(cfgfile, MAXPATHLEN, CFGFILE_FMT_IPV4, ifinst); 23257c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: Scanning %s\n", cfgfile); 2326e11c3f44Smeem if ((hostfp = fopen(cfgfile, "r")) != NULL) { 2327e11c3f44Smeem if (isgrouped(cfgfile)) 2328e11c3f44Smeem ipmp = B_TRUE; 23297c478bd9Sstevel@tonic-gate } 23307c478bd9Sstevel@tonic-gate 2331e11c3f44Smeem (void) snprintf(cfgfile, MAXPATHLEN, CFGFILE_FMT_IPV6, ifinst); 23327c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: Scanning %s\n", cfgfile); 2333e11c3f44Smeem if ((host6fp = fopen(cfgfile, "r")) != NULL) { 2334e11c3f44Smeem if (!ipmp && isgrouped(cfgfile)) 2335e11c3f44Smeem ipmp = B_TRUE; 23367c478bd9Sstevel@tonic-gate } 23377c478bd9Sstevel@tonic-gate 23387c478bd9Sstevel@tonic-gate /* 2339e11c3f44Smeem * Configure the interface according to its hostname files. 23407c478bd9Sstevel@tonic-gate */ 2341e11c3f44Smeem if (hostfp != NULL && 2342e11c3f44Smeem if_config_inst(ifinst, hostfp, AF_INET, ipmp) == -1) { 2343e11c3f44Smeem rcm_log_message(RCM_ERROR, 2344e11c3f44Smeem _("IP: IPv4 Post-attach failed (%s)\n"), ifinst); 2345e11c3f44Smeem goto fail; 2346e11c3f44Smeem } 2347e11c3f44Smeem 2348e11c3f44Smeem if (host6fp != NULL && 2349e11c3f44Smeem if_config_inst(ifinst, host6fp, AF_INET6, ipmp) == -1) { 2350e11c3f44Smeem rcm_log_message(RCM_ERROR, 2351e11c3f44Smeem _("IP: IPv6 Post-attach failed (%s)\n"), ifinst); 2352e11c3f44Smeem goto fail; 2353e11c3f44Smeem } 2354e11c3f44Smeem 2355e11c3f44Smeem (void) fclose(hostfp); 2356e11c3f44Smeem (void) fclose(host6fp); 23576e91bba0SGirish Moodalbail rcm_log_message(RCM_TRACE1, "IP: if_configure_hostname(%s) success\n", 23586e91bba0SGirish Moodalbail ifinst); 2359e11c3f44Smeem return (0); 2360e11c3f44Smeem fail: 2361e11c3f44Smeem (void) fclose(hostfp); 2362e11c3f44Smeem (void) fclose(host6fp); 2363e11c3f44Smeem return (-1); 2364e11c3f44Smeem } 2365e11c3f44Smeem 2366e11c3f44Smeem /* 23676e91bba0SGirish Moodalbail * if_configure_ipadm() - Configure a physical interface after attach 23686e91bba0SGirish Moodalbail * Queries libipadm for persistent configuration information and then 23696e91bba0SGirish Moodalbail * resurrects that persistent configuration. 23706e91bba0SGirish Moodalbail */ 23716e91bba0SGirish Moodalbail static int 23726e91bba0SGirish Moodalbail if_configure_ipadm(datalink_id_t linkid) 23736e91bba0SGirish Moodalbail { 23746e91bba0SGirish Moodalbail char ifinst[MAXLINKNAMELEN]; 23756e91bba0SGirish Moodalbail boolean_t found; 23766e91bba0SGirish Moodalbail ipadm_if_info_t *ifinfo, *ptr; 23776e91bba0SGirish Moodalbail ipadm_status_t status; 23786e91bba0SGirish Moodalbail 23796e91bba0SGirish Moodalbail assert(linkid != DATALINK_INVALID_LINKID); 23806e91bba0SGirish Moodalbail rcm_log_message(RCM_TRACE1, _("IP: if_configure_ipadm(%u)\n"), 23816e91bba0SGirish Moodalbail linkid); 23826e91bba0SGirish Moodalbail 23836e91bba0SGirish Moodalbail if (if_configure_get_linkid(linkid, ifinst, sizeof (ifinst)) != 0) 23846e91bba0SGirish Moodalbail return (-1); 23856e91bba0SGirish Moodalbail 23866e91bba0SGirish Moodalbail /* Check if the interface is already configured. */ 23876e91bba0SGirish Moodalbail if (ifinst[0] == '\0') 23886e91bba0SGirish Moodalbail return (0); 23896e91bba0SGirish Moodalbail 23906e91bba0SGirish Moodalbail status = ipadm_if_info(ip_handle, ifinst, &ifinfo, 0, LIFC_UNDER_IPMP); 23916e91bba0SGirish Moodalbail if (status == IPADM_ENXIO) 23926e91bba0SGirish Moodalbail goto done; 23936e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) { 23946e91bba0SGirish Moodalbail rcm_log_message(RCM_ERROR, 23956e91bba0SGirish Moodalbail _("IP: IPv4 Post-attach failed (%s) Error %s\n"), 23966e91bba0SGirish Moodalbail ifinst, ipadm_status2str(status)); 23976e91bba0SGirish Moodalbail goto fail; 23986e91bba0SGirish Moodalbail } 23996e91bba0SGirish Moodalbail if (ifinfo != NULL) { 24006e91bba0SGirish Moodalbail found = B_FALSE; 24016e91bba0SGirish Moodalbail for (ptr = ifinfo; ptr; ptr = ptr->ifi_next) { 24026e91bba0SGirish Moodalbail if (strncmp(ptr->ifi_name, ifinst, 24036e91bba0SGirish Moodalbail sizeof (ifinst)) == 0) { 24046e91bba0SGirish Moodalbail found = B_TRUE; 24056e91bba0SGirish Moodalbail break; 24066e91bba0SGirish Moodalbail } 24076e91bba0SGirish Moodalbail } 24086e91bba0SGirish Moodalbail free(ifinfo); 24096e91bba0SGirish Moodalbail if (!found) { 24106e91bba0SGirish Moodalbail return (0); 24116e91bba0SGirish Moodalbail } 24126e91bba0SGirish Moodalbail if (if_hostname_exists(ifinst, AF_INET) || 24136e91bba0SGirish Moodalbail if_hostname_exists(ifinst, AF_INET6)) { 24146e91bba0SGirish Moodalbail rcm_log_message(RCM_WARNING, 24156e91bba0SGirish Moodalbail _("IP: IPv4 Post-attach (%s) found both " 24166e91bba0SGirish Moodalbail "/etc/hostname and ipadm persistent configuration. " 24176e91bba0SGirish Moodalbail "Ignoring ipadm config\n"), ifinst); 24186e91bba0SGirish Moodalbail return (0); 24196e91bba0SGirish Moodalbail } 24206e91bba0SGirish Moodalbail status = ipadm_enable_if(ip_handle, ifinst, IPADM_OPT_ACTIVE); 24216e91bba0SGirish Moodalbail if (status != IPADM_SUCCESS) { 24226e91bba0SGirish Moodalbail rcm_log_message(RCM_ERROR, 24236e91bba0SGirish Moodalbail _("IP: Post-attach failed (%s) Error %s\n"), 24246e91bba0SGirish Moodalbail ifinst, ipadm_status2str(status)); 24256e91bba0SGirish Moodalbail goto fail; 24266e91bba0SGirish Moodalbail } 24276e91bba0SGirish Moodalbail } 24286e91bba0SGirish Moodalbail done: 24296e91bba0SGirish Moodalbail rcm_log_message(RCM_TRACE1, "IP: if_configure_ipadm(%s) success\n", 24306e91bba0SGirish Moodalbail ifinst); 24316e91bba0SGirish Moodalbail return (0); 24326e91bba0SGirish Moodalbail fail: 24336e91bba0SGirish Moodalbail return (-1); 24346e91bba0SGirish Moodalbail } 24356e91bba0SGirish Moodalbail 24366e91bba0SGirish Moodalbail /* 2437e11c3f44Smeem * isgrouped() - Scans the given config file to see if this interface is 2438e11c3f44Smeem * using IPMP. Returns B_TRUE or B_FALSE. 2439e11c3f44Smeem */ 2440e11c3f44Smeem static boolean_t 2441e11c3f44Smeem isgrouped(const char *cfgfile) 24427c478bd9Sstevel@tonic-gate { 24437c478bd9Sstevel@tonic-gate FILE *fp; 24447c478bd9Sstevel@tonic-gate struct stat statb; 2445e11c3f44Smeem char *nlp, *line, *token, *lasts, *buf; 2446e11c3f44Smeem boolean_t grouped = B_FALSE; 24477c478bd9Sstevel@tonic-gate 24487c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, "IP: isgrouped(%s)\n", cfgfile); 24497c478bd9Sstevel@tonic-gate 24507c478bd9Sstevel@tonic-gate if (stat(cfgfile, &statb) != 0) { 24517c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, 24527c478bd9Sstevel@tonic-gate _("IP: No config file(%s)\n"), cfgfile); 2453e11c3f44Smeem return (B_FALSE); 24547c478bd9Sstevel@tonic-gate } 24557c478bd9Sstevel@tonic-gate 24567c478bd9Sstevel@tonic-gate /* 24577c478bd9Sstevel@tonic-gate * We also ignore single-byte config files because the file should 24587c478bd9Sstevel@tonic-gate * always be newline-terminated, so we know there's nothing of 24597c478bd9Sstevel@tonic-gate * interest. Further, a single-byte file would cause the fgets() loop 24607c478bd9Sstevel@tonic-gate * below to spin forever. 24617c478bd9Sstevel@tonic-gate */ 24627c478bd9Sstevel@tonic-gate if (statb.st_size <= 1) { 24637c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, 24647c478bd9Sstevel@tonic-gate _("IP: Empty config file(%s)\n"), cfgfile); 2465e11c3f44Smeem return (B_FALSE); 24667c478bd9Sstevel@tonic-gate } 24677c478bd9Sstevel@tonic-gate 24687c478bd9Sstevel@tonic-gate if ((fp = fopen(cfgfile, "r")) == NULL) { 24697c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 24707c478bd9Sstevel@tonic-gate _("IP: Cannot open configuration file(%s): %s\n"), cfgfile, 24717c478bd9Sstevel@tonic-gate strerror(errno)); 2472e11c3f44Smeem return (B_FALSE); 24737c478bd9Sstevel@tonic-gate } 24747c478bd9Sstevel@tonic-gate 2475e11c3f44Smeem if ((buf = malloc(statb.st_size)) == NULL) { 24767c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 2477e11c3f44Smeem _("IP: malloc failure(%s): %s\n"), cfgfile, 24787c478bd9Sstevel@tonic-gate strerror(errno)); 2479e11c3f44Smeem goto out; 24807c478bd9Sstevel@tonic-gate } 24817c478bd9Sstevel@tonic-gate 24827c478bd9Sstevel@tonic-gate while (fgets(buf, statb.st_size, fp) != NULL) { 2483e11c3f44Smeem if ((nlp = strrchr(buf, '\n')) != NULL) 2484e11c3f44Smeem *nlp = '\0'; 24857c478bd9Sstevel@tonic-gate 2486e11c3f44Smeem line = buf; 2487e11c3f44Smeem while ((token = strtok_r(line, " \t", &lasts)) != NULL) { 2488e11c3f44Smeem line = NULL; 2489e11c3f44Smeem if (STREQ("group", token) && 2490e11c3f44Smeem strtok_r(NULL, " \t", &lasts) != NULL) { 2491e11c3f44Smeem grouped = B_TRUE; 2492e11c3f44Smeem goto out; 24937c478bd9Sstevel@tonic-gate } 24947c478bd9Sstevel@tonic-gate } 24957c478bd9Sstevel@tonic-gate } 2496e11c3f44Smeem out: 24977c478bd9Sstevel@tonic-gate free(buf); 24987c478bd9Sstevel@tonic-gate (void) fclose(fp); 24997c478bd9Sstevel@tonic-gate 2500e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: isgrouped(%s): %d\n", cfgfile, 2501e11c3f44Smeem grouped); 25027c478bd9Sstevel@tonic-gate 2503e11c3f44Smeem return (grouped); 2504e11c3f44Smeem } 25057c478bd9Sstevel@tonic-gate 25067c478bd9Sstevel@tonic-gate /* 2507e11c3f44Smeem * if_config_inst() - Configure an interface instance as specified by the 25087c478bd9Sstevel@tonic-gate * address family af and if it is grouped (ipmp). 25097c478bd9Sstevel@tonic-gate */ 25107c478bd9Sstevel@tonic-gate static int 2511e11c3f44Smeem if_config_inst(const char *ifinst, FILE *hfp, int af, boolean_t ipmp) 25127c478bd9Sstevel@tonic-gate { 2513e11c3f44Smeem FILE *ifparsefp; 25147c478bd9Sstevel@tonic-gate struct stat statb; 2515e11c3f44Smeem char *buf = NULL; 2516e11c3f44Smeem char *ifparsebuf = NULL; 2517e11c3f44Smeem uint_t ifparsebufsize; 2518e11c3f44Smeem const char *fstr; /* address family string */ 2519e11c3f44Smeem boolean_t stdif = B_FALSE; 25207c478bd9Sstevel@tonic-gate 2521e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: if_config_inst(%s) ipmp = %d\n", 25227c478bd9Sstevel@tonic-gate ifinst, ipmp); 25237c478bd9Sstevel@tonic-gate 2524e11c3f44Smeem if (fstat(fileno(hfp), &statb) != 0) { 2525e11c3f44Smeem rcm_log_message(RCM_ERROR, 2526e11c3f44Smeem _("IP: Cannot fstat file(%s)\n"), ifinst); 2527e11c3f44Smeem goto fail; 25287c478bd9Sstevel@tonic-gate } 25297c478bd9Sstevel@tonic-gate 2530e11c3f44Smeem switch (af) { 2531e11c3f44Smeem case AF_INET: 2532e11c3f44Smeem fstr = "inet"; 2533e11c3f44Smeem break; 2534e11c3f44Smeem case AF_INET6: 2535e11c3f44Smeem fstr = "inet6"; 2536e11c3f44Smeem break; 2537e11c3f44Smeem default: 2538e11c3f44Smeem assert(0); 25397c478bd9Sstevel@tonic-gate } 25407c478bd9Sstevel@tonic-gate 25417c478bd9Sstevel@tonic-gate /* 2542e11c3f44Smeem * The hostname file exists; plumb the physical interface. 25437c478bd9Sstevel@tonic-gate */ 2544e11c3f44Smeem if (!ifconfig(ifinst, fstr, "plumb", B_FALSE)) 2545e11c3f44Smeem goto fail; 25467c478bd9Sstevel@tonic-gate 2547e11c3f44Smeem /* Skip static configuration if the hostname file is empty */ 2548e11c3f44Smeem if (statb.st_size <= 1) { 25497c478bd9Sstevel@tonic-gate rcm_log_message(RCM_TRACE1, 2550e11c3f44Smeem _("IP: Zero size hostname file(%s)\n"), ifinst); 2551e11c3f44Smeem goto configured; 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate 2554e11c3f44Smeem if (fseek(hfp, 0, SEEK_SET) == -1) { 25557c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 2556e11c3f44Smeem _("IP: Cannot rewind hostname file(%s): %s\n"), ifinst, 2557e11c3f44Smeem strerror(errno)); 2558e11c3f44Smeem goto fail; 25597c478bd9Sstevel@tonic-gate } 25607c478bd9Sstevel@tonic-gate 2561e11c3f44Smeem /* 2562e11c3f44Smeem * Allocate the worst-case single-line buffer sizes. A bit skanky, 2563e11c3f44Smeem * but since hostname files are small, this should suffice. 2564e11c3f44Smeem */ 25657c478bd9Sstevel@tonic-gate if ((buf = calloc(1, statb.st_size)) == NULL) { 25667c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 25677c478bd9Sstevel@tonic-gate _("IP: calloc(%s): %s\n"), ifinst, strerror(errno)); 2568e11c3f44Smeem goto fail; 25697c478bd9Sstevel@tonic-gate } 25707c478bd9Sstevel@tonic-gate 2571e11c3f44Smeem ifparsebufsize = statb.st_size + sizeof (SBIN_IFPARSE " -s inet6 "); 2572e11c3f44Smeem if ((ifparsebuf = calloc(1, ifparsebufsize)) == NULL) { 2573e11c3f44Smeem rcm_log_message(RCM_ERROR, 2574e11c3f44Smeem _("IP: calloc(%s): %s\n"), ifinst, strerror(errno)); 2575e11c3f44Smeem goto fail; 25767c478bd9Sstevel@tonic-gate } 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate /* 2579e11c3f44Smeem * For IPv4, determine whether the hostname file consists of a single 2580e11c3f44Smeem * line. We need to handle these specially since they should 2581e11c3f44Smeem * automatically be suffixed with "netmask + broadcast + up". 25827c478bd9Sstevel@tonic-gate */ 2583e11c3f44Smeem if (af == AF_INET && 2584e11c3f44Smeem fgets(buf, statb.st_size, hfp) != NULL && 2585e11c3f44Smeem fgets(buf, statb.st_size, hfp) == NULL) { 2586e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: one-line hostname file\n"); 2587e11c3f44Smeem stdif = B_TRUE; 25887c478bd9Sstevel@tonic-gate } 2589e11c3f44Smeem 2590e11c3f44Smeem if (fseek(hfp, 0L, SEEK_SET) == -1) { 25917c478bd9Sstevel@tonic-gate rcm_log_message(RCM_ERROR, 2592e11c3f44Smeem _("IP: Cannot rewind hostname file(%s): %s\n"), ifinst, 25937c478bd9Sstevel@tonic-gate strerror(errno)); 2594e11c3f44Smeem goto fail; 25957c478bd9Sstevel@tonic-gate } 25967c478bd9Sstevel@tonic-gate 25977c478bd9Sstevel@tonic-gate /* 2598e11c3f44Smeem * Loop through the file one line at a time and feed it to ifconfig. 2599e11c3f44Smeem * If the interface is using IPMP, then we use /sbin/ifparse -s to 2600e11c3f44Smeem * weed out all of the data addresses, since those are already on the 2601e11c3f44Smeem * IPMP meta-interface. 26027c478bd9Sstevel@tonic-gate */ 2603e11c3f44Smeem while (fgets(buf, statb.st_size, hfp) != NULL) { 2604e11c3f44Smeem if (ntok(buf) == 0) 2605e11c3f44Smeem continue; 2606e11c3f44Smeem 2607e11c3f44Smeem if (!ipmp) { 2608e11c3f44Smeem (void) ifconfig(ifinst, fstr, buf, stdif); 2609e11c3f44Smeem continue; 2610e11c3f44Smeem } 2611e11c3f44Smeem 2612e11c3f44Smeem (void) snprintf(ifparsebuf, ifparsebufsize, SBIN_IFPARSE 2613e11c3f44Smeem " -s %s %s", fstr, buf); 2614e11c3f44Smeem if ((ifparsefp = popen(ifparsebuf, "r")) == NULL) { 2615e11c3f44Smeem rcm_log_message(RCM_ERROR, 2616e11c3f44Smeem _("IP: cannot configure %s: popen \"%s\" " 2617e11c3f44Smeem "failed: %s\n"), ifinst, buf, strerror(errno)); 2618e11c3f44Smeem goto fail; 2619e11c3f44Smeem } 2620e11c3f44Smeem 2621e11c3f44Smeem while (fgets(buf, statb.st_size, ifparsefp) != NULL) { 2622e11c3f44Smeem if (ntok(buf) > 0) 2623e11c3f44Smeem (void) ifconfig(ifinst, fstr, buf, stdif); 2624e11c3f44Smeem } 2625e11c3f44Smeem 2626e11c3f44Smeem if (pclose(ifparsefp) == -1) { 2627e11c3f44Smeem rcm_log_message(RCM_ERROR, 2628e11c3f44Smeem _("IP: cannot configure %s: pclose \"%s\" " 2629e11c3f44Smeem "failed: %s\n"), ifinst, buf, strerror(errno)); 2630e11c3f44Smeem goto fail; 26317c478bd9Sstevel@tonic-gate } 26327c478bd9Sstevel@tonic-gate } 26337c478bd9Sstevel@tonic-gate 2634e11c3f44Smeem configured: 2635e11c3f44Smeem /* 2636e11c3f44Smeem * Bring up the interface (it may already be up) 2637e11c3f44Smeem * 2638e11c3f44Smeem * Technically, since the boot scripts only unconditionally bring up 2639e11c3f44Smeem * IPv6 interfaces, we should only unconditionally bring up IPv6 here. 2640e11c3f44Smeem * However, if we don't bring up IPv4, and a legacy IPMP configuration 2641e11c3f44Smeem * without test addresses is being used, we will never bring the 2642e11c3f44Smeem * interface up even though we would've at boot. One fix is to check 2643e11c3f44Smeem * if the IPv4 hostname file contains data addresses that we would've 2644e11c3f44Smeem * brought up, but there's no simple way to do that. Given that it's 2645e11c3f44Smeem * rare to have persistent IP configuration for an interface that 2646e11c3f44Smeem * leaves it down, we cheap out and always bring it up for IPMP. 2647e11c3f44Smeem */ 2648e11c3f44Smeem if ((af == AF_INET6 || ipmp) && !ifconfig(ifinst, fstr, "up", B_FALSE)) 2649e11c3f44Smeem goto fail; 2650e11c3f44Smeem 2651e11c3f44Smeem /* 2652e11c3f44Smeem * For IPv4, if a DHCP configuration file exists, have DHCP configure 2653e11c3f44Smeem * the interface. As with the boot scripts, this is done after the 2654e11c3f44Smeem * hostname files are processed so that configuration in those files 2655e11c3f44Smeem * (such as IPMP group names) will be applied first. 2656e11c3f44Smeem */ 2657e11c3f44Smeem if (af == AF_INET) { 2658e11c3f44Smeem char dhcpfile[MAXPATHLEN]; 2659e11c3f44Smeem char *dhcpbuf; 2660e11c3f44Smeem off_t i, dhcpsize; 2661e11c3f44Smeem 2662e11c3f44Smeem (void) snprintf(dhcpfile, MAXPATHLEN, DHCPFILE_FMT, ifinst); 2663e11c3f44Smeem if (stat(dhcpfile, &statb) == -1) 2664e11c3f44Smeem goto out; 2665e11c3f44Smeem 2666e11c3f44Smeem if ((dhcpbuf = copylist(dhcpfile, &dhcpsize)) == NULL) { 2667e11c3f44Smeem rcm_log_message(RCM_ERROR, _("IP: cannot read " 2668e11c3f44Smeem "(%s): %s\n"), dhcpfile, strerror(errno)); 2669e11c3f44Smeem goto fail; 2670e11c3f44Smeem } 2671e11c3f44Smeem 2672e11c3f44Smeem /* 2673e11c3f44Smeem * The copylist() API converts \n's to \0's, but we want them 2674e11c3f44Smeem * to be spaces. 2675e11c3f44Smeem */ 2676e11c3f44Smeem if (dhcpsize > 0) { 2677e11c3f44Smeem for (i = 0; i < dhcpsize; i++) 2678e11c3f44Smeem if (dhcpbuf[i] == '\0') 2679e11c3f44Smeem dhcpbuf[i] = ' '; 2680e11c3f44Smeem dhcpbuf[dhcpsize - 1] = '\0'; 2681e11c3f44Smeem } 2682e11c3f44Smeem (void) ifconfig(ifinst, CFG_DHCP_CMD, dhcpbuf, B_FALSE); 2683e11c3f44Smeem free(dhcpbuf); 2684e11c3f44Smeem } 2685e11c3f44Smeem out: 2686e11c3f44Smeem free(ifparsebuf); 26877c478bd9Sstevel@tonic-gate free(buf); 2688e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: if_config_inst(%s) success\n", ifinst); 26897c478bd9Sstevel@tonic-gate return (0); 2690e11c3f44Smeem fail: 2691e11c3f44Smeem free(ifparsebuf); 2692e11c3f44Smeem free(buf); 2693e11c3f44Smeem rcm_log_message(RCM_ERROR, "IP: if_config_inst(%s) failure\n", ifinst); 2694e11c3f44Smeem return (-1); 26957c478bd9Sstevel@tonic-gate } 26967c478bd9Sstevel@tonic-gate 26977c478bd9Sstevel@tonic-gate /* 2698e11c3f44Smeem * ntok() - count the number of tokens in the provided buffer. 26997c478bd9Sstevel@tonic-gate */ 2700e11c3f44Smeem static uint_t 2701e11c3f44Smeem ntok(const char *cp) 27027c478bd9Sstevel@tonic-gate { 2703e11c3f44Smeem uint_t ntok = 0; 27047c478bd9Sstevel@tonic-gate 2705e11c3f44Smeem for (;;) { 27067c478bd9Sstevel@tonic-gate while (ISSPACE(*cp)) 27077c478bd9Sstevel@tonic-gate cp++; 2708e11c3f44Smeem 27097c478bd9Sstevel@tonic-gate if (ISEOL(*cp)) 27107c478bd9Sstevel@tonic-gate break; 2711e11c3f44Smeem 27127c478bd9Sstevel@tonic-gate do { 2713e11c3f44Smeem cp++; 27147c478bd9Sstevel@tonic-gate } while (!ISSPACE(*cp) && !ISEOL(*cp)); 27157c478bd9Sstevel@tonic-gate 2716e11c3f44Smeem ntok++; 27177c478bd9Sstevel@tonic-gate } 2718e11c3f44Smeem return (ntok); 2719e11c3f44Smeem } 2720e11c3f44Smeem 2721e11c3f44Smeem static boolean_t 2722e11c3f44Smeem ifconfig(const char *ifinst, const char *fstr, const char *buf, boolean_t stdif) 2723e11c3f44Smeem { 2724e11c3f44Smeem char syscmd[MAX_RECONFIG_SIZE + MAXPATHLEN + 1]; 2725e11c3f44Smeem int status; 2726e11c3f44Smeem 2727e11c3f44Smeem (void) snprintf(syscmd, sizeof (syscmd), SBIN_IFCONFIG " %s %s %s", 2728e11c3f44Smeem ifinst, fstr, buf); 2729e11c3f44Smeem 2730e11c3f44Smeem if (stdif) 2731e11c3f44Smeem (void) strlcat(syscmd, CFG_CMDS_STD, sizeof (syscmd)); 2732e11c3f44Smeem 2733e11c3f44Smeem rcm_log_message(RCM_TRACE1, "IP: Exec: %s\n", syscmd); 2734e11c3f44Smeem if ((status = rcm_exec_cmd(syscmd)) != 0) { 2735e11c3f44Smeem if (WIFEXITED(status)) { 2736e11c3f44Smeem rcm_log_message(RCM_ERROR, _("IP: \"%s\" failed with " 2737e11c3f44Smeem "exit status %d\n"), syscmd, WEXITSTATUS(status)); 2738e11c3f44Smeem } else { 2739e11c3f44Smeem rcm_log_message(RCM_ERROR, _("IP: Error: %s: %s\n"), 2740e11c3f44Smeem syscmd, strerror(errno)); 2741e11c3f44Smeem } 2742e11c3f44Smeem return (B_FALSE); 2743e11c3f44Smeem } 2744e11c3f44Smeem return (B_TRUE); 27457c478bd9Sstevel@tonic-gate } 27466e91bba0SGirish Moodalbail 27476e91bba0SGirish Moodalbail /* 27486e91bba0SGirish Moodalbail * Return TRUE if a writeable /etc/hostname[6].ifname file exists. 27496e91bba0SGirish Moodalbail */ 27506e91bba0SGirish Moodalbail static boolean_t 27516e91bba0SGirish Moodalbail if_hostname_exists(char *ifname, sa_family_t af) 27526e91bba0SGirish Moodalbail { 27536e91bba0SGirish Moodalbail char cfgfile[MAXPATHLEN]; 27546e91bba0SGirish Moodalbail 27556e91bba0SGirish Moodalbail if (af == AF_INET) { 27566e91bba0SGirish Moodalbail (void) snprintf(cfgfile, MAXPATHLEN, CFGFILE_FMT_IPV4, ifname); 27576e91bba0SGirish Moodalbail if (access(cfgfile, W_OK|F_OK) == 0) 27586e91bba0SGirish Moodalbail return (B_TRUE); 27596e91bba0SGirish Moodalbail } else if (af == AF_INET6) { 27606e91bba0SGirish Moodalbail (void) snprintf(cfgfile, MAXPATHLEN, CFGFILE_FMT_IPV6, ifname); 27616e91bba0SGirish Moodalbail if (access(cfgfile, W_OK|F_OK) == 0) 27626e91bba0SGirish Moodalbail return (B_TRUE); 27636e91bba0SGirish Moodalbail } 27646e91bba0SGirish Moodalbail return (B_FALSE); 27656e91bba0SGirish Moodalbail } 2766