]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/in6_prefix.c
2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 /* $KAME: in6_prefix.c,v 1.27 2000/03/29 23:13:13 itojun Exp $ */
32 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
33 * All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the project nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * Copyright (c) 1982, 1986, 1991, 1993
62 * The Regents of the University of California. All rights reserved.
64 * Redistribution and use in source and binary forms, with or without
65 * modification, are permitted provided that the following conditions
67 * 1. Redistributions of source code must retain the above copyright
68 * notice, this list of conditions and the following disclaimer.
69 * 2. Redistributions in binary form must reproduce the above copyright
70 * notice, this list of conditions and the following disclaimer in the
71 * documentation and/or other materials provided with the distribution.
72 * 3. All advertising materials mentioning features or use of this software
73 * must display the following acknowledgement:
74 * This product includes software developed by the University of
75 * California, Berkeley and its contributors.
76 * 4. Neither the name of the University nor the names of its contributors
77 * may be used to endorse or promote products derived from this software
78 * without specific prior written permission.
80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92 * @(#)in.c 8.2 (Berkeley) 11/15/93
95 #include <sys/param.h>
96 #include <sys/malloc.h>
97 #include <sys/kernel.h>
98 #include <sys/socket.h>
99 #include <sys/socketvar.h>
100 #include <sys/sockio.h>
101 #include <sys/systm.h>
102 #include <sys/syslog.h>
103 #include <sys/proc.h>
107 #include <netinet/in.h>
108 #include <netinet/in_var.h>
109 #include <netinet/ip6.h>
110 #include <netinet6/in6_prefix.h>
111 #include <netinet6/ip6_var.h>
114 #define M_IP6RR M_IP6MISC
115 #define M_RR_ADDR M_IP6MISC
117 static MALLOC_DEFINE(M_IP6RR
, "ip6rr", "IPv6 Router Renumbering Prefix");
118 static MALLOC_DEFINE(M_RR_ADDR
, "rp_addr", "IPv6 Router Renumbering Ifid");
121 struct rr_prhead rr_prefix
;
123 #include <net/net_osdep.h>
125 static void add_each_addr(struct socket
*so
, struct rr_prefix
*rpp
,
126 struct rp_addr
*rap
);
127 static int create_ra_entry(struct rp_addr
**rapp
);
128 static int add_each_prefix(struct socket
*so
, struct rr_prefix
*rpp
);
129 static void free_rp_entries(struct rr_prefix
*rpp
);
130 static int link_stray_ia6s(struct rr_prefix
*rpp
);
131 static void rp_remove(struct rr_prefix
*rpp
);
132 extern lck_mtx_t
*prefix6_mutex
;
135 * Copy bits from src to tgt, from off bit for len bits.
136 * Caller must specify collect tgtsize and srcsize.
139 bit_copy(char *tgt
, u_int tgtsize
, char *src
, u_int srcsize
,
140 u_int off
, u_int len
)
144 /* arg values check */
145 if (srcsize
< off
|| srcsize
< (off
+ len
) ||
146 tgtsize
< off
|| tgtsize
< (off
+ len
)) {
148 "in6_prefix.c: bit_copy: invalid args: srcsize %d,\n"
149 "tgtsize %d, off %d, len %d\n", srcsize
, tgtsize
, off
,
154 /* search start point */
155 for (sp
= src
, tp
= tgt
; off
>= 8; sp
++, tp
++)
157 /* copy starting bits */
162 startbits
= min((8 - off
), len
);
164 for (setbit
= (0x80 >> off
); startbits
;
165 setbit
>>= 1, startbits
--, len
--)
166 *tp
|= (setbit
& *sp
);
170 /* copy midium bits */
171 for (; len
>= 8; sp
++, tp
++) {
175 /* copy ending bits */
179 for (setbit
= 0x80; len
; setbit
>>= 1, len
--)
180 *tp
|= (setbit
& *sp
);
184 static struct ifprefix
*
185 in6_prefixwithifp(struct ifnet
*ifp
, int plen
, struct in6_addr
*dst
)
187 struct ifprefix
*ifpr
;
189 /* search matched prefix */
190 ifnet_lock_shared(ifp
);
191 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
;
192 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
))
194 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
195 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
197 if (plen
<= in6_matchlen(dst
, IFPR_IN6(ifpr
)))
200 ifnet_lock_done(ifp
);
206 * Search prefix which matches arg prefix as specified in
207 * draft-ietf-ipngwg-router-renum-08.txt
209 static struct rr_prefix
*
210 search_matched_prefix(struct ifnet
*ifp
, struct in6_prefixreq
*ipr
)
212 struct ifprefix
*ifpr
;
214 struct rr_prefix
*rpp
;
216 /* search matched prefix */
217 ifpr
= in6_prefixwithifp(ifp
, ipr
->ipr_plen
,
218 &ipr
->ipr_prefix
.sin6_addr
);
220 return ifpr2rp(ifpr
);
223 * search matched addr, and then search prefix
224 * which matches the addr
227 ifnet_lock_shared(ifp
);
228 TAILQ_FOREACH(ifa
, &ifp
->if_addrlist
, ifa_list
)
231 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
) {
236 in6_matchlen(&ipr
->ipr_prefix
.sin6_addr
, IFA_IN6(ifa
))) {
243 ifnet_lock_done(ifp
);
246 IFA_LOCK_ASSERT_HELD(ifa
);
247 rpp
= ifpr2rp(((struct in6_ifaddr
*)ifa
)->ia6_ifpr
);
250 ifnet_lock_done(ifp
);
254 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
;
255 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
))
257 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
258 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
260 if (ifpr
->ifpr_plen
<= in6_matchlen(IFA_IN6(ifa
),
264 ifnet_lock_done(ifp
);
266 log(LOG_ERR
, "in6_prefix.c: search_matched_prefix: addr %s"
267 "has no pointer to prefix %s\n", ip6_sprintf(IFA_IN6(ifa
)),
268 ip6_sprintf(IFPR_IN6(ifpr
)));
269 return ifpr2rp(ifpr
);
273 * Search prefix which matches arg prefix as specified in
274 * draft-ietf-ipngwg-router-renum-08.txt, and mark it if exists.
275 * Return 1 if anything matched, and 0 if nothing matched.
278 mark_matched_prefixes(u_int32_t cmd
, struct ifnet
*ifp
, struct in6_rrenumreq
*irr
)
280 struct ifprefix
*ifpr
;
282 int matchlen
, matched
= 0;
284 /* search matched prefixes */
285 ifnet_lock_exclusive(ifp
); /* Should if_prefixhead be protected by IPv6?? */
286 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
;
287 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
))
289 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
290 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
292 matchlen
= in6_matchlen(&irr
->irr_matchprefix
.sin6_addr
,
294 if (irr
->irr_m_minlen
> ifpr
->ifpr_plen
||
295 irr
->irr_m_maxlen
< ifpr
->ifpr_plen
||
296 irr
->irr_m_len
> matchlen
)
299 ifpr2rp(ifpr
)->rp_statef_addmark
= 1;
300 if (cmd
== SIOCCIFPREFIX_IN6
)
301 ifpr2rp(ifpr
)->rp_statef_delmark
= 1;
305 * search matched addr, and then search prefixes
306 * which matche the addr
308 TAILQ_FOREACH(ifa
, &ifp
->if_addrlist
, ifa_list
)
310 struct rr_prefix
*rpp
;
313 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
) {
317 matchlen
= in6_matchlen(&irr
->irr_matchprefix
.sin6_addr
,
319 if (irr
->irr_m_minlen
> matchlen
||
320 irr
->irr_m_maxlen
< matchlen
|| irr
->irr_m_len
> matchlen
) {
324 rpp
= ifpr2rp(((struct in6_ifaddr
*)ifa
)->ia6_ifpr
);
327 rpp
->rp_statef_addmark
= 1;
328 if (cmd
== SIOCCIFPREFIX_IN6
)
329 rpp
->rp_statef_delmark
= 1;
331 log(LOG_WARNING
, "in6_prefix.c: mark_matched_prefixes:"
332 "no back pointer to ifprefix for %s. "
333 "ND autoconfigured addr?\n",
334 ip6_sprintf(IFA_IN6(ifa
)));
338 ifnet_lock_done(ifp
);
343 * Mark global prefixes as to be deleted.
346 delmark_global_prefixes(struct ifnet
*ifp
, __unused
struct in6_rrenumreq
*irr
)
348 struct ifprefix
*ifpr
;
350 /* search matched prefixes */
351 ifnet_lock_exclusive(ifp
);
352 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
;
353 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
))
355 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
356 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
358 /* mark delete global prefix */
359 if (in6_addrscope(RP_IN6(ifpr2rp(ifpr
))) ==
360 IPV6_ADDR_SCOPE_GLOBAL
)
361 ifpr2rp(ifpr
)->rp_statef_delmark
= 1;
363 ifnet_lock_done(ifp
);
366 /* Unmark prefixes */
368 unmark_prefixes(struct ifnet
*ifp
)
370 struct ifprefix
*ifpr
;
372 /* unmark all prefix */
373 ifnet_lock_exclusive(ifp
);
374 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
;
375 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
))
377 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
378 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
381 ifpr2rp(ifpr
)->rp_statef_addmark
= 0;
382 ifpr2rp(ifpr
)->rp_statef_delmark
= 0;
384 ifnet_lock_done(ifp
);
389 init_prefix_ltimes(struct rr_prefix
*rpp
)
391 struct timeval timenow
;
393 getmicrotime(&timenow
);
395 if (rpp
->rp_pltime
== RR_INFINITE_LIFETIME
||
396 rpp
->rp_rrf_decrprefd
== 0)
397 rpp
->rp_preferred
= 0;
399 rpp
->rp_preferred
= timenow
.tv_sec
+ rpp
->rp_pltime
;
400 if (rpp
->rp_vltime
== RR_INFINITE_LIFETIME
||
401 rpp
->rp_rrf_decrvalid
== 0)
404 rpp
->rp_expire
= timenow
.tv_sec
+ rpp
->rp_vltime
;
408 rr_are_ifid_equal(struct in6_addr
*ii1
, struct in6_addr
*ii2
, int ii_len
)
410 int ii_bytelen
, ii_bitlen
;
411 int p_bytelen
, p_bitlen
;
415 ii_len
> 124) { /* as RFC2373, prefix is at least 4 bit */
416 log(LOG_ERR
, "rr_are_ifid_equal: invalid ifid length(%d)\n",
421 ii_bytelen
= ii_len
/ 8;
422 ii_bitlen
= ii_len
% 8;
424 p_bytelen
= sizeof(struct in6_addr
) - ii_bytelen
- 1;
425 p_bitlen
= 8 - ii_bitlen
;
427 if (bcmp(ii1
->s6_addr
+ p_bytelen
+ 1, ii2
->s6_addr
+ p_bytelen
+ 1,
430 if (((ii1
->s6_addr
[p_bytelen
] << p_bitlen
) & 0xff) !=
431 ((ii2
->s6_addr
[p_bytelen
] << p_bitlen
) & 0xff))
437 static struct rp_addr
*
438 search_ifidwithprefix(struct rr_prefix
*rpp
, struct in6_addr
*ifid
)
442 lck_mtx_lock(prefix6_mutex
);
443 LIST_FOREACH(rap
, &rpp
->rp_addrhead
, ra_entry
)
445 if (rr_are_ifid_equal(ifid
, &rap
->ra_ifid
,
446 (sizeof(struct in6_addr
) << 3) -
450 lck_mtx_unlock(prefix6_mutex
);
455 assign_ra_entry(struct rr_prefix
*rpp
, int iilen
, struct in6_ifaddr
*ia
)
460 if ((error
= create_ra_entry(&rap
)) != 0)
463 /* copy interface id part */
464 IFA_LOCK(&ia
->ia_ifa
);
465 bit_copy((caddr_t
)&rap
->ra_ifid
, sizeof(rap
->ra_ifid
) << 3,
466 (caddr_t
)IA6_IN6(ia
), sizeof(*IA6_IN6(ia
)) << 3,
467 rpp
->rp_plen
, iilen
);
468 /* link to ia, and put into list */
470 IFA_ADDREF_LOCKED(&rap
->ra_addr
->ia_ifa
);
471 #if 0 /* Can't do this now, because rpp may be on th stack. should fix it? */
472 ia
->ia6_ifpr
= rp2ifpr(rpp
);
474 IFA_UNLOCK(&ia
->ia_ifa
);
475 lck_mtx_lock(prefix6_mutex
);
476 LIST_INSERT_HEAD(&rpp
->rp_addrhead
, rap
, ra_entry
);
477 lck_mtx_unlock(prefix6_mutex
);
483 * add a link-local address to an interface. we will add new interface address
484 * (prefix database + new interface id).
487 in6_prefix_add_llifid(__unused
int iilen
, struct in6_ifaddr
*ia
)
489 struct rr_prefix
*rpp
;
494 if ((error
= create_ra_entry(&rap
)) != 0)
496 /* copy interface id part */
497 IFA_LOCK(&ia
->ia_ifa
);
498 bit_copy((caddr_t
)&rap
->ra_ifid
, sizeof(rap
->ra_ifid
) << 3,
499 (caddr_t
)IA6_IN6(ia
), sizeof(*IA6_IN6(ia
)) << 3,
500 64, (sizeof(rap
->ra_ifid
) << 3) - 64);
501 IFA_UNLOCK(&ia
->ia_ifa
);
502 /* XXX: init dummy so */
503 bzero(&so
, sizeof(so
));
504 /* insert into list */
505 lck_mtx_lock(prefix6_mutex
);
506 LIST_FOREACH(rpp
, &rr_prefix
, rp_entry
)
509 * do not attempt to add an address, if ifp does not match
511 if (rpp
->rp_ifp
!= ia
->ia_ifp
)
514 LIST_INSERT_HEAD(&rpp
->rp_addrhead
, rap
, ra_entry
);
515 add_each_addr(&so
, rpp
, rap
);
517 lck_mtx_unlock(prefix6_mutex
);
523 * add an address to an interface. if the interface id portion is new,
524 * we will add new interface address (prefix database + new interface id).
527 in6_prefix_add_ifid(int iilen
, struct in6_ifaddr
*ia
)
529 struct in6_addr addr
;
531 struct ifprefix
*ifpr
;
535 IFA_LOCK_SPIN(&ia
->ia_ifa
);
537 plen
= (sizeof(*IA6_IN6(ia
)) << 3) - iilen
;
538 IFA_UNLOCK(&ia
->ia_ifa
);
540 if (IN6_IS_ADDR_LINKLOCAL(&addr
))
541 return(in6_prefix_add_llifid(iilen
, ia
));
542 ifpr
= in6_prefixwithifp(ia
->ia_ifp
, plen
, &addr
);
547 int pplen
= (plen
== 128) ? 64 : plen
; /* XXX hardcoded 64 is bad */
549 /* allocate a prefix for ia, with default properties */
552 bzero(&rp
, sizeof(rp
));
553 rp
.rp_type
= IN6_PREFIX_RR
;
554 rp
.rp_ifp
= ifp
= ia
->ia_ifp
;
556 rp
.rp_prefix
.sin6_len
= sizeof(rp
.rp_prefix
);
557 rp
.rp_prefix
.sin6_family
= AF_INET6
;
558 bit_copy((char *)RP_IN6(&rp
), sizeof(*RP_IN6(&rp
)) << 3,
559 (char *)&addr
, sizeof (addr
) << 3, 0, pplen
);
560 rp
.rp_vltime
= rp
.rp_pltime
= RR_INFINITE_LIFETIME
;
561 rp
.rp_raf_onlink
= 1;
563 /* Is some FlagMasks for rrf necessary? */
564 rp
.rp_rrf_decrvalid
= rp
.rp_rrf_decrprefd
= 0;
565 rp
.rp_origin
= PR_ORIG_RR
; /* can be renumbered */
567 /* create ra_entry */
568 ifnet_lock_shared(ifp
);
569 error
= link_stray_ia6s(&rp
);
570 ifnet_lock_done(ifp
);
572 free_rp_entries(&rp
);
576 /* XXX: init dummy so */
577 bzero(&so
, sizeof(so
));
579 error
= add_each_prefix(&so
, &rp
);
581 /* free each rp_addr entry */
582 free_rp_entries(&rp
);
588 ifpr
= in6_prefixwithifp(ia
->ia_ifp
, pplen
, &addr
);
592 rap
= search_ifidwithprefix(ifpr2rp(ifpr
), &addr
);
594 if (rap
->ra_addr
== NULL
) {
596 IFA_ADDREF(&rap
->ra_addr
->ia_ifa
);
597 } else if (rap
->ra_addr
!= ia
) {
598 /* There may be some inconsistencies between addrs. */
599 log(LOG_ERR
, "ip6_prefix.c: addr %s/%d matched prefix"
600 " already has another ia %p(%s) on its ifid list\n",
601 ip6_sprintf(&addr
), plen
, rap
->ra_addr
,
602 ip6_sprintf(IA6_IN6(rap
->ra_addr
)));
603 return EADDRINUSE
/* XXX */;
605 IFA_LOCK_SPIN(&ia
->ia_ifa
);
607 IFA_UNLOCK(&ia
->ia_ifa
);
610 error
= assign_ra_entry(ifpr2rp(ifpr
), iilen
, ia
);
612 IFA_LOCK_SPIN(&ia
->ia_ifa
);
614 IFA_UNLOCK(&ia
->ia_ifa
);
622 in6_prefix_remove_ifid(__unused
int iilen
, struct in6_ifaddr
*ia
)
625 struct in6_addr addr
;
626 struct ifprefix
*ifpr
;
628 IFA_LOCK_SPIN(&ia
->ia_ifa
);
629 if ((ifpr
= ia
->ia6_ifpr
) == NULL
) {
630 IFA_UNLOCK(&ia
->ia_ifa
);
634 IFA_UNLOCK(&ia
->ia_ifa
);
635 rap
= search_ifidwithprefix(ifpr2rp(ifpr
), &addr
);
637 lck_mtx_lock(prefix6_mutex
);
638 LIST_REMOVE(rap
, ra_entry
);
639 lck_mtx_unlock(prefix6_mutex
);
641 IFA_REMREF(&rap
->ra_addr
->ia_ifa
);
644 FREE(rap
, M_RR_ADDR
);
647 if (LIST_EMPTY(&ifpr2rp(ifpr
)->rp_addrhead
))
648 rp_remove(ifpr2rp(ifpr
));
656 struct ifprefix
*ifpr
, *nextifpr
;
658 /* delete prefixes before ifnet goes away */
659 ifnet_lock_exclusive(ifp
);
660 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
;
663 nextifpr
= TAILQ_NEXT(ifpr
, ifpr_list
);
664 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
665 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
667 (void)delete_each_prefix(ifpr2rp(ifpr
), PR_ORIG_KERNEL
);
669 ifnet_lock_done(ifp
);
673 add_each_addr(struct socket
*so
, struct rr_prefix
*rpp
, struct rp_addr
*rap
)
675 struct in6_ifaddr
*ia6
;
676 struct in6_aliasreq ifra
;
677 struct proc
*p
= current_proc();
678 int error
, p64
= proc_is64bit(p
);
681 bzero(&ifra
, sizeof(ifra
));
682 strncpy(ifra
.ifra_name
, if_name(rpp
->rp_ifp
), sizeof(ifra
.ifra_name
));
683 ifra
.ifra_addr
.sin6_family
= ifra
.ifra_prefixmask
.sin6_family
=
685 ifra
.ifra_addr
.sin6_len
= ifra
.ifra_prefixmask
.sin6_len
=
686 sizeof(ifra
.ifra_addr
);
687 /* copy prefix part */
688 bit_copy((char *)&ifra
.ifra_addr
.sin6_addr
,
689 sizeof(ifra
.ifra_addr
.sin6_addr
) << 3,
690 (char *)RP_IN6(rpp
), sizeof(*RP_IN6(rpp
)) << 3,
692 /* copy interface id part */
693 bit_copy((char *)&ifra
.ifra_addr
.sin6_addr
,
694 sizeof(ifra
.ifra_addr
.sin6_addr
) << 3,
695 (char *)&rap
->ra_ifid
, sizeof(rap
->ra_ifid
) << 3,
696 rpp
->rp_plen
, (sizeof(rap
->ra_ifid
) << 3) - rpp
->rp_plen
);
697 in6_prefixlen2mask(&ifra
.ifra_prefixmask
.sin6_addr
, rpp
->rp_plen
);
698 /* don't care ifra_flags for now */
701 * XXX: if we did this with finite lifetime values, the lifetimes would
702 * decrese in time and never incremented.
703 * we should need more clarifications on the prefix mechanism...
705 ifra
.ifra_lifetime
.ia6t_vltime
= rpp
->rp_vltime
;
706 ifra
.ifra_lifetime
.ia6t_pltime
= rpp
->rp_pltime
;
708 ia6
= in6ifa_ifpwithaddr(rpp
->rp_ifp
, &ifra
.ifra_addr
.sin6_addr
);
710 struct in6_ifaddr
*ria6
= NULL
;
712 IFA_LOCK(&ia6
->ia_ifa
);
713 if (ia6
->ia6_ifpr
== NULL
) {
714 /* link this addr and the prefix each other */
715 if (rap
->ra_addr
!= NULL
)
717 /* Reference held in in6ifa_ifpwithaddr() */
719 ia6
->ia6_ifpr
= rp2ifpr(rpp
);
720 IFA_UNLOCK(&ia6
->ia_ifa
);
722 IFA_REMREF(&ria6
->ia_ifa
);
725 if (ia6
->ia6_ifpr
== rp2ifpr(rpp
)) {
726 if (rap
->ra_addr
!= NULL
)
728 /* Reference held in in6ifa_ifpwithaddr() */
730 IFA_UNLOCK(&ia6
->ia_ifa
);
732 IFA_REMREF(&ria6
->ia_ifa
);
736 * The addr is already assigned to other
738 * There may be some inconsistencies between
740 * e.g. overraped prefixes with common starting
741 * part and different plefixlen.
742 * Or, completely duplicated prefixes?
746 "in6_prefix.c: add_each_addr: addition of an addr %s/%d "
747 "failed because there is already another addr %s/%d\n",
748 ip6_sprintf(&ifra
.ifra_addr
.sin6_addr
), rpp
->rp_plen
,
749 ip6_sprintf(IA6_IN6(ia6
)),
750 in6_mask2len(&ia6
->ia_prefixmask
.sin6_addr
, NULL
));
751 IFA_UNLOCK(&ia6
->ia_ifa
);
752 IFA_REMREF(&ia6
->ia_ifa
);
755 /* propagate ANYCAST flag if it is set for ancestor addr */
756 if (rap
->ra_flags
.anycast
!= 0)
757 ifra
.ifra_flags
|= IN6_IFF_ANYCAST
;
760 #if defined(__LP64__)
761 struct in6_aliasreq_32 ifra_32
;
763 * Use 32-bit ioctl and structure for 32-bit process.
765 in6_aliasreq_64_to_32((struct in6_aliasreq_64
*)&ifra
,
767 error
= in6_control(so
, SIOCAIFADDR_IN6_32
, (caddr_t
)&ifra_32
,
770 error
= in6_control(so
, SIOCAIFADDR_IN6
, (caddr_t
)&ifra
,
772 #endif /* __LP64__ */
774 #if defined(__LP64__)
775 error
= in6_control(so
, SIOCAIFADDR_IN6
, (caddr_t
)&ifra
,
778 struct in6_aliasreq_64 ifra_64
;
780 * Use 32-bit ioctl and structure for 32-bit process.
782 in6_aliasreq_32_to_64((struct in6_aliasreq_32
*)&ifra
,
784 error
= in6_control(so
, SIOCAIFADDR_IN6_64
, (caddr_t
)&ifra_64
,
786 #endif /* __LP64__ */
790 log(LOG_ERR
, "in6_prefix.c: add_each_addr: addition of an addr"
791 "%s/%d failed because in6_control failed for error %d\n",
792 ip6_sprintf(&ifra
.ifra_addr
.sin6_addr
), rpp
->rp_plen
,
798 * link beween this addr and the prefix will be done
799 * in in6_prefix_add_ifid
804 rrpr_update(struct socket
*so
, struct rr_prefix
*new)
806 struct rr_prefix
*rpp
;
807 struct ifprefix
*ifpr
;
810 /* search existing prefix */
811 ifnet_lock_exclusive(new->rp_ifp
);
812 for (ifpr
= TAILQ_FIRST(&new->rp_ifp
->if_prefixhead
); ifpr
;
813 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
))
815 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
816 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
818 if (ifpr
->ifpr_plen
== new->rp_plen
&&
819 in6_are_prefix_equal(IFPR_IN6(ifpr
), RP_IN6(new),
826 * We got a prefix which we have seen in the past.
829 * If the origin of the already-installed prefix is more
830 * preferable than the new one, ignore installation request.
832 if (rpp
->rp_origin
> new->rp_origin
) {
833 ifnet_lock_done(new->rp_ifp
);
837 /* update prefix information */
838 rpp
->rp_flags
.prf_ra
= new->rp_flags
.prf_ra
;
839 if (rpp
->rp_origin
>= PR_ORIG_RR
)
840 rpp
->rp_flags
.prf_rr
= new->rp_flags
.prf_rr
;
841 rpp
->rp_vltime
= new->rp_vltime
;
842 rpp
->rp_pltime
= new->rp_pltime
;
843 rpp
->rp_expire
= new->rp_expire
;
844 rpp
->rp_preferred
= new->rp_preferred
;
845 rpp
->rp_statef_delmark
= 0; /* cancel deletion */
847 * Interface id related update.
848 * add rp_addr entries in new into rpp, if they have not
849 * been already included in rpp.
851 lck_mtx_lock(prefix6_mutex
);
852 while (!LIST_EMPTY(&new->rp_addrhead
))
854 rap
= LIST_FIRST(&new->rp_addrhead
);
855 LIST_REMOVE(rap
, ra_entry
);
856 if (search_ifidwithprefix(rpp
, &rap
->ra_ifid
)
859 IFA_REMREF(&rap
->ra_addr
->ia_ifa
);
862 FREE(rap
, M_RR_ADDR
);
865 LIST_INSERT_HEAD(&rpp
->rp_addrhead
, rap
, ra_entry
);
867 lck_mtx_unlock(prefix6_mutex
);
870 * We got a fresh prefix.
872 /* create new prefix */
873 rpp
= (struct rr_prefix
*)_MALLOC(sizeof(*rpp
), M_IP6RR
,
876 log(LOG_ERR
, "in6_prefix.c: rrpr_update:%d"
877 ": ENOBUFS for rr_prefix\n", __LINE__
);
878 ifnet_lock_done(new->rp_ifp
);
882 lck_mtx_lock(prefix6_mutex
);
884 LIST_INIT(&rpp
->rp_addrhead
);
885 /* move rp_addr entries of new to rpp */
886 while (!LIST_EMPTY(&new->rp_addrhead
))
888 rap
= LIST_FIRST(&new->rp_addrhead
);
889 LIST_REMOVE(rap
, ra_entry
);
890 LIST_INSERT_HEAD(&rpp
->rp_addrhead
, rap
, ra_entry
);
892 lck_mtx_unlock(prefix6_mutex
);
894 /* let rp_ifpr.ifpr_prefix point rr_prefix. */
895 rpp
->rp_ifpr
.ifpr_prefix
= (struct sockaddr
*)&rpp
->rp_prefix
;
896 /* link rr_prefix entry to if_prefixlist */
898 struct ifnet
*ifp
= rpp
->rp_ifp
;
900 if ((ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
))
902 for ( ; TAILQ_NEXT(ifpr
, ifpr_list
);
903 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
))
905 TAILQ_NEXT(ifpr
, ifpr_list
) = rp2ifpr(rpp
);
907 TAILQ_FIRST(&ifp
->if_prefixhead
) =
909 rp2ifpr(rpp
)->ifpr_type
= IN6_PREFIX_RR
;
911 /* link rr_prefix entry to rr_prefix list */
912 lck_mtx_lock(prefix6_mutex
);
913 LIST_INSERT_HEAD(&rr_prefix
, rpp
, rp_entry
);
914 lck_mtx_unlock(prefix6_mutex
);
916 ifnet_lock_done(new->rp_ifp
);
918 if (!new->rp_raf_auto
)
922 * Add an address for each interface id, if it is not yet
923 * If it existed but not pointing to the prefix yet,
924 * init the prefix pointer.
926 lck_mtx_lock(prefix6_mutex
);
927 LIST_FOREACH(rap
, &rpp
->rp_addrhead
, ra_entry
) {
928 struct in6_ifaddr
*ia6
;
930 if ((ia6
= rap
->ra_addr
) != NULL
) {
931 IFA_LOCK(&ia6
->ia_ifa
);
932 if (ia6
->ia6_ifpr
== NULL
)
933 ia6
->ia6_ifpr
= rp2ifpr(rpp
);
934 IFA_UNLOCK(&ia6
->ia_ifa
);
937 add_each_addr(so
, rpp
, rap
);
939 lck_mtx_unlock(prefix6_mutex
);
944 add_each_prefix(struct socket
*so
, struct rr_prefix
*rpp
)
946 init_prefix_ltimes(rpp
);
947 return(rrpr_update(so
, rpp
));
951 rp_remove(struct rr_prefix
*rpp
)
954 /* unlink rp_entry from if_prefixlist */
955 lck_mtx_lock(prefix6_mutex
);
957 struct ifnet
*ifp
= rpp
->rp_ifp
;
958 struct ifprefix
*ifpr
;
960 ifnet_lock_exclusive(ifp
);
961 if ((ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
)) == rp2ifpr(rpp
))
962 TAILQ_FIRST(&ifp
->if_prefixhead
) =
963 TAILQ_NEXT(ifpr
, ifpr_list
);
965 while (TAILQ_NEXT(ifpr
, ifpr_list
) != NULL
&&
966 (TAILQ_NEXT(ifpr
, ifpr_list
) != rp2ifpr(rpp
)))
967 ifpr
= TAILQ_NEXT(ifpr
, ifpr_list
);
968 if (TAILQ_NEXT(ifpr
, ifpr_list
))
969 TAILQ_NEXT(ifpr
, ifpr_list
) =
970 TAILQ_NEXT(rp2ifpr(rpp
), ifpr_list
);
972 printf("Couldn't unlink rr_prefix from ifp\n");
974 ifnet_lock_done(ifp
);
976 /* unlink rp_entry from rr_prefix list */
977 LIST_REMOVE(rpp
, rp_entry
);
978 lck_mtx_unlock(prefix6_mutex
);
983 create_ra_entry(struct rp_addr
**rapp
)
985 *rapp
= (struct rp_addr
*)_MALLOC(sizeof(struct rp_addr
), M_RR_ADDR
,
988 log(LOG_ERR
, "in6_prefix.c:%d: ENOBUFS"
989 "for rp_addr\n", __LINE__
);
992 bzero(*rapp
, sizeof(*(*rapp
)));
999 init_newprefix(struct in6_rrenumreq
*irr
, struct ifprefix
*ifpr
,
1000 struct rr_prefix
*rpp
)
1002 struct rp_addr
*orap
;
1005 bzero(rpp
, sizeof(*rpp
));
1006 rpp
->rp_type
= IN6_PREFIX_RR
;
1007 rpp
->rp_ifp
= ifpr
->ifpr_ifp
;
1008 rpp
->rp_plen
= ifpr
->ifpr_plen
;
1009 rpp
->rp_prefix
.sin6_len
= sizeof(rpp
->rp_prefix
);
1010 rpp
->rp_prefix
.sin6_family
= AF_INET6
;
1011 bit_copy((char *)RP_IN6(rpp
), sizeof(*RP_IN6(rpp
)) << 3,
1012 (char *)&irr
->irr_useprefix
.sin6_addr
,
1013 sizeof(irr
->irr_useprefix
.sin6_addr
) << 3,
1014 0, irr
->irr_u_uselen
);
1015 /* copy keeplen part if necessary as necessary len */
1016 if (irr
->irr_u_uselen
< ifpr
->ifpr_plen
)
1017 bit_copy((char *)RP_IN6(rpp
), sizeof(*RP_IN6(rpp
)) << 3,
1018 (char *)IFPR_IN6(ifpr
), sizeof(*IFPR_IN6(ifpr
)) << 3,
1020 min(ifpr
->ifpr_plen
- irr
->irr_u_uselen
,
1021 irr
->irr_u_keeplen
));
1022 lck_mtx_lock(prefix6_mutex
);
1023 LIST_FOREACH(orap
, &(ifpr2rp(ifpr
)->rp_addrhead
), ra_entry
)
1025 struct rp_addr
*rap
;
1027 struct in6_ifaddr
*ia6
;
1029 if ((error
= create_ra_entry(&rap
)) != 0)
1031 rap
->ra_ifid
= orap
->ra_ifid
;
1032 ia6
= orap
->ra_addr
->ia_ifa
;
1034 IFA_LOCK(&ia6
->ia_ifa
);
1035 rap
->ra_flags
.anycast
=
1036 ((ia6
->ia6_flags
& IN6_IFF_ANYCAST
) != 0) ? 1 : 0;
1037 IFA_UNLOCK(&ia6
->ia_ifa
);
1039 rap
->ra_flags
.anycast
= 0;
1041 LIST_INSERT_HEAD(&rpp
->rp_addrhead
, rap
, ra_entry
);
1043 rpp
->rp_vltime
= irr
->irr_vltime
;
1044 rpp
->rp_pltime
= irr
->irr_pltime
;
1045 rpp
->rp_raf_onlink
= irr
->irr_raf_mask_onlink
? irr
->irr_raf_onlink
:
1046 ifpr2rp(ifpr
)->rp_raf_onlink
;
1047 rpp
->rp_raf_auto
= irr
->irr_raf_mask_auto
? irr
->irr_raf_auto
:
1048 ifpr2rp(ifpr
)->rp_raf_auto
;
1049 /* Is some FlagMasks for rrf necessary? */
1050 rpp
->rp_rrf
= irr
->irr_rrf
;
1051 rpp
->rp_origin
= irr
->irr_origin
;
1052 lck_mtx_unlock(prefix6_mutex
);
1059 free_rp_entries(struct rr_prefix
*rpp
)
1062 * This func is only called with rpp on stack(not on list).
1063 * So no splnet() here
1065 lck_mtx_lock(prefix6_mutex
);
1066 while (!LIST_EMPTY(&rpp
->rp_addrhead
))
1068 struct rp_addr
*rap
;
1070 rap
= LIST_FIRST(&rpp
->rp_addrhead
);
1071 LIST_REMOVE(rap
, ra_entry
);
1073 IFA_REMREF(&rap
->ra_addr
->ia_ifa
);
1074 rap
->ra_addr
= NULL
;
1076 FREE(rap
, M_RR_ADDR
);
1078 lck_mtx_unlock(prefix6_mutex
);
1083 add_useprefixes(struct socket
*so
, struct ifnet
*ifp
,
1084 struct in6_rrenumreq
*irr
)
1086 struct ifprefix
*ifpr
, *nextifpr
;
1087 struct rr_prefix rp
;
1090 /* add prefixes to each of marked prefix */
1091 ifnet_lock_exclusive(ifp
);
1092 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
; ifpr
= nextifpr
)
1094 nextifpr
= TAILQ_NEXT(ifpr
, ifpr_list
);
1095 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
1096 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
1098 if (ifpr2rp(ifpr
)->rp_statef_addmark
) {
1099 if ((error
= init_newprefix(irr
, ifpr
, &rp
)) != 0)
1101 error
= add_each_prefix(so
, &rp
);
1104 ifnet_lock_done(ifp
);
1105 /* free each rp_addr entry */
1106 free_rp_entries(&rp
);
1113 unprefer_prefix(struct rr_prefix
*rpp
)
1115 struct rp_addr
*rap
;
1116 struct timeval timenow
;
1118 getmicrotime(&timenow
);
1120 lck_mtx_lock(prefix6_mutex
);
1121 for (rap
= rpp
->rp_addrhead
.lh_first
; rap
!= NULL
;
1122 rap
= rap
->ra_entry
.le_next
) {
1123 struct in6_ifaddr
*ia6
;
1125 if ((ia6
= rap
->ra_addr
) == NULL
)
1127 IFA_LOCK(&ia6
->ia_ifa
);
1128 ia6
->ia6_lifetime
.ia6t_preferred
= timenow
.tv_sec
;
1129 ia6
->ia6_lifetime
.ia6t_pltime
= 0;
1130 IFA_UNLOCK(&ia6
->ia_ifa
);
1132 lck_mtx_unlock(prefix6_mutex
);
1137 delete_each_prefix(struct rr_prefix
*rpp
, u_char origin
)
1141 if (rpp
->rp_origin
> origin
)
1144 lck_mtx_lock(prefix6_mutex
);
1145 while (rpp
->rp_addrhead
.lh_first
!= NULL
) {
1146 struct rp_addr
*rap
;
1147 struct in6_ifaddr
*ia6
;
1149 rap
= LIST_FIRST(&rpp
->rp_addrhead
);
1153 LIST_REMOVE(rap
, ra_entry
);
1154 if ((ia6
= rap
->ra_addr
) == NULL
) {
1155 FREE(rap
, M_RR_ADDR
);
1158 rap
->ra_addr
= NULL
;
1159 IFA_LOCK(&ia6
->ia_ifa
);
1160 ia6
->ia6_ifpr
= NULL
;
1161 IFA_UNLOCK(&ia6
->ia_ifa
);
1163 in6_purgeaddr(&ia6
->ia_ifa
, 0);
1164 IFA_REMREF(&ia6
->ia_ifa
);
1165 FREE(rap
, M_RR_ADDR
);
1168 lck_mtx_unlock(prefix6_mutex
);
1175 delete_prefixes(struct ifnet
*ifp
, u_char origin
)
1177 struct ifprefix
*ifpr
, *nextifpr
;
1179 /* delete prefixes marked as tobe deleted */
1180 ifnet_lock_exclusive(ifp
);
1181 for (ifpr
= TAILQ_FIRST(&ifp
->if_prefixhead
); ifpr
; ifpr
= nextifpr
)
1183 nextifpr
= TAILQ_NEXT(ifpr
, ifpr_list
);
1184 if (ifpr
->ifpr_prefix
->sa_family
!= AF_INET6
||
1185 ifpr
->ifpr_type
!= IN6_PREFIX_RR
)
1187 if (ifpr2rp(ifpr
)->rp_statef_delmark
)
1188 (void)delete_each_prefix(ifpr2rp(ifpr
), origin
);
1190 ifnet_lock_done(ifp
);
1195 link_stray_ia6s(struct rr_prefix
*rpp
)
1199 ifnet_lock_assert(rpp
->rp_ifp
, IFNET_LCK_ASSERT_OWNED
);
1201 for (ifa
= rpp
->rp_ifp
->if_addrlist
.tqh_first
; ifa
;
1202 ifa
= ifa
->ifa_list
.tqe_next
)
1204 struct rp_addr
*rap
;
1205 struct rr_prefix
*orpp
;
1209 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
) {
1213 if (rpp
->rp_plen
> in6_matchlen(RP_IN6(rpp
), IFA_IN6(ifa
))) {
1217 orpp
= ifpr2rp(((struct in6_ifaddr
*)ifa
)->ia6_ifpr
);
1219 if (!in6_are_prefix_equal(RP_IN6(orpp
), RP_IN6(rpp
),
1221 log(LOG_ERR
, "in6_prefix.c: link_stray_ia6s:"
1222 "addr %s/%d already linked to a prefix"
1223 "and it matches also %s/%d\n",
1224 ip6_sprintf(IFA_IN6(ifa
)), orpp
->rp_plen
,
1225 ip6_sprintf(RP_IN6(rpp
)),
1231 if ((error
= assign_ra_entry(rpp
,
1232 (sizeof(rap
->ra_ifid
) << 3) -
1234 (struct in6_ifaddr
*)ifa
)) != 0)
1241 /* XXX assumes that permission is already checked by the caller */
1243 in6_prefix_ioctl(struct socket
*so
, u_long cmd
, caddr_t data
,
1246 struct rr_prefix
*rpp
, rp_tmp
;
1247 struct rp_addr
*rap
;
1248 struct in6_prefixreq
*ipr
= (struct in6_prefixreq
*)data
;
1249 struct in6_rrenumreq
*irr
= (struct in6_rrenumreq
*)data
;
1254 * Failsafe for erroneous address config program.
1255 * Let's hope rrenumd don't make a mistakes.
1257 if (ipr
->ipr_origin
<= PR_ORIG_RA
)
1258 ipr
->ipr_origin
= PR_ORIG_STATIC
;
1261 case SIOCSGIFPREFIX_IN6
:
1262 delmark_global_prefixes(ifp
, irr
);
1264 case SIOCAIFPREFIX_IN6
:
1265 case SIOCCIFPREFIX_IN6
:
1266 /* check if preferred lifetime > valid lifetime */
1267 if (irr
->irr_pltime
> irr
->irr_vltime
) {
1269 "in6_prefix_ioctl: preferred lifetime"
1270 "(%ld) is greater than valid lifetime(%ld)\n",
1271 (u_int32_t
)irr
->irr_pltime
, (u_int32_t
)irr
->irr_vltime
);
1275 if (mark_matched_prefixes(cmd
, ifp
, irr
)) {
1276 if (irr
->irr_u_uselen
!= 0)
1277 if ((error
= add_useprefixes(so
, ifp
, irr
))
1280 if (cmd
!= SIOCAIFPREFIX_IN6
)
1281 delete_prefixes(ifp
, irr
->irr_origin
);
1283 return (EADDRNOTAVAIL
);
1285 unmark_prefixes(ifp
);
1287 case SIOCGIFPREFIX_IN6
:
1288 rpp
= search_matched_prefix(ifp
, ipr
);
1289 if (rpp
== NULL
|| ifp
!= rpp
->rp_ifp
)
1290 return (EADDRNOTAVAIL
);
1292 ipr
->ipr_origin
= rpp
->rp_origin
;
1293 ipr
->ipr_plen
= rpp
->rp_plen
;
1294 ipr
->ipr_vltime
= rpp
->rp_vltime
;
1295 ipr
->ipr_pltime
= rpp
->rp_pltime
;
1296 ipr
->ipr_flags
= rpp
->rp_flags
;
1297 ipr
->ipr_prefix
= rpp
->rp_prefix
;
1300 case SIOCSIFPREFIX_IN6
:
1301 /* check if preferred lifetime > valid lifetime */
1302 if (ipr
->ipr_pltime
> ipr
->ipr_vltime
) {
1304 "in6_prefix_ioctl: preferred lifetime"
1305 "(%ld) is greater than valid lifetime(%ld)\n",
1306 (u_int32_t
)ipr
->ipr_pltime
, (u_int32_t
)ipr
->ipr_vltime
);
1312 bzero((caddr_t
)&rp_tmp
, sizeof(rp_tmp
));
1313 rp_tmp
.rp_ifp
= ifp
;
1314 rp_tmp
.rp_plen
= ipr
->ipr_plen
;
1315 rp_tmp
.rp_prefix
= ipr
->ipr_prefix
;
1316 rp_tmp
.rp_vltime
= ipr
->ipr_vltime
;
1317 rp_tmp
.rp_pltime
= ipr
->ipr_pltime
;
1318 rp_tmp
.rp_flags
= ipr
->ipr_flags
;
1319 rp_tmp
.rp_origin
= ipr
->ipr_origin
;
1321 /* create rp_addr entries, usually at least for lladdr */
1322 ifnet_lock_shared(ifp
);
1323 if ((error
= link_stray_ia6s(&rp_tmp
)) != 0) {
1324 ifnet_lock_done(ifp
);
1325 free_rp_entries(&rp_tmp
);
1328 for (ifa
= ifp
->if_addrlist
.tqh_first
;
1330 ifa
= ifa
->ifa_list
.tqe_next
)
1333 if (ifa
->ifa_addr
->sa_family
!= AF_INET6
) {
1337 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa
)) == 0) {
1341 if ((error
= create_ra_entry(&rap
)) != 0) {
1343 ifnet_lock_done(ifp
);
1344 free_rp_entries(&rp_tmp
);
1347 /* copy interface id part */
1348 bit_copy((caddr_t
)&rap
->ra_ifid
,
1349 sizeof(rap
->ra_ifid
) << 3,
1350 (caddr_t
)IFA_IN6(ifa
),
1351 sizeof(*IFA_IN6(ifa
)) << 3,
1353 (sizeof(rap
->ra_ifid
) << 3) - rp_tmp
.rp_plen
);
1355 /* insert into list */
1356 lck_mtx_lock(prefix6_mutex
);
1357 LIST_INSERT_HEAD(&rp_tmp
.rp_addrhead
, rap
, ra_entry
);
1358 lck_mtx_unlock(prefix6_mutex
);
1360 ifnet_lock_done(ifp
);
1362 error
= add_each_prefix(so
, &rp_tmp
);
1364 /* free each rp_addr entry */
1365 free_rp_entries(&rp_tmp
);
1368 case SIOCDIFPREFIX_IN6
:
1369 rpp
= search_matched_prefix(ifp
, ipr
);
1370 if (rpp
== NULL
|| ifp
!= rpp
->rp_ifp
)
1371 return (EADDRNOTAVAIL
);
1373 ifnet_lock_exclusive(ifp
);
1374 error
= delete_each_prefix(rpp
, ipr
->ipr_origin
);
1375 ifnet_lock_done(ifp
);