1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2002-2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * RCM module to prevent plumbed IP addresses from being removed.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <ctype.h>
36*7c478bd9Sstevel@tonic-gate #include <memory.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
39*7c478bd9Sstevel@tonic-gate #include <string.h>
40*7c478bd9Sstevel@tonic-gate #include <thread.h>
41*7c478bd9Sstevel@tonic-gate #include <synch.h>
42*7c478bd9Sstevel@tonic-gate #include <assert.h>
43*7c478bd9Sstevel@tonic-gate #include <errno.h>
44*7c478bd9Sstevel@tonic-gate #include <libintl.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/cladm.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
55*7c478bd9Sstevel@tonic-gate #include <net/if.h>
56*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
57*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
58*7c478bd9Sstevel@tonic-gate #include <netinet/ip6.h>
59*7c478bd9Sstevel@tonic-gate #include <inet/ip.h>
60*7c478bd9Sstevel@tonic-gate #include <inet/ip6.h>
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate #include "rcm_module.h"
63*7c478bd9Sstevel@tonic-gate #include "ifaddrlist.h"
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #define	SUNW_IP		"SUNW_ip/"
66*7c478bd9Sstevel@tonic-gate #define	IP_REG_SIZE	(9 + INET6_ADDRSTRLEN)
67*7c478bd9Sstevel@tonic-gate #define	IP_ANON_USAGE	gettext("Plumbed IP Address")
68*7c478bd9Sstevel@tonic-gate #define	IP_SUSPEND_ERR	gettext("Plumbed IP Addresses cannot be suspended")
69*7c478bd9Sstevel@tonic-gate #define	IP_OFFLINE_ERR	gettext("Invalid operation: IP cannot be offlined")
70*7c478bd9Sstevel@tonic-gate #define	IP_REMOVE_ERR	gettext("Invalid operation: IP cannot be removed")
71*7c478bd9Sstevel@tonic-gate #define	IP_REG_FAIL	gettext("Registration Failed")
72*7c478bd9Sstevel@tonic-gate #define	IP_NO_CLUSTER	gettext("Could not read cluster network addresses")
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate #define	IP_FLAG_NEW	0x00
75*7c478bd9Sstevel@tonic-gate #define	IP_FLAG_REG	0x01
76*7c478bd9Sstevel@tonic-gate #define	IP_FLAG_CL	0x02
77*7c478bd9Sstevel@tonic-gate #define	IP_FLAG_IGNORE	0x04
78*7c478bd9Sstevel@tonic-gate #define	IP_FLAG_DELETE	0x08
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate static int		ip_anon_register(rcm_handle_t *);
81*7c478bd9Sstevel@tonic-gate static int		ip_anon_unregister(rcm_handle_t *);
82*7c478bd9Sstevel@tonic-gate static int		ip_anon_getinfo(rcm_handle_t *, char *, id_t, uint_t,
83*7c478bd9Sstevel@tonic-gate 			    char **, char **, nvlist_t *, rcm_info_t **);
84*7c478bd9Sstevel@tonic-gate static int		ip_anon_suspend(rcm_handle_t *, char *, id_t,
85*7c478bd9Sstevel@tonic-gate 			    timespec_t *, uint_t, char **, rcm_info_t **);
86*7c478bd9Sstevel@tonic-gate static int		ip_anon_resume(rcm_handle_t *, char *, id_t, uint_t,
87*7c478bd9Sstevel@tonic-gate 			    char **, rcm_info_t **);
88*7c478bd9Sstevel@tonic-gate static int		ip_anon_offline(rcm_handle_t *, char *, id_t, uint_t,
89*7c478bd9Sstevel@tonic-gate 			    char **, rcm_info_t **);
90*7c478bd9Sstevel@tonic-gate static int		ip_anon_online(rcm_handle_t *, char *, id_t, uint_t,
91*7c478bd9Sstevel@tonic-gate 			    char **, rcm_info_t **);
92*7c478bd9Sstevel@tonic-gate static int		ip_anon_remove(rcm_handle_t *, char *, id_t, uint_t,
93*7c478bd9Sstevel@tonic-gate 			    char **, rcm_info_t **);
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate static int		exclude_ipv4(cladm_netaddrs_t exclude_addrs,
96*7c478bd9Sstevel@tonic-gate 			    ipaddr_t address);
97*7c478bd9Sstevel@tonic-gate static int		exclude_ipv6(cladm_netaddrs_t exclude_addrs,
98*7c478bd9Sstevel@tonic-gate 			    uint32_t address[4]);
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate typedef struct ip_status {
102*7c478bd9Sstevel@tonic-gate 	int			flags;
103*7c478bd9Sstevel@tonic-gate 	char			device[IP_REG_SIZE];
104*7c478bd9Sstevel@tonic-gate 	struct ip_status	*next;
105*7c478bd9Sstevel@tonic-gate } ip_status_t;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate static ip_status_t	*findreg(char *reg);
108*7c478bd9Sstevel@tonic-gate static ip_status_t	*addreg(char *reg);
109*7c478bd9Sstevel@tonic-gate static int		deletereg(ip_status_t *entry);
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate static ip_status_t	*ip_list = NULL;
112*7c478bd9Sstevel@tonic-gate static mutex_t		ip_list_lock;
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate static struct rcm_mod_ops ip_anon_ops =
115*7c478bd9Sstevel@tonic-gate {
116*7c478bd9Sstevel@tonic-gate 	RCM_MOD_OPS_VERSION,
117*7c478bd9Sstevel@tonic-gate 	ip_anon_register,
118*7c478bd9Sstevel@tonic-gate 	ip_anon_unregister,
119*7c478bd9Sstevel@tonic-gate 	ip_anon_getinfo,
120*7c478bd9Sstevel@tonic-gate 	ip_anon_suspend,
121*7c478bd9Sstevel@tonic-gate 	ip_anon_resume,
122*7c478bd9Sstevel@tonic-gate 	ip_anon_offline,
123*7c478bd9Sstevel@tonic-gate 	ip_anon_online,
124*7c478bd9Sstevel@tonic-gate 	ip_anon_remove,
125*7c478bd9Sstevel@tonic-gate 	NULL,
126*7c478bd9Sstevel@tonic-gate 	NULL,
127*7c478bd9Sstevel@tonic-gate 	NULL
128*7c478bd9Sstevel@tonic-gate };
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate struct rcm_mod_ops *
131*7c478bd9Sstevel@tonic-gate rcm_mod_init()
132*7c478bd9Sstevel@tonic-gate {
133*7c478bd9Sstevel@tonic-gate 	return (&ip_anon_ops);
134*7c478bd9Sstevel@tonic-gate }
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate const char *
137*7c478bd9Sstevel@tonic-gate rcm_mod_info()
138*7c478bd9Sstevel@tonic-gate {
139*7c478bd9Sstevel@tonic-gate 	return ("RCM IP address module %I%");
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate int
143*7c478bd9Sstevel@tonic-gate rcm_mod_fini()
144*7c478bd9Sstevel@tonic-gate {
145*7c478bd9Sstevel@tonic-gate 	ip_status_t *tlist;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	/* free the registration list */
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&ip_list_lock);
150*7c478bd9Sstevel@tonic-gate 	while (ip_list != NULL) {
151*7c478bd9Sstevel@tonic-gate 		tlist = ip_list->next;
152*7c478bd9Sstevel@tonic-gate 		free(ip_list);
153*7c478bd9Sstevel@tonic-gate 		ip_list = tlist;
154*7c478bd9Sstevel@tonic-gate 	}
155*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&ip_list_lock);
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate 	(void) mutex_destroy(&ip_list_lock);
158*7c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
159*7c478bd9Sstevel@tonic-gate }
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate static int
162*7c478bd9Sstevel@tonic-gate ip_anon_register(rcm_handle_t *hdl)
163*7c478bd9Sstevel@tonic-gate {
164*7c478bd9Sstevel@tonic-gate 	int bootflags;
165*7c478bd9Sstevel@tonic-gate 	struct ifaddrlist *al = NULL, *al6 = NULL;
166*7c478bd9Sstevel@tonic-gate 	char errbuf[ERRBUFSIZE] = "", errbuf6[ERRBUFSIZE] = "";
167*7c478bd9Sstevel@tonic-gate 	char treg[IP_REG_SIZE], tstr[IP_REG_SIZE];
168*7c478bd9Sstevel@tonic-gate 	cladm_netaddrs_t exclude_addrs;
169*7c478bd9Sstevel@tonic-gate 	int num_ifs, num_ifs6,  i, ret;
170*7c478bd9Sstevel@tonic-gate 	uint32_t num_exclude_addrs = 0;
171*7c478bd9Sstevel@tonic-gate 	ip_status_t *tlist, *tentry;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&ip_list_lock);
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: registration refresh.\n");
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	exclude_addrs.cladm_num_netaddrs = 0;
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	if (_cladm(CL_INITIALIZE, CL_GET_BOOTFLAG, &bootflags) != 0) {
180*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
181*7c478bd9Sstevel@tonic-gate 			gettext("unable to check cluster status\n"));
182*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&ip_list_lock);
183*7c478bd9Sstevel@tonic-gate 		return (RCM_FAILURE);
184*7c478bd9Sstevel@tonic-gate 	}
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG,
187*7c478bd9Sstevel@tonic-gate 	    "ip_anon: cladm bootflags=%d\n", bootflags);
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	if (bootflags == 3) {
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 		/* build the exclusion list */
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 		if ((ret = _cladm(CL_CONFIG, CL_GET_NUM_NETADDRS,
194*7c478bd9Sstevel@tonic-gate 		    &num_exclude_addrs)) == 0) {
195*7c478bd9Sstevel@tonic-gate 			exclude_addrs.cladm_num_netaddrs = num_exclude_addrs;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 			if (num_exclude_addrs == 0)
198*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_DEBUG,
199*7c478bd9Sstevel@tonic-gate 				    "ip_anon: no addresses excluded\n");
200*7c478bd9Sstevel@tonic-gate 			else {
201*7c478bd9Sstevel@tonic-gate 				if ((exclude_addrs.cladm_netaddrs_array =
202*7c478bd9Sstevel@tonic-gate 				    malloc(sizeof (cladm_netaddr_entry_t) *
203*7c478bd9Sstevel@tonic-gate 					    (num_exclude_addrs))) == NULL) {
204*7c478bd9Sstevel@tonic-gate 					rcm_log_message(RCM_ERROR,
205*7c478bd9Sstevel@tonic-gate 					    gettext("out of memory\n"));
206*7c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&ip_list_lock);
207*7c478bd9Sstevel@tonic-gate 					return (RCM_FAILURE);
208*7c478bd9Sstevel@tonic-gate 				}
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 				if ((ret = _cladm(CL_CONFIG,
211*7c478bd9Sstevel@tonic-gate 				    CL_GET_NETADDRS, &exclude_addrs))
212*7c478bd9Sstevel@tonic-gate 				    != 0) {
213*7c478bd9Sstevel@tonic-gate 					rcm_log_message(RCM_ERROR,
214*7c478bd9Sstevel@tonic-gate 					    IP_NO_CLUSTER);
215*7c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&ip_list_lock);
216*7c478bd9Sstevel@tonic-gate 					return (RCM_FAILURE);
217*7c478bd9Sstevel@tonic-gate 				}
218*7c478bd9Sstevel@tonic-gate 			}
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 		} else {
221*7c478bd9Sstevel@tonic-gate 			if ((ret != 0) && (errno == EINVAL)) {
222*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_DEBUG,
223*7c478bd9Sstevel@tonic-gate 				    "no _cladm() backend to get addrs\n");
224*7c478bd9Sstevel@tonic-gate 			} else {
225*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_ERROR, IP_NO_CLUSTER);
226*7c478bd9Sstevel@tonic-gate 				(void) mutex_unlock(&ip_list_lock);
227*7c478bd9Sstevel@tonic-gate 				return (RCM_FAILURE);
228*7c478bd9Sstevel@tonic-gate 			}
229*7c478bd9Sstevel@tonic-gate 		}
230*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_DEBUG,
231*7c478bd9Sstevel@tonic-gate 		    "cladm returned %d errno=%d\n", ret, errno);
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_DEBUG,
234*7c478bd9Sstevel@tonic-gate 		    "ip_anon: num exclude addrs: %d\n",
235*7c478bd9Sstevel@tonic-gate 		    exclude_addrs.cladm_num_netaddrs);
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 		/* print the exclusion list for debugging purposes */
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < exclude_addrs.cladm_num_netaddrs; i++) {
240*7c478bd9Sstevel@tonic-gate 			(void) strcpy(treg, "<UNKNOWN>");
241*7c478bd9Sstevel@tonic-gate 			(void) strcpy(tstr, "<UNKNOWN>");
242*7c478bd9Sstevel@tonic-gate 			if (exclude_addrs.cladm_netaddrs_array[i].\
243*7c478bd9Sstevel@tonic-gate 			    cl_ipversion == IPV4_VERSION) {
244*7c478bd9Sstevel@tonic-gate 				(void) inet_ntop(AF_INET,
245*7c478bd9Sstevel@tonic-gate 				    &exclude_addrs.cladm_netaddrs_array[i].
246*7c478bd9Sstevel@tonic-gate 				    cl_ipv_un.cl_ipv4.ipv4_netaddr,
247*7c478bd9Sstevel@tonic-gate 				    treg, INET_ADDRSTRLEN);
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 				(void) inet_ntop(AF_INET,
250*7c478bd9Sstevel@tonic-gate 				    &exclude_addrs.cladm_netaddrs_array[i].
251*7c478bd9Sstevel@tonic-gate 				    cl_ipv_un.cl_ipv4.ipv4_netmask,
252*7c478bd9Sstevel@tonic-gate 				    tstr, INET_ADDRSTRLEN);
253*7c478bd9Sstevel@tonic-gate 			}
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 			if (exclude_addrs.cladm_netaddrs_array[i].\
256*7c478bd9Sstevel@tonic-gate 			    cl_ipversion == IPV6_VERSION) {
257*7c478bd9Sstevel@tonic-gate 				(void) inet_ntop(AF_INET6,
258*7c478bd9Sstevel@tonic-gate 				    &exclude_addrs.cladm_netaddrs_array[i].
259*7c478bd9Sstevel@tonic-gate 				    cl_ipv_un.cl_ipv6.ipv6_netaddr,
260*7c478bd9Sstevel@tonic-gate 				    treg, INET6_ADDRSTRLEN);
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 				(void) inet_ntop(AF_INET6,
263*7c478bd9Sstevel@tonic-gate 				    &exclude_addrs.cladm_netaddrs_array[i].
264*7c478bd9Sstevel@tonic-gate 				    cl_ipv_un.cl_ipv6.ipv6_netmask,
265*7c478bd9Sstevel@tonic-gate 				    tstr, INET6_ADDRSTRLEN);
266*7c478bd9Sstevel@tonic-gate 			}
267*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_DEBUG, "IPV%d: %s %s\n",
268*7c478bd9Sstevel@tonic-gate 			    exclude_addrs.cladm_netaddrs_array[i].
269*7c478bd9Sstevel@tonic-gate 			    cl_ipversion, treg, tstr);
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 		}
272*7c478bd9Sstevel@tonic-gate 	}
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	/* obtain a list of all IPv4 and IPv6 addresses in the system */
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG,
279*7c478bd9Sstevel@tonic-gate 	    "ip_anon: obtaining list of IPv4 addresses.\n");
280*7c478bd9Sstevel@tonic-gate 	num_ifs = ifaddrlist(&al, AF_INET, errbuf);
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	if ((num_ifs == -1) && (errno != 0) && (errno != ENOENT) &&
283*7c478bd9Sstevel@tonic-gate 	    (errno != EINVAL)) {
284*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
285*7c478bd9Sstevel@tonic-gate 		    gettext("cannot get IPv4 address list errno=%d (%s)\n"),
286*7c478bd9Sstevel@tonic-gate 		    errno, errbuf);
287*7c478bd9Sstevel@tonic-gate 		free(al);
288*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&ip_list_lock);
289*7c478bd9Sstevel@tonic-gate 		return (RCM_FAILURE);
290*7c478bd9Sstevel@tonic-gate 	}
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG,
293*7c478bd9Sstevel@tonic-gate 	    "ip_anon: obtaining list of IPv6 addresses.\n");
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	num_ifs6 = ifaddrlist(&al6, AF_INET6, errbuf6);
296*7c478bd9Sstevel@tonic-gate 	if ((num_ifs6 == -1) && (errno != 0) && (errno != ENOENT) &&
297*7c478bd9Sstevel@tonic-gate 		(errno != EINVAL)) {
298*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR,
299*7c478bd9Sstevel@tonic-gate 		    gettext("cannot get IPv6 address list errno=%d (%s)\n"),
300*7c478bd9Sstevel@tonic-gate 		    errno, errbuf6);
301*7c478bd9Sstevel@tonic-gate 		free(al);
302*7c478bd9Sstevel@tonic-gate 		free(al6);
303*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&ip_list_lock);
304*7c478bd9Sstevel@tonic-gate 		return (RCM_FAILURE);
305*7c478bd9Sstevel@tonic-gate 	}
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	/* check the state of outstanding registrations against the list */
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG,
310*7c478bd9Sstevel@tonic-gate 	    "ip_anon: checking outstanding registrations.\n");
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	tlist = ip_list;
313*7c478bd9Sstevel@tonic-gate 	while (tlist != NULL) {
314*7c478bd9Sstevel@tonic-gate 		tlist->flags |= IP_FLAG_DELETE;
315*7c478bd9Sstevel@tonic-gate 		tlist = tlist->next;
316*7c478bd9Sstevel@tonic-gate 	}
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	/* IPv4 */
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: checking IPv4 addresses.\n");
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_ifs; i++) {
323*7c478bd9Sstevel@tonic-gate 		(void) inet_ntop(AF_INET, &al[i].addr.addr, tstr,
324*7c478bd9Sstevel@tonic-gate 		    INET_ADDRSTRLEN);
325*7c478bd9Sstevel@tonic-gate 		(void) strcpy(treg, SUNW_IP);
326*7c478bd9Sstevel@tonic-gate 		(void) strcat(treg, tstr);
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 		if ((tlist = findreg(treg)) == NULL)
329*7c478bd9Sstevel@tonic-gate 			tlist = addreg(treg);
330*7c478bd9Sstevel@tonic-gate 		else
331*7c478bd9Sstevel@tonic-gate 			tlist->flags &= (~IP_FLAG_DELETE);
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 		if (tlist == NULL) {
334*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_ERROR,
335*7c478bd9Sstevel@tonic-gate 			    gettext("out of memory\n"));
336*7c478bd9Sstevel@tonic-gate 			free(al);
337*7c478bd9Sstevel@tonic-gate 			free(al6);
338*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&ip_list_lock);
339*7c478bd9Sstevel@tonic-gate 			return (RCM_FAILURE);
340*7c478bd9Sstevel@tonic-gate 		}
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 		if (exclude_ipv4(exclude_addrs, al[i].addr.addr.s_addr))
343*7c478bd9Sstevel@tonic-gate 			tlist->flags |= IP_FLAG_CL;
344*7c478bd9Sstevel@tonic-gate 	}
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	/* IPv6 */
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: checking IPv6 addresses.\n");
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_ifs6; i++) {
351*7c478bd9Sstevel@tonic-gate 		(void) inet_ntop(AF_INET6, &al6[i].addr.addr, tstr,
352*7c478bd9Sstevel@tonic-gate 		    INET6_ADDRSTRLEN);
353*7c478bd9Sstevel@tonic-gate 		(void) strcpy(treg, SUNW_IP);
354*7c478bd9Sstevel@tonic-gate 		(void) strcat(treg, tstr);
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 		if ((tlist = findreg(treg)) == NULL)
357*7c478bd9Sstevel@tonic-gate 			tlist = addreg(treg);
358*7c478bd9Sstevel@tonic-gate 		else
359*7c478bd9Sstevel@tonic-gate 			tlist->flags &= (~IP_FLAG_DELETE);
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 		if (tlist == NULL) {
362*7c478bd9Sstevel@tonic-gate 			rcm_log_message(RCM_ERROR,
363*7c478bd9Sstevel@tonic-gate 			    gettext("out of memory\n"));
364*7c478bd9Sstevel@tonic-gate 			free(al);
365*7c478bd9Sstevel@tonic-gate 			free(al6);
366*7c478bd9Sstevel@tonic-gate 			(void) mutex_unlock(&ip_list_lock);
367*7c478bd9Sstevel@tonic-gate 			return (RCM_FAILURE);
368*7c478bd9Sstevel@tonic-gate 		}
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 		if (exclude_ipv6(exclude_addrs, al6[i].addr.addr6._S6_un.\
371*7c478bd9Sstevel@tonic-gate 		    _S6_u32))
372*7c478bd9Sstevel@tonic-gate 			tlist->flags |= IP_FLAG_CL;
373*7c478bd9Sstevel@tonic-gate 	}
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: updating reg. state.\n");
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	/* examine the list of ip address registrations and their state */
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	tlist = ip_list;
380*7c478bd9Sstevel@tonic-gate 	while (tlist != NULL) {
381*7c478bd9Sstevel@tonic-gate 		tentry = tlist;
382*7c478bd9Sstevel@tonic-gate 		tlist = tlist->next;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 		if (tentry->flags & IP_FLAG_DELETE) {
385*7c478bd9Sstevel@tonic-gate 			if (tentry->flags & IP_FLAG_REG) {
386*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_DEBUG,
387*7c478bd9Sstevel@tonic-gate 				    "ip_anon: unregistering interest in %s\n",
388*7c478bd9Sstevel@tonic-gate 				    tentry->device);
389*7c478bd9Sstevel@tonic-gate 				if (rcm_unregister_interest(hdl,
390*7c478bd9Sstevel@tonic-gate 				    tentry->device, 0) != 0) {
391*7c478bd9Sstevel@tonic-gate 					rcm_log_message(RCM_ERROR,
392*7c478bd9Sstevel@tonic-gate 					    gettext("failed to unregister"));
393*7c478bd9Sstevel@tonic-gate 				}
394*7c478bd9Sstevel@tonic-gate 			}
395*7c478bd9Sstevel@tonic-gate 			(void) deletereg(tentry);
396*7c478bd9Sstevel@tonic-gate 		} else if (!(tentry->flags & IP_FLAG_IGNORE)) {
397*7c478bd9Sstevel@tonic-gate 			/*
398*7c478bd9Sstevel@tonic-gate 			 * If the registration is not a clustered devices and
399*7c478bd9Sstevel@tonic-gate 			 * not already registered, then RCM doesn't
400*7c478bd9Sstevel@tonic-gate 			 * currently know about it.
401*7c478bd9Sstevel@tonic-gate 			 */
402*7c478bd9Sstevel@tonic-gate 			if (!(tentry->flags & IP_FLAG_CL) &&
403*7c478bd9Sstevel@tonic-gate 				!(tentry->flags & IP_FLAG_REG)) {
404*7c478bd9Sstevel@tonic-gate 				tentry->flags |= IP_FLAG_REG;
405*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_DEBUG,
406*7c478bd9Sstevel@tonic-gate 				    "ip_anon: registering interest in %s\n",
407*7c478bd9Sstevel@tonic-gate 				    tentry->device);
408*7c478bd9Sstevel@tonic-gate 				if (rcm_register_interest(hdl,
409*7c478bd9Sstevel@tonic-gate 				    tentry->device, 0, NULL) !=
410*7c478bd9Sstevel@tonic-gate 				    RCM_SUCCESS) {
411*7c478bd9Sstevel@tonic-gate 					rcm_log_message(RCM_ERROR,
412*7c478bd9Sstevel@tonic-gate 					    IP_REG_FAIL);
413*7c478bd9Sstevel@tonic-gate 					free(al);
414*7c478bd9Sstevel@tonic-gate 					free(al6);
415*7c478bd9Sstevel@tonic-gate 					(void) mutex_unlock(&ip_list_lock);
416*7c478bd9Sstevel@tonic-gate 					return (RCM_FAILURE);
417*7c478bd9Sstevel@tonic-gate 				} else {
418*7c478bd9Sstevel@tonic-gate 					rcm_log_message(RCM_DEBUG,
419*7c478bd9Sstevel@tonic-gate 					    "ip_anon: registered %s\n",
420*7c478bd9Sstevel@tonic-gate 					    tentry->device);
421*7c478bd9Sstevel@tonic-gate 				}
422*7c478bd9Sstevel@tonic-gate 			}
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 			/*
425*7c478bd9Sstevel@tonic-gate 			 * If the entry is registered and clustered, then
426*7c478bd9Sstevel@tonic-gate 			 * the configuration has been changed and it
427*7c478bd9Sstevel@tonic-gate 			 * should be unregistered.
428*7c478bd9Sstevel@tonic-gate 			 */
429*7c478bd9Sstevel@tonic-gate 			if ((tentry->flags & IP_FLAG_REG) &
430*7c478bd9Sstevel@tonic-gate 			    (tentry->flags & IP_FLAG_CL)) {
431*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_DEBUG,
432*7c478bd9Sstevel@tonic-gate 				    "ip_anon: unregistering in %s\n",
433*7c478bd9Sstevel@tonic-gate 				    tentry->device);
434*7c478bd9Sstevel@tonic-gate 				if (rcm_unregister_interest(hdl,
435*7c478bd9Sstevel@tonic-gate 				    tentry->device, 0) != 0) {
436*7c478bd9Sstevel@tonic-gate 					rcm_log_message(RCM_ERROR,
437*7c478bd9Sstevel@tonic-gate 					    gettext("failed to unregister"));
438*7c478bd9Sstevel@tonic-gate 				}
439*7c478bd9Sstevel@tonic-gate 				tentry->flags &= (~IP_FLAG_REG);
440*7c478bd9Sstevel@tonic-gate 			}
441*7c478bd9Sstevel@tonic-gate 		}
442*7c478bd9Sstevel@tonic-gate 	}
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate 	tlist = ip_list;
445*7c478bd9Sstevel@tonic-gate 	while (tlist != NULL) {
446*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_DEBUG, "ip_anon: %s (%Xh)\n",
447*7c478bd9Sstevel@tonic-gate 		    tlist->device, tlist->flags);
448*7c478bd9Sstevel@tonic-gate 		tlist = tlist->next;
449*7c478bd9Sstevel@tonic-gate 	}
450*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: registration complete.\n");
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	free(al);
453*7c478bd9Sstevel@tonic-gate 	free(al6);
454*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&ip_list_lock);
455*7c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
456*7c478bd9Sstevel@tonic-gate }
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate static int
459*7c478bd9Sstevel@tonic-gate ip_anon_unregister(rcm_handle_t *hdl)
460*7c478bd9Sstevel@tonic-gate {
461*7c478bd9Sstevel@tonic-gate 	ip_status_t *tlist;
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&ip_list_lock);
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 	tlist = ip_list;
466*7c478bd9Sstevel@tonic-gate 	while (tlist != NULL) {
467*7c478bd9Sstevel@tonic-gate 		if ((tlist->flags & IP_FLAG_REG)) {
468*7c478bd9Sstevel@tonic-gate 			if (rcm_unregister_interest(hdl,
469*7c478bd9Sstevel@tonic-gate 			    tlist->device, 0) != 0) {
470*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_ERROR,
471*7c478bd9Sstevel@tonic-gate 				    gettext("failed to unregister"));
472*7c478bd9Sstevel@tonic-gate 			}
473*7c478bd9Sstevel@tonic-gate 			tlist->flags &= (~IP_FLAG_REG);
474*7c478bd9Sstevel@tonic-gate 		}
475*7c478bd9Sstevel@tonic-gate 		tlist = tlist->next;
476*7c478bd9Sstevel@tonic-gate 	}
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&ip_list_lock);
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
481*7c478bd9Sstevel@tonic-gate }
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
484*7c478bd9Sstevel@tonic-gate static int
485*7c478bd9Sstevel@tonic-gate ip_anon_getinfo(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
486*7c478bd9Sstevel@tonic-gate     char **infostr, char **errstr, nvlist_t *props, rcm_info_t **dependent)
487*7c478bd9Sstevel@tonic-gate {
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	assert(rsrcname != NULL && infostr != NULL);
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 	if ((*infostr = strdup(IP_ANON_USAGE)) == NULL)
492*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
495*7c478bd9Sstevel@tonic-gate }
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
498*7c478bd9Sstevel@tonic-gate static int
499*7c478bd9Sstevel@tonic-gate ip_anon_suspend(rcm_handle_t *hdl, char *rsrcname, id_t id,
500*7c478bd9Sstevel@tonic-gate     timespec_t *interval, uint_t flags, char **errstr,
501*7c478bd9Sstevel@tonic-gate     rcm_info_t **dependent)
502*7c478bd9Sstevel@tonic-gate {
503*7c478bd9Sstevel@tonic-gate 	if ((*errstr = strdup(IP_SUSPEND_ERR)) == NULL)
504*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	return (RCM_FAILURE);
507*7c478bd9Sstevel@tonic-gate }
508*7c478bd9Sstevel@tonic-gate 
509*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
510*7c478bd9Sstevel@tonic-gate static int
511*7c478bd9Sstevel@tonic-gate ip_anon_resume(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
512*7c478bd9Sstevel@tonic-gate     char **errstr, rcm_info_t **dependent)
513*7c478bd9Sstevel@tonic-gate {
514*7c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
515*7c478bd9Sstevel@tonic-gate }
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
518*7c478bd9Sstevel@tonic-gate static int
519*7c478bd9Sstevel@tonic-gate ip_anon_offline(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
520*7c478bd9Sstevel@tonic-gate     char **errstr, rcm_info_t **dependent)
521*7c478bd9Sstevel@tonic-gate {
522*7c478bd9Sstevel@tonic-gate 	if ((*errstr = strdup(IP_OFFLINE_ERR)) == NULL)
523*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	return (RCM_FAILURE);
526*7c478bd9Sstevel@tonic-gate }
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
529*7c478bd9Sstevel@tonic-gate static int
530*7c478bd9Sstevel@tonic-gate ip_anon_online(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
531*7c478bd9Sstevel@tonic-gate     char  **errstr, rcm_info_t **dependent)
532*7c478bd9Sstevel@tonic-gate {
533*7c478bd9Sstevel@tonic-gate 	return (RCM_SUCCESS);
534*7c478bd9Sstevel@tonic-gate }
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
537*7c478bd9Sstevel@tonic-gate static int
538*7c478bd9Sstevel@tonic-gate ip_anon_remove(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
539*7c478bd9Sstevel@tonic-gate     char **errstr, rcm_info_t **dependent)
540*7c478bd9Sstevel@tonic-gate {
541*7c478bd9Sstevel@tonic-gate 	if ((*errstr = strdup(IP_REMOVE_ERR)) == NULL)
542*7c478bd9Sstevel@tonic-gate 		rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	return (RCM_FAILURE);
545*7c478bd9Sstevel@tonic-gate }
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate /*
548*7c478bd9Sstevel@tonic-gate  * Call with ip_list_lock held.
549*7c478bd9Sstevel@tonic-gate  */
550*7c478bd9Sstevel@tonic-gate 
551*7c478bd9Sstevel@tonic-gate static ip_status_t *
552*7c478bd9Sstevel@tonic-gate findreg(char *reg)
553*7c478bd9Sstevel@tonic-gate {
554*7c478bd9Sstevel@tonic-gate 	ip_status_t *tlist;
555*7c478bd9Sstevel@tonic-gate 	int done;
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	tlist = ip_list;
558*7c478bd9Sstevel@tonic-gate 	done = 0;
559*7c478bd9Sstevel@tonic-gate 	while ((tlist != NULL) && (!done)) {
560*7c478bd9Sstevel@tonic-gate 		if (strcmp(tlist->device, reg) == 0)
561*7c478bd9Sstevel@tonic-gate 			done = 1;
562*7c478bd9Sstevel@tonic-gate 		else
563*7c478bd9Sstevel@tonic-gate 			tlist = tlist->next;
564*7c478bd9Sstevel@tonic-gate 	}
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	return (tlist);
567*7c478bd9Sstevel@tonic-gate }
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate static ip_status_t *
570*7c478bd9Sstevel@tonic-gate addreg(char *reg)
571*7c478bd9Sstevel@tonic-gate {
572*7c478bd9Sstevel@tonic-gate 	ip_status_t *tlist, *tentry;
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate 	tentry = (ip_status_t *)malloc(sizeof (ip_status_t));
575*7c478bd9Sstevel@tonic-gate 	if (tentry == NULL)
576*7c478bd9Sstevel@tonic-gate 		return (tentry);
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 	tentry->flags = IP_FLAG_NEW;
579*7c478bd9Sstevel@tonic-gate 	tentry->next = NULL;
580*7c478bd9Sstevel@tonic-gate 	(void) strcpy(tentry->device, reg);
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	if (ip_list == NULL)
583*7c478bd9Sstevel@tonic-gate 		ip_list = tentry;
584*7c478bd9Sstevel@tonic-gate 	else {
585*7c478bd9Sstevel@tonic-gate 		tlist = ip_list;
586*7c478bd9Sstevel@tonic-gate 		while (tlist->next != NULL)
587*7c478bd9Sstevel@tonic-gate 			tlist = tlist->next;
588*7c478bd9Sstevel@tonic-gate 		tlist->next = tentry;
589*7c478bd9Sstevel@tonic-gate 	}
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 	return (tentry);
592*7c478bd9Sstevel@tonic-gate }
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate static int
595*7c478bd9Sstevel@tonic-gate deletereg(ip_status_t *entry)
596*7c478bd9Sstevel@tonic-gate {
597*7c478bd9Sstevel@tonic-gate 	ip_status_t *tlist;
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 	if (entry == NULL)
600*7c478bd9Sstevel@tonic-gate 		return (-1);
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	if (entry == ip_list) {
603*7c478bd9Sstevel@tonic-gate 		ip_list = ip_list->next;
604*7c478bd9Sstevel@tonic-gate 		free(entry);
605*7c478bd9Sstevel@tonic-gate 	} else {
606*7c478bd9Sstevel@tonic-gate 		tlist = ip_list;
607*7c478bd9Sstevel@tonic-gate 		while ((tlist->next != NULL) && (tlist->next != entry))
608*7c478bd9Sstevel@tonic-gate 			tlist = tlist->next;
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 		if (tlist->next != entry)
611*7c478bd9Sstevel@tonic-gate 			return (-1);
612*7c478bd9Sstevel@tonic-gate 		tlist->next = entry->next;
613*7c478bd9Sstevel@tonic-gate 		free(entry);
614*7c478bd9Sstevel@tonic-gate 	}
615*7c478bd9Sstevel@tonic-gate 	return (0);
616*7c478bd9Sstevel@tonic-gate }
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate static int
619*7c478bd9Sstevel@tonic-gate exclude_ipv4(cladm_netaddrs_t exclude_addrs, ipaddr_t address)
620*7c478bd9Sstevel@tonic-gate {
621*7c478bd9Sstevel@tonic-gate 	int i;
622*7c478bd9Sstevel@tonic-gate 	char taddr[IP_REG_SIZE], tmask[IP_REG_SIZE], tmatch[IP_REG_SIZE];
623*7c478bd9Sstevel@tonic-gate 	ipaddr_t ipv4_netaddr, ipv4_netmask;
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 	(void) inet_ntop(AF_INET, &address, taddr, INET_ADDRSTRLEN);
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: exclude_ipv4 (%s, %d)\n",
628*7c478bd9Sstevel@tonic-gate 	    taddr, exclude_addrs.cladm_num_netaddrs);
629*7c478bd9Sstevel@tonic-gate 	/*
630*7c478bd9Sstevel@tonic-gate 	 * If this falls in the exclusion list, the IP_FLAG_CL
631*7c478bd9Sstevel@tonic-gate 	 * bit should be set for the adapter.
632*7c478bd9Sstevel@tonic-gate 	 */
633*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < exclude_addrs.cladm_num_netaddrs; i++) {
634*7c478bd9Sstevel@tonic-gate 		if (exclude_addrs.cladm_netaddrs_array[i].\
635*7c478bd9Sstevel@tonic-gate 		    cl_ipversion == IPV4_VERSION) {
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 			ipv4_netaddr = exclude_addrs.\
638*7c478bd9Sstevel@tonic-gate 			    cladm_netaddrs_array[i].cl_ipv_un.cl_ipv4.\
639*7c478bd9Sstevel@tonic-gate 			    ipv4_netaddr;
640*7c478bd9Sstevel@tonic-gate 			ipv4_netmask = exclude_addrs.\
641*7c478bd9Sstevel@tonic-gate 			    cladm_netaddrs_array[i].cl_ipv_un.cl_ipv4.\
642*7c478bd9Sstevel@tonic-gate 			    ipv4_netmask;
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 			(void) inet_ntop(AF_INET, &ipv4_netaddr, tmatch,
645*7c478bd9Sstevel@tonic-gate 			    INET_ADDRSTRLEN);
646*7c478bd9Sstevel@tonic-gate 			(void) inet_ntop(AF_INET, &ipv4_netmask, tmask,
647*7c478bd9Sstevel@tonic-gate 			    INET_ADDRSTRLEN);
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 			if ((address & ipv4_netmask) == ipv4_netaddr) {
650*7c478bd9Sstevel@tonic-gate 				rcm_log_message(RCM_DEBUG,
651*7c478bd9Sstevel@tonic-gate 				    "ip_anon: matched %s:%s => %s\n",
652*7c478bd9Sstevel@tonic-gate 				    taddr, tmask, tmatch);
653*7c478bd9Sstevel@tonic-gate 				return (1);
654*7c478bd9Sstevel@tonic-gate 			}
655*7c478bd9Sstevel@tonic-gate 		}
656*7c478bd9Sstevel@tonic-gate 	}
657*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: no match for %s\n",
658*7c478bd9Sstevel@tonic-gate 	    taddr);
659*7c478bd9Sstevel@tonic-gate 	return (0);
660*7c478bd9Sstevel@tonic-gate }
661*7c478bd9Sstevel@tonic-gate 
662*7c478bd9Sstevel@tonic-gate static int
663*7c478bd9Sstevel@tonic-gate exclude_ipv6(cladm_netaddrs_t exclude_addrs, uint32_t address[4])
664*7c478bd9Sstevel@tonic-gate {
665*7c478bd9Sstevel@tonic-gate 	int i, j, numequal;
666*7c478bd9Sstevel@tonic-gate 	uint32_t addr[4], ipv6_netaddr[4], ipv6_netmask[4];
667*7c478bd9Sstevel@tonic-gate 	char taddr[IP_REG_SIZE], tmask[IP_REG_SIZE], tmatch[IP_REG_SIZE];
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 	(void) inet_ntop(AF_INET6, address, taddr, INET6_ADDRSTRLEN);
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	/*
672*7c478bd9Sstevel@tonic-gate 	 * If this falls in the exclusion list, the IP_FLAG_CL
673*7c478bd9Sstevel@tonic-gate 	 * bit should be set for the adapter.
674*7c478bd9Sstevel@tonic-gate 	 */
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < exclude_addrs.cladm_num_netaddrs; i++) {
677*7c478bd9Sstevel@tonic-gate 		if (exclude_addrs.cladm_netaddrs_array[i].\
678*7c478bd9Sstevel@tonic-gate 		    cl_ipversion == IPV6_VERSION) {
679*7c478bd9Sstevel@tonic-gate 			numequal = 0;
680*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < 4; j++) {
681*7c478bd9Sstevel@tonic-gate 				ipv6_netaddr[j] = exclude_addrs.\
682*7c478bd9Sstevel@tonic-gate 				    cladm_netaddrs_array[i].\
683*7c478bd9Sstevel@tonic-gate 				    cl_ipv_un.cl_ipv6.ipv6_netaddr[j];
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 				ipv6_netmask[j] = exclude_addrs.\
686*7c478bd9Sstevel@tonic-gate 				    cladm_netaddrs_array[i].\
687*7c478bd9Sstevel@tonic-gate 				    cl_ipv_un.cl_ipv6.ipv6_netmask[j];
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 				addr[j] = address[j] & ipv6_netmask[j];
690*7c478bd9Sstevel@tonic-gate 				if (addr[j] == ipv6_netaddr[j])
691*7c478bd9Sstevel@tonic-gate 					numequal++;
692*7c478bd9Sstevel@tonic-gate 			}
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 			(void) inet_ntop(AF_INET6, ipv6_netaddr, tmatch,
695*7c478bd9Sstevel@tonic-gate 			    INET6_ADDRSTRLEN);
696*7c478bd9Sstevel@tonic-gate 			(void) inet_ntop(AF_INET6, ipv6_netmask, tmask,
697*7c478bd9Sstevel@tonic-gate 			    INET6_ADDRSTRLEN);
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 			if (numequal == 4)
700*7c478bd9Sstevel@tonic-gate 				return (1);
701*7c478bd9Sstevel@tonic-gate 		}
702*7c478bd9Sstevel@tonic-gate 	}
703*7c478bd9Sstevel@tonic-gate 	rcm_log_message(RCM_DEBUG, "ip_anon: no match for %s\n",
704*7c478bd9Sstevel@tonic-gate 	    taddr);
705*7c478bd9Sstevel@tonic-gate 	return (0);
706*7c478bd9Sstevel@tonic-gate }
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate /*
709*7c478bd9Sstevel@tonic-gate  * The code below is taken from usr/src/cmd/cmd-inet/common/ifaddrlist.c
710*7c478bd9Sstevel@tonic-gate  */
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate /*
713*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1997
714*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
715*7c478bd9Sstevel@tonic-gate  *
716*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
717*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
718*7c478bd9Sstevel@tonic-gate  * are met:
719*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
720*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
721*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
722*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
723*7c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
724*7c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
725*7c478bd9Sstevel@tonic-gate  *    must display the following acknowledgement:
726*7c478bd9Sstevel@tonic-gate  *	This product includes software developed by the Computer Systems
727*7c478bd9Sstevel@tonic-gate  *	Engineering Group at Lawrence Berkeley Laboratory.
728*7c478bd9Sstevel@tonic-gate  * 4. Neither the name of the University nor of the Laboratory may be used
729*7c478bd9Sstevel@tonic-gate  *    to endorse or promote products derived from this software without
730*7c478bd9Sstevel@tonic-gate  *    specific prior written permission.
731*7c478bd9Sstevel@tonic-gate  *
732*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
733*7c478bd9Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
734*7c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
735*7c478bd9Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
736*7c478bd9Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
737*7c478bd9Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
738*7c478bd9Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
739*7c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
740*7c478bd9Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
741*7c478bd9Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
742*7c478bd9Sstevel@tonic-gate  * SUCH DAMAGE.
743*7c478bd9Sstevel@tonic-gate  *
744*7c478bd9Sstevel@tonic-gate  */
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate /*
747*7c478bd9Sstevel@tonic-gate  * Construct the interface list with given address family.
748*7c478bd9Sstevel@tonic-gate  * If it fails, returns -1 and an error message in *errbuf;
749*7c478bd9Sstevel@tonic-gate  * otherwise, returns number of interfaces, and the interface list in *ipaddrp.
750*7c478bd9Sstevel@tonic-gate  */
751*7c478bd9Sstevel@tonic-gate int
752*7c478bd9Sstevel@tonic-gate ifaddrlist(struct ifaddrlist **ipaddrp, int family, char *errbuf)
753*7c478bd9Sstevel@tonic-gate {
754*7c478bd9Sstevel@tonic-gate 	int fd;
755*7c478bd9Sstevel@tonic-gate 	struct lifreq *lifrp, *lifend;
756*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin;
757*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 *sin6;
758*7c478bd9Sstevel@tonic-gate 	struct ifaddrlist *al;
759*7c478bd9Sstevel@tonic-gate 	struct lifconf lifc;
760*7c478bd9Sstevel@tonic-gate 	struct lifreq *ibuf, lifr;
761*7c478bd9Sstevel@tonic-gate 	char device[LIFNAMSIZ + 1];
762*7c478bd9Sstevel@tonic-gate 	struct ifaddrlist *ifaddrlist;
763*7c478bd9Sstevel@tonic-gate 	struct lifnum lifn;
764*7c478bd9Sstevel@tonic-gate 	int lifc_flags = 0;
765*7c478bd9Sstevel@tonic-gate 	int count;
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate 	if (family != AF_INET && family != AF_INET6) {
768*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, "invalid address family");
769*7c478bd9Sstevel@tonic-gate 		return (-1);
770*7c478bd9Sstevel@tonic-gate 	}
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	fd = socket(family, SOCK_DGRAM, 0);
773*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
774*7c478bd9Sstevel@tonic-gate 		(void) snprintf(errbuf, ERRBUFSIZE, "socket: %s",
775*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
776*7c478bd9Sstevel@tonic-gate 		return (-1);
777*7c478bd9Sstevel@tonic-gate 	}
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	/* determine the number of interfaces */
780*7c478bd9Sstevel@tonic-gate 	lifn.lifn_family = family;
781*7c478bd9Sstevel@tonic-gate 	lifn.lifn_flags = lifc_flags;
782*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0) {
783*7c478bd9Sstevel@tonic-gate 		(void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFNUM: %s",
784*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
785*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
786*7c478bd9Sstevel@tonic-gate 		return (-1);
787*7c478bd9Sstevel@tonic-gate 	}
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate 	/* allocate memory for the determined number of interfaces */
790*7c478bd9Sstevel@tonic-gate 	ifaddrlist = calloc((size_t)lifn.lifn_count,
791*7c478bd9Sstevel@tonic-gate 	    (size_t)sizeof (struct ifaddrlist));
792*7c478bd9Sstevel@tonic-gate 	if (ifaddrlist == NULL) {
793*7c478bd9Sstevel@tonic-gate 		(void) snprintf(errbuf, ERRBUFSIZE, "calloc: %s",
794*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
795*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
796*7c478bd9Sstevel@tonic-gate 		return (-1);
797*7c478bd9Sstevel@tonic-gate 	}
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate 	ibuf = calloc((size_t)lifn.lifn_count, (size_t)sizeof (struct lifreq));
800*7c478bd9Sstevel@tonic-gate 	if (ibuf == NULL) {
801*7c478bd9Sstevel@tonic-gate 		(void) snprintf(errbuf, ERRBUFSIZE, "calloc: %s",
802*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
803*7c478bd9Sstevel@tonic-gate 		free(ifaddrlist);
804*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
805*7c478bd9Sstevel@tonic-gate 		return (-1);
806*7c478bd9Sstevel@tonic-gate 	}
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 	/* pull out the interface list from the kernel */
809*7c478bd9Sstevel@tonic-gate 	lifc.lifc_family = family;
810*7c478bd9Sstevel@tonic-gate 	lifc.lifc_len = (int)(lifn.lifn_count * sizeof (struct lifreq));
811*7c478bd9Sstevel@tonic-gate 	lifc.lifc_buf = (caddr_t)ibuf;
812*7c478bd9Sstevel@tonic-gate 	lifc.lifc_flags = lifc_flags;
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, SIOCGLIFCONF, (char *)&lifc) < 0 ||
815*7c478bd9Sstevel@tonic-gate 	    lifc.lifc_len < sizeof (struct lifreq)) {
816*7c478bd9Sstevel@tonic-gate 		(void) snprintf(errbuf, ERRBUFSIZE, "SIOCGLIFCONF: %s",
817*7c478bd9Sstevel@tonic-gate 		    strerror(errno));
818*7c478bd9Sstevel@tonic-gate 		free(ifaddrlist);
819*7c478bd9Sstevel@tonic-gate 		free(ibuf);
820*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
821*7c478bd9Sstevel@tonic-gate 		return (-1);
822*7c478bd9Sstevel@tonic-gate 	}
823*7c478bd9Sstevel@tonic-gate 
824*7c478bd9Sstevel@tonic-gate 	lifrp = ibuf;
825*7c478bd9Sstevel@tonic-gate 	/*LINTED*/
826*7c478bd9Sstevel@tonic-gate 	lifend = (struct lifreq *)((char *)ibuf + lifc.lifc_len);
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	al = ifaddrlist;
829*7c478bd9Sstevel@tonic-gate 	count = 0;
830*7c478bd9Sstevel@tonic-gate 
831*7c478bd9Sstevel@tonic-gate 	/* let's populate the interface entries in the ifaddrlist */
832*7c478bd9Sstevel@tonic-gate 	for (; lifrp < lifend; lifrp++) {
833*7c478bd9Sstevel@tonic-gate 		/*
834*7c478bd9Sstevel@tonic-gate 		 * Need a template to preserve address info that is
835*7c478bd9Sstevel@tonic-gate 		 * used below to locate the next entry.  (Otherwise,
836*7c478bd9Sstevel@tonic-gate 		 * SIOCGLIFFLAGS stomps over it because the requests
837*7c478bd9Sstevel@tonic-gate 		 * are returned in a union.)
838*7c478bd9Sstevel@tonic-gate 		 */
839*7c478bd9Sstevel@tonic-gate 		(void) strncpy(lifr.lifr_name, lifrp->lifr_name,
840*7c478bd9Sstevel@tonic-gate 		    sizeof (lifr.lifr_name));
841*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
842*7c478bd9Sstevel@tonic-gate 			if (errno == ENXIO) {
843*7c478bd9Sstevel@tonic-gate 				continue;
844*7c478bd9Sstevel@tonic-gate 			}
845*7c478bd9Sstevel@tonic-gate 			(void) snprintf(errbuf, ERRBUFSIZE,
846*7c478bd9Sstevel@tonic-gate 			    "SIOCGLIFFLAGS: %.*s: %s",
847*7c478bd9Sstevel@tonic-gate 			    (int)sizeof (lifr.lifr_name), lifr.lifr_name,
848*7c478bd9Sstevel@tonic-gate 			    strerror(errno));
849*7c478bd9Sstevel@tonic-gate 			free(ifaddrlist);
850*7c478bd9Sstevel@tonic-gate 			free(ibuf);
851*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
852*7c478bd9Sstevel@tonic-gate 			return (-1);
853*7c478bd9Sstevel@tonic-gate 		}
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate 		al->flags = lifr.lifr_flags;
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate 		/* get the interface address */
858*7c478bd9Sstevel@tonic-gate 		(void) strncpy(device, lifr.lifr_name, sizeof (device));
859*7c478bd9Sstevel@tonic-gate 		device[sizeof (device) - 1] = '\0';
860*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, SIOCGLIFADDR, (char *)&lifr) < 0) {
861*7c478bd9Sstevel@tonic-gate 			(void) snprintf(errbuf, ERRBUFSIZE,
862*7c478bd9Sstevel@tonic-gate 			    "SIOCGLIFADDR: %s: %s", device, strerror(errno));
863*7c478bd9Sstevel@tonic-gate 			free(ifaddrlist);
864*7c478bd9Sstevel@tonic-gate 			free(ibuf);
865*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
866*7c478bd9Sstevel@tonic-gate 			return (-1);
867*7c478bd9Sstevel@tonic-gate 		}
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate 		if (family == AF_INET) {
870*7c478bd9Sstevel@tonic-gate 			sin = (struct sockaddr_in *)&lifr.lifr_addr;
871*7c478bd9Sstevel@tonic-gate 			al->addr.addr = sin->sin_addr;
872*7c478bd9Sstevel@tonic-gate 		} else {
873*7c478bd9Sstevel@tonic-gate 			sin6 = (struct sockaddr_in6 *)&lifr.lifr_addr;
874*7c478bd9Sstevel@tonic-gate 			al->addr.addr6 = sin6->sin6_addr;
875*7c478bd9Sstevel@tonic-gate 		}
876*7c478bd9Sstevel@tonic-gate 
877*7c478bd9Sstevel@tonic-gate 		(void) strncpy(al->device, device, sizeof (device));
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate 		/* get the interface index */
880*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, SIOCGLIFINDEX, (char *)&lifr) < 0) {
881*7c478bd9Sstevel@tonic-gate 			(void) snprintf(errbuf, ERRBUFSIZE,
882*7c478bd9Sstevel@tonic-gate 			    "SIOCGLIFADDR: %s: %s", device, strerror(errno));
883*7c478bd9Sstevel@tonic-gate 			free(ifaddrlist);
884*7c478bd9Sstevel@tonic-gate 			free(ibuf);
885*7c478bd9Sstevel@tonic-gate 			(void) close(fd);
886*7c478bd9Sstevel@tonic-gate 			return (-1);
887*7c478bd9Sstevel@tonic-gate 		}
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 		al->index = lifr.lifr_index;
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate 		++al;
892*7c478bd9Sstevel@tonic-gate 		++count;
893*7c478bd9Sstevel@tonic-gate 	}
894*7c478bd9Sstevel@tonic-gate 
895*7c478bd9Sstevel@tonic-gate 	free(ibuf);
896*7c478bd9Sstevel@tonic-gate 	(void) close(fd);
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate 	*ipaddrp = ifaddrlist;
899*7c478bd9Sstevel@tonic-gate 
900*7c478bd9Sstevel@tonic-gate 	return (count);
901*7c478bd9Sstevel@tonic-gate }
902