1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * RCM module to prevent plumbed IP addresses from being removed.
28 */
29
30
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <memory.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <thread.h>
38 #include <synch.h>
39 #include <assert.h>
40 #include <errno.h>
41 #include <libintl.h>
42 #include <sys/param.h>
43 #include <sys/wait.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/cladm.h>
47 #include <sys/file.h>
48 #include <sys/ioctl.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
51 #include <sys/time.h>
52 #include <net/if.h>
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
55 #include <netinet/ip6.h>
56 #include <inet/ip.h>
57 #include <inet/ip6.h>
58 #include <libinetutil.h>
59
60 #include "rcm_module.h"
61
62 #define SUNW_IP "SUNW_ip/"
63 #define IP_REG_SIZE (9 + INET6_ADDRSTRLEN)
64 #define IP_ANON_USAGE gettext("Plumbed IP Address")
65 #define IP_SUSPEND_ERR gettext("Plumbed IP Addresses cannot be suspended")
66 #define IP_OFFLINE_ERR gettext("Invalid operation: IP cannot be offlined")
67 #define IP_REMOVE_ERR gettext("Invalid operation: IP cannot be removed")
68 #define IP_REG_FAIL gettext("Registration Failed")
69 #define IP_NO_CLUSTER gettext("Could not read cluster network addresses")
70
71 #define IP_FLAG_NEW 0x00
72 #define IP_FLAG_REG 0x01
73 #define IP_FLAG_CL 0x02
74 #define IP_FLAG_IGNORE 0x04
75 #define IP_FLAG_DELETE 0x08
76
77 static int ip_anon_register(rcm_handle_t *);
78 static int ip_anon_unregister(rcm_handle_t *);
79 static int ip_anon_getinfo(rcm_handle_t *, char *, id_t, uint_t,
80 char **, char **, nvlist_t *, rcm_info_t **);
81 static int ip_anon_suspend(rcm_handle_t *, char *, id_t,
82 timespec_t *, uint_t, char **, rcm_info_t **);
83 static int ip_anon_resume(rcm_handle_t *, char *, id_t, uint_t,
84 char **, rcm_info_t **);
85 static int ip_anon_offline(rcm_handle_t *, char *, id_t, uint_t,
86 char **, rcm_info_t **);
87 static int ip_anon_online(rcm_handle_t *, char *, id_t, uint_t,
88 char **, rcm_info_t **);
89 static int ip_anon_remove(rcm_handle_t *, char *, id_t, uint_t,
90 char **, rcm_info_t **);
91
92 static int exclude_ipv4(cladm_netaddrs_t exclude_addrs,
93 ipaddr_t address);
94 static int exclude_ipv6(cladm_netaddrs_t exclude_addrs,
95 uint32_t address[4]);
96
97
98 typedef struct ip_status {
99 int flags;
100 char device[IP_REG_SIZE];
101 struct ip_status *next;
102 } ip_status_t;
103
104 static ip_status_t *findreg(char *reg);
105 static ip_status_t *addreg(char *reg);
106 static int deletereg(ip_status_t *entry);
107
108 static ip_status_t *ip_list = NULL;
109 static mutex_t ip_list_lock;
110
111 static struct rcm_mod_ops ip_anon_ops =
112 {
113 RCM_MOD_OPS_VERSION,
114 ip_anon_register,
115 ip_anon_unregister,
116 ip_anon_getinfo,
117 ip_anon_suspend,
118 ip_anon_resume,
119 ip_anon_offline,
120 ip_anon_online,
121 ip_anon_remove,
122 NULL,
123 NULL,
124 NULL
125 };
126
127 struct rcm_mod_ops *
rcm_mod_init()128 rcm_mod_init()
129 {
130 return (&ip_anon_ops);
131 }
132
133 const char *
rcm_mod_info()134 rcm_mod_info()
135 {
136 return ("RCM IP address module 1.4");
137 }
138
139 int
rcm_mod_fini()140 rcm_mod_fini()
141 {
142 ip_status_t *tlist;
143
144 /* free the registration list */
145
146 (void) mutex_lock(&ip_list_lock);
147 while (ip_list != NULL) {
148 tlist = ip_list->next;
149 free(ip_list);
150 ip_list = tlist;
151 }
152 (void) mutex_unlock(&ip_list_lock);
153
154 (void) mutex_destroy(&ip_list_lock);
155 return (RCM_SUCCESS);
156 }
157
158 static int
ip_anon_register(rcm_handle_t * hdl)159 ip_anon_register(rcm_handle_t *hdl)
160 {
161 int bootflags;
162 struct ifaddrlist *al = NULL, *al6 = NULL;
163 char errbuf[ERRBUFSIZE];
164 char treg[IP_REG_SIZE], tstr[IP_REG_SIZE];
165 cladm_netaddrs_t exclude_addrs;
166 int num_ifs, num_ifs6, i, ret;
167 uint32_t num_exclude_addrs = 0;
168 ip_status_t *tlist, *tentry;
169
170 (void) mutex_lock(&ip_list_lock);
171
172 rcm_log_message(RCM_DEBUG, "ip_anon: registration refresh.\n");
173
174 exclude_addrs.cladm_num_netaddrs = 0;
175
176 if (_cladm(CL_INITIALIZE, CL_GET_BOOTFLAG, &bootflags) != 0) {
177 rcm_log_message(RCM_ERROR,
178 gettext("unable to check cluster status\n"));
179 (void) mutex_unlock(&ip_list_lock);
180 return (RCM_FAILURE);
181 }
182
183 rcm_log_message(RCM_DEBUG,
184 "ip_anon: cladm bootflags=%d\n", bootflags);
185
186 if (bootflags == 3) {
187
188 /* build the exclusion list */
189
190 if ((ret = _cladm(CL_CONFIG, CL_GET_NUM_NETADDRS,
191 &num_exclude_addrs)) == 0) {
192 exclude_addrs.cladm_num_netaddrs = num_exclude_addrs;
193
194 if (num_exclude_addrs == 0)
195 rcm_log_message(RCM_DEBUG,
196 "ip_anon: no addresses excluded\n");
197 else {
198 if ((exclude_addrs.cladm_netaddrs_array =
199 malloc(sizeof (cladm_netaddr_entry_t) *
200 (num_exclude_addrs))) == NULL) {
201 rcm_log_message(RCM_ERROR,
202 gettext("out of memory\n"));
203 (void) mutex_unlock(&ip_list_lock);
204 return (RCM_FAILURE);
205 }
206
207 if ((ret = _cladm(CL_CONFIG,
208 CL_GET_NETADDRS, &exclude_addrs))
209 != 0) {
210 rcm_log_message(RCM_ERROR,
211 IP_NO_CLUSTER);
212 (void) mutex_unlock(&ip_list_lock);
213 return (RCM_FAILURE);
214 }
215 }
216
217 } else {
218 if ((ret != 0) && (errno == EINVAL)) {
219 rcm_log_message(RCM_DEBUG,
220 "no _cladm() backend to get addrs\n");
221 } else {
222 rcm_log_message(RCM_ERROR, IP_NO_CLUSTER);
223 (void) mutex_unlock(&ip_list_lock);
224 return (RCM_FAILURE);
225 }
226 }
227 rcm_log_message(RCM_DEBUG,
228 "cladm returned %d errno=%d\n", ret, errno);
229
230 rcm_log_message(RCM_DEBUG,
231 "ip_anon: num exclude addrs: %d\n",
232 exclude_addrs.cladm_num_netaddrs);
233
234 /* print the exclusion list for debugging purposes */
235
236 for (i = 0; i < exclude_addrs.cladm_num_netaddrs; i++) {
237 (void) strcpy(treg, "<UNKNOWN>");
238 (void) strcpy(tstr, "<UNKNOWN>");
239 if (exclude_addrs.cladm_netaddrs_array[i].\
240 cl_ipversion == IPV4_VERSION) {
241 (void) inet_ntop(AF_INET,
242 &exclude_addrs.cladm_netaddrs_array[i].
243 cl_ipv_un.cl_ipv4.ipv4_netaddr,
244 treg, INET_ADDRSTRLEN);
245
246 (void) inet_ntop(AF_INET,
247 &exclude_addrs.cladm_netaddrs_array[i].
248 cl_ipv_un.cl_ipv4.ipv4_netmask,
249 tstr, INET_ADDRSTRLEN);
250 }
251
252 if (exclude_addrs.cladm_netaddrs_array[i].\
253 cl_ipversion == IPV6_VERSION) {
254 (void) inet_ntop(AF_INET6,
255 &exclude_addrs.cladm_netaddrs_array[i].
256 cl_ipv_un.cl_ipv6.ipv6_netaddr,
257 treg, INET6_ADDRSTRLEN);
258
259 (void) inet_ntop(AF_INET6,
260 &exclude_addrs.cladm_netaddrs_array[i].
261 cl_ipv_un.cl_ipv6.ipv6_netmask,
262 tstr, INET6_ADDRSTRLEN);
263 }
264 rcm_log_message(RCM_DEBUG, "IPV%d: %s %s\n",
265 exclude_addrs.cladm_netaddrs_array[i].
266 cl_ipversion, treg, tstr);
267
268 }
269 }
270
271 /* obtain a list of all IPv4 and IPv6 addresses in the system */
272
273 rcm_log_message(RCM_DEBUG,
274 "ip_anon: obtaining list of IPv4 addresses.\n");
275 num_ifs = ifaddrlist(&al, AF_INET, LIFC_UNDER_IPMP, errbuf);
276 if (num_ifs == -1) {
277 rcm_log_message(RCM_ERROR,
278 gettext("cannot get IPv4 address list errno=%d (%s)\n"),
279 errno, errbuf);
280 (void) mutex_unlock(&ip_list_lock);
281 return (RCM_FAILURE);
282 }
283
284 rcm_log_message(RCM_DEBUG,
285 "ip_anon: obtaining list of IPv6 addresses.\n");
286
287 num_ifs6 = ifaddrlist(&al6, AF_INET6, LIFC_UNDER_IPMP, errbuf);
288 if (num_ifs6 == -1) {
289 rcm_log_message(RCM_ERROR,
290 gettext("cannot get IPv6 address list errno=%d (%s)\n"),
291 errno, errbuf);
292 free(al);
293 (void) mutex_unlock(&ip_list_lock);
294 return (RCM_FAILURE);
295 }
296
297 /* check the state of outstanding registrations against the list */
298
299 rcm_log_message(RCM_DEBUG,
300 "ip_anon: checking outstanding registrations.\n");
301
302 tlist = ip_list;
303 while (tlist != NULL) {
304 tlist->flags |= IP_FLAG_DELETE;
305 tlist = tlist->next;
306 }
307
308 /* IPv4 */
309
310 rcm_log_message(RCM_DEBUG, "ip_anon: checking IPv4 addresses.\n");
311
312 for (i = 0; i < num_ifs; i++) {
313 (void) inet_ntop(AF_INET, &al[i].addr.addr, tstr,
314 INET_ADDRSTRLEN);
315 (void) strcpy(treg, SUNW_IP);
316 (void) strcat(treg, tstr);
317
318 if ((tlist = findreg(treg)) == NULL)
319 tlist = addreg(treg);
320 else
321 tlist->flags &= (~IP_FLAG_DELETE);
322
323 if (tlist == NULL) {
324 rcm_log_message(RCM_ERROR,
325 gettext("out of memory\n"));
326 free(al);
327 free(al6);
328 (void) mutex_unlock(&ip_list_lock);
329 return (RCM_FAILURE);
330 }
331
332 if (exclude_ipv4(exclude_addrs, al[i].addr.addr.s_addr))
333 tlist->flags |= IP_FLAG_CL;
334 }
335
336 /* IPv6 */
337
338 rcm_log_message(RCM_DEBUG, "ip_anon: checking IPv6 addresses.\n");
339
340 for (i = 0; i < num_ifs6; i++) {
341 (void) inet_ntop(AF_INET6, &al6[i].addr.addr, tstr,
342 INET6_ADDRSTRLEN);
343 (void) strcpy(treg, SUNW_IP);
344 (void) strcat(treg, tstr);
345
346 if ((tlist = findreg(treg)) == NULL)
347 tlist = addreg(treg);
348 else
349 tlist->flags &= (~IP_FLAG_DELETE);
350
351 if (tlist == NULL) {
352 rcm_log_message(RCM_ERROR,
353 gettext("out of memory\n"));
354 free(al);
355 free(al6);
356 (void) mutex_unlock(&ip_list_lock);
357 return (RCM_FAILURE);
358 }
359
360 if (exclude_ipv6(exclude_addrs, al6[i].addr.addr6._S6_un.\
361 _S6_u32))
362 tlist->flags |= IP_FLAG_CL;
363 }
364
365 rcm_log_message(RCM_DEBUG, "ip_anon: updating reg. state.\n");
366
367 /* examine the list of ip address registrations and their state */
368
369 tlist = ip_list;
370 while (tlist != NULL) {
371 tentry = tlist;
372 tlist = tlist->next;
373
374 if (tentry->flags & IP_FLAG_DELETE) {
375 if (tentry->flags & IP_FLAG_REG) {
376 rcm_log_message(RCM_DEBUG,
377 "ip_anon: unregistering interest in %s\n",
378 tentry->device);
379 if (rcm_unregister_interest(hdl,
380 tentry->device, 0) != 0) {
381 rcm_log_message(RCM_ERROR,
382 gettext("failed to unregister"));
383 }
384 }
385 (void) deletereg(tentry);
386 } else if (!(tentry->flags & IP_FLAG_IGNORE)) {
387 /*
388 * If the registration is not a clustered devices and
389 * not already registered, then RCM doesn't
390 * currently know about it.
391 */
392 if (!(tentry->flags & IP_FLAG_CL) &&
393 !(tentry->flags & IP_FLAG_REG)) {
394 tentry->flags |= IP_FLAG_REG;
395 rcm_log_message(RCM_DEBUG,
396 "ip_anon: registering interest in %s\n",
397 tentry->device);
398 if (rcm_register_interest(hdl,
399 tentry->device, 0, NULL) !=
400 RCM_SUCCESS) {
401 rcm_log_message(RCM_ERROR,
402 IP_REG_FAIL);
403 free(al);
404 free(al6);
405 (void) mutex_unlock(&ip_list_lock);
406 return (RCM_FAILURE);
407 } else {
408 rcm_log_message(RCM_DEBUG,
409 "ip_anon: registered %s\n",
410 tentry->device);
411 }
412 }
413
414 /*
415 * If the entry is registered and clustered, then
416 * the configuration has been changed and it
417 * should be unregistered.
418 */
419 if ((tentry->flags & IP_FLAG_REG) &
420 (tentry->flags & IP_FLAG_CL)) {
421 rcm_log_message(RCM_DEBUG,
422 "ip_anon: unregistering in %s\n",
423 tentry->device);
424 if (rcm_unregister_interest(hdl,
425 tentry->device, 0) != 0) {
426 rcm_log_message(RCM_ERROR,
427 gettext("failed to unregister"));
428 }
429 tentry->flags &= (~IP_FLAG_REG);
430 }
431 }
432 }
433
434 tlist = ip_list;
435 while (tlist != NULL) {
436 rcm_log_message(RCM_DEBUG, "ip_anon: %s (%Xh)\n",
437 tlist->device, tlist->flags);
438 tlist = tlist->next;
439 }
440 rcm_log_message(RCM_DEBUG, "ip_anon: registration complete.\n");
441
442 free(al);
443 free(al6);
444 (void) mutex_unlock(&ip_list_lock);
445 return (RCM_SUCCESS);
446 }
447
448 static int
ip_anon_unregister(rcm_handle_t * hdl)449 ip_anon_unregister(rcm_handle_t *hdl)
450 {
451 ip_status_t *tlist;
452
453 (void) mutex_lock(&ip_list_lock);
454
455 tlist = ip_list;
456 while (tlist != NULL) {
457 if ((tlist->flags & IP_FLAG_REG)) {
458 if (rcm_unregister_interest(hdl,
459 tlist->device, 0) != 0) {
460 rcm_log_message(RCM_ERROR,
461 gettext("failed to unregister"));
462 }
463 tlist->flags &= (~IP_FLAG_REG);
464 }
465 tlist = tlist->next;
466 }
467
468 (void) mutex_unlock(&ip_list_lock);
469
470 return (RCM_SUCCESS);
471 }
472
473 /*ARGSUSED*/
474 static int
ip_anon_getinfo(rcm_handle_t * hdl,char * rsrcname,id_t id,uint_t flags,char ** infostr,char ** errstr,nvlist_t * props,rcm_info_t ** dependent)475 ip_anon_getinfo(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
476 char **infostr, char **errstr, nvlist_t *props, rcm_info_t **dependent)
477 {
478
479 assert(rsrcname != NULL && infostr != NULL);
480
481 if ((*infostr = strdup(IP_ANON_USAGE)) == NULL)
482 rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
483
484 return (RCM_SUCCESS);
485 }
486
487 /*ARGSUSED*/
488 static int
ip_anon_suspend(rcm_handle_t * hdl,char * rsrcname,id_t id,timespec_t * interval,uint_t flags,char ** errstr,rcm_info_t ** dependent)489 ip_anon_suspend(rcm_handle_t *hdl, char *rsrcname, id_t id,
490 timespec_t *interval, uint_t flags, char **errstr,
491 rcm_info_t **dependent)
492 {
493 if ((*errstr = strdup(IP_SUSPEND_ERR)) == NULL)
494 rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
495
496 return (RCM_FAILURE);
497 }
498
499 /*ARGSUSED*/
500 static int
ip_anon_resume(rcm_handle_t * hdl,char * rsrcname,id_t id,uint_t flags,char ** errstr,rcm_info_t ** dependent)501 ip_anon_resume(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
502 char **errstr, rcm_info_t **dependent)
503 {
504 return (RCM_SUCCESS);
505 }
506
507 /*ARGSUSED*/
508 static int
ip_anon_offline(rcm_handle_t * hdl,char * rsrcname,id_t id,uint_t flags,char ** errstr,rcm_info_t ** dependent)509 ip_anon_offline(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
510 char **errstr, rcm_info_t **dependent)
511 {
512 if ((*errstr = strdup(IP_OFFLINE_ERR)) == NULL)
513 rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
514
515 return (RCM_FAILURE);
516 }
517
518 /*ARGSUSED*/
519 static int
ip_anon_online(rcm_handle_t * hdl,char * rsrcname,id_t id,uint_t flags,char ** errstr,rcm_info_t ** dependent)520 ip_anon_online(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
521 char **errstr, rcm_info_t **dependent)
522 {
523 return (RCM_SUCCESS);
524 }
525
526 /*ARGSUSED*/
527 static int
ip_anon_remove(rcm_handle_t * hdl,char * rsrcname,id_t id,uint_t flags,char ** errstr,rcm_info_t ** dependent)528 ip_anon_remove(rcm_handle_t *hdl, char *rsrcname, id_t id, uint_t flags,
529 char **errstr, rcm_info_t **dependent)
530 {
531 if ((*errstr = strdup(IP_REMOVE_ERR)) == NULL)
532 rcm_log_message(RCM_ERROR, gettext("strdup failure\n"));
533
534 return (RCM_FAILURE);
535 }
536
537 /*
538 * Call with ip_list_lock held.
539 */
540
541 static ip_status_t *
findreg(char * reg)542 findreg(char *reg)
543 {
544 ip_status_t *tlist;
545 int done;
546
547 tlist = ip_list;
548 done = 0;
549 while ((tlist != NULL) && (!done)) {
550 if (strcmp(tlist->device, reg) == 0)
551 done = 1;
552 else
553 tlist = tlist->next;
554 }
555
556 return (tlist);
557 }
558
559 static ip_status_t *
addreg(char * reg)560 addreg(char *reg)
561 {
562 ip_status_t *tlist, *tentry;
563
564 tentry = (ip_status_t *)malloc(sizeof (ip_status_t));
565 if (tentry == NULL)
566 return (tentry);
567
568 tentry->flags = IP_FLAG_NEW;
569 tentry->next = NULL;
570 (void) strcpy(tentry->device, reg);
571
572 if (ip_list == NULL)
573 ip_list = tentry;
574 else {
575 tlist = ip_list;
576 while (tlist->next != NULL)
577 tlist = tlist->next;
578 tlist->next = tentry;
579 }
580
581 return (tentry);
582 }
583
584 static int
deletereg(ip_status_t * entry)585 deletereg(ip_status_t *entry)
586 {
587 ip_status_t *tlist;
588
589 if (entry == NULL)
590 return (-1);
591
592 if (entry == ip_list) {
593 ip_list = ip_list->next;
594 free(entry);
595 } else {
596 tlist = ip_list;
597 while ((tlist->next != NULL) && (tlist->next != entry))
598 tlist = tlist->next;
599
600 if (tlist->next != entry)
601 return (-1);
602 tlist->next = entry->next;
603 free(entry);
604 }
605 return (0);
606 }
607
608 static int
exclude_ipv4(cladm_netaddrs_t exclude_addrs,ipaddr_t address)609 exclude_ipv4(cladm_netaddrs_t exclude_addrs, ipaddr_t address)
610 {
611 int i;
612 char taddr[IP_REG_SIZE], tmask[IP_REG_SIZE], tmatch[IP_REG_SIZE];
613 ipaddr_t ipv4_netaddr, ipv4_netmask;
614
615 (void) inet_ntop(AF_INET, &address, taddr, INET_ADDRSTRLEN);
616
617 rcm_log_message(RCM_DEBUG, "ip_anon: exclude_ipv4 (%s, %d)\n",
618 taddr, exclude_addrs.cladm_num_netaddrs);
619 /*
620 * If this falls in the exclusion list, the IP_FLAG_CL
621 * bit should be set for the adapter.
622 */
623 for (i = 0; i < exclude_addrs.cladm_num_netaddrs; i++) {
624 if (exclude_addrs.cladm_netaddrs_array[i].\
625 cl_ipversion == IPV4_VERSION) {
626
627 ipv4_netaddr = exclude_addrs.\
628 cladm_netaddrs_array[i].cl_ipv_un.cl_ipv4.\
629 ipv4_netaddr;
630 ipv4_netmask = exclude_addrs.\
631 cladm_netaddrs_array[i].cl_ipv_un.cl_ipv4.\
632 ipv4_netmask;
633
634 (void) inet_ntop(AF_INET, &ipv4_netaddr, tmatch,
635 INET_ADDRSTRLEN);
636 (void) inet_ntop(AF_INET, &ipv4_netmask, tmask,
637 INET_ADDRSTRLEN);
638
639 if ((address & ipv4_netmask) == ipv4_netaddr) {
640 rcm_log_message(RCM_DEBUG,
641 "ip_anon: matched %s:%s => %s\n",
642 taddr, tmask, tmatch);
643 return (1);
644 }
645 }
646 }
647 rcm_log_message(RCM_DEBUG, "ip_anon: no match for %s\n",
648 taddr);
649 return (0);
650 }
651
652 static int
exclude_ipv6(cladm_netaddrs_t exclude_addrs,uint32_t address[4])653 exclude_ipv6(cladm_netaddrs_t exclude_addrs, uint32_t address[4])
654 {
655 int i, j, numequal;
656 uint32_t addr[4], ipv6_netaddr[4], ipv6_netmask[4];
657 char taddr[IP_REG_SIZE], tmask[IP_REG_SIZE], tmatch[IP_REG_SIZE];
658
659 (void) inet_ntop(AF_INET6, address, taddr, INET6_ADDRSTRLEN);
660
661 /*
662 * If this falls in the exclusion list, the IP_FLAG_CL
663 * bit should be set for the adapter.
664 */
665
666 for (i = 0; i < exclude_addrs.cladm_num_netaddrs; i++) {
667 if (exclude_addrs.cladm_netaddrs_array[i].\
668 cl_ipversion == IPV6_VERSION) {
669 numequal = 0;
670 for (j = 0; j < 4; j++) {
671 ipv6_netaddr[j] = exclude_addrs.\
672 cladm_netaddrs_array[i].\
673 cl_ipv_un.cl_ipv6.ipv6_netaddr[j];
674
675 ipv6_netmask[j] = exclude_addrs.\
676 cladm_netaddrs_array[i].\
677 cl_ipv_un.cl_ipv6.ipv6_netmask[j];
678
679 addr[j] = address[j] & ipv6_netmask[j];
680 if (addr[j] == ipv6_netaddr[j])
681 numequal++;
682 }
683
684 (void) inet_ntop(AF_INET6, ipv6_netaddr, tmatch,
685 INET6_ADDRSTRLEN);
686 (void) inet_ntop(AF_INET6, ipv6_netmask, tmask,
687 INET6_ADDRSTRLEN);
688
689 if (numequal == 4)
690 return (1);
691 }
692 }
693 rcm_log_message(RCM_DEBUG, "ip_anon: no match for %s\n",
694 taddr);
695 return (0);
696 }
697