]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/bsd_tcpip/v2_0/src/sys/netinet6/nd6_rtr.c
Initial revision
[karo-tx-redboot.git] / packages / net / bsd_tcpip / v2_0 / src / sys / netinet6 / nd6_rtr.c
1 //==========================================================================
2 //
3 //      src/sys/netinet6/nd6_rtr.c
4 //
5 //==========================================================================
6 //####BSDCOPYRIGHTBEGIN####
7 //
8 // -------------------------------------------
9 //
10 // Portions of this software may have been derived from OpenBSD, 
11 // FreeBSD or other sources, and are covered by the appropriate
12 // copyright disclaimers included herein.
13 //
14 // Portions created by Red Hat are
15 // Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16 //
17 // -------------------------------------------
18 //
19 //####BSDCOPYRIGHTEND####
20 //==========================================================================
21
22 /*      $KAME: nd6_rtr.c,v 1.187 2001/12/18 02:01:25 itojun Exp $       */
23
24 /*
25  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
26  * All rights reserved.
27  *
28  * Redistribution and use in source and binary forms, with or without
29  * modification, are permitted provided that the following conditions
30  * are met:
31  * 1. Redistributions of source code must retain the above copyright
32  *    notice, this list of conditions and the following disclaimer.
33  * 2. Redistributions in binary form must reproduce the above copyright
34  *    notice, this list of conditions and the following disclaimer in the
35  *    documentation and/or other materials provided with the distribution.
36  * 3. Neither the name of the project nor the names of its contributors
37  *    may be used to endorse or promote products derived from this software
38  *    without specific prior written permission.
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  */
52
53 #include <sys/param.h>
54 #include <sys/malloc.h>
55 #include <sys/mbuf.h>
56 #include <sys/socket.h>
57 #include <sys/sockio.h>
58 #include <sys/time.h>
59 #include <sys/errno.h>
60 #include <sys/queue.h>
61 #ifdef __OpenBSD__
62 #include <dev/rndvar.h>
63 #endif
64
65 #include <net/if.h>
66 #include <net/if_types.h>
67 #include <net/if_dl.h>
68 #include <net/route.h>
69 #include <net/radix.h>
70
71 #include <netinet/in.h>
72 #include <netinet6/in6_var.h>
73 #include <netinet6/in6_ifattach.h>
74 #include <netinet/ip6.h>
75 #include <netinet6/ip6_var.h>
76 #include <netinet6/nd6.h>
77 #include <netinet/icmp6.h>
78 #include <netinet6/scope6_var.h>
79
80 #ifdef MIP6
81 #include <netinet6/mip6.h>
82 #endif /* MIP6 */
83
84 #define SDL(s)  ((struct sockaddr_dl *)s)
85
86 static int rtpref __P((struct nd_defrouter *));
87 static struct nd_defrouter *defrtrlist_update __P((struct nd_defrouter *));
88 static struct in6_ifaddr *in6_ifadd __P((struct nd_prefix *));
89 static struct nd_pfxrouter *pfxrtr_lookup __P((struct nd_prefix *,
90         struct nd_defrouter *));
91 static void pfxrtr_add __P((struct nd_prefix *, struct nd_defrouter *));
92 static void pfxrtr_del __P((struct nd_pfxrouter *));
93 static struct nd_pfxrouter *find_pfxlist_reachable_router
94         __P((struct nd_prefix *));
95 static void defrouter_delreq __P((struct nd_defrouter *));
96 static void defrouter_addifreq __P((struct ifnet *));
97 static void defrouter_delifreq __P((void));
98 static void nd6_rtmsg __P((int, struct rtentry *));
99
100 static void in6_init_address_ltimes __P((struct nd_prefix *ndpr,
101                                          struct in6_addrlifetime *lt6));
102
103 static int rt6_deleteroute __P((struct radix_node *, void *));
104
105 extern int nd6_recalc_reachtm_interval;
106
107 static struct ifnet *nd6_defifp;
108 int nd6_defifindex;
109 static struct ifaddr *nd6_defif_installed = NULL;
110
111 int ip6_use_tempaddr = 0;
112
113 int ip6_desync_factor;
114 u_int32_t ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME;
115 u_int32_t ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME;
116 int ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE;
117
118 /* RTPREF_MEDIUM has to be 0! */
119 #define RTPREF_HIGH     1
120 #define RTPREF_MEDIUM   0
121 #define RTPREF_LOW      (-1)
122 #define RTPREF_INVALID  (-2)
123
124 /*
125  * Receive Router Solicitation Message - just for routers.
126  * Router solicitation/advertisement is mostly managed by userland program
127  * (rtadvd) so here we have no function like nd6_ra_output().
128  *
129  * Based on RFC 2461
130  */
131 void
132 nd6_rs_input(m, off, icmp6len)
133         struct  mbuf *m;
134         int off, icmp6len;
135 {
136         struct ifnet *ifp = m->m_pkthdr.rcvif;
137         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
138         struct nd_router_solicit *nd_rs;
139         struct in6_addr saddr6 = ip6->ip6_src;
140 #if 0
141         struct in6_addr daddr6 = ip6->ip6_dst;
142 #endif
143         char *lladdr = NULL;
144         int lladdrlen = 0;
145 #if 0
146         struct sockaddr_dl *sdl = (struct sockaddr_dl *)NULL;
147         struct llinfo_nd6 *ln = (struct llinfo_nd6 *)NULL;
148         struct rtentry *rt = NULL;
149         int is_newentry;
150 #endif
151         union nd_opts ndopts;
152
153         /* If I'm not a router, ignore it. */
154         if (ip6_accept_rtadv != 0 || ip6_forwarding != 1)
155                 goto freeit;
156
157         /* Sanity checks */
158         if (ip6->ip6_hlim != 255) {
159                 nd6log((LOG_ERR,
160                     "nd6_rs_input: invalid hlim (%d) from %s to %s on %s\n",
161                     ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
162                     ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
163                 goto bad;
164         }
165
166         /*
167          * Don't update the neighbor cache, if src = ::.
168          * This indicates that the src has no IP address assigned yet.
169          */
170         if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
171                 goto freeit;
172
173 #ifndef PULLDOWN_TEST
174         IP6_EXTHDR_CHECK(m, off, icmp6len,);
175         nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off);
176 #else
177         IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
178         if (nd_rs == NULL) {
179                 icmp6stat.icp6s_tooshort++;
180                 return;
181         }
182 #endif
183
184         icmp6len -= sizeof(*nd_rs);
185         nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
186         if (nd6_options(&ndopts) < 0) {
187                 nd6log((LOG_INFO,
188                     "nd6_rs_input: invalid ND option, ignored\n"));
189                 /* nd6_options have incremented stats */
190                 goto freeit;
191         }
192
193         if (ndopts.nd_opts_src_lladdr) {
194                 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
195                 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
196         }
197
198         if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
199                 nd6log((LOG_INFO,
200                     "nd6_rs_input: lladdrlen mismatch for %s "
201                     "(if %d, RS packet %d)\n",
202                         ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2));
203                 goto bad;
204         }
205
206         nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
207
208  freeit:
209         m_freem(m);
210         return;
211
212  bad:
213         icmp6stat.icp6s_badrs++;
214         m_freem(m);
215 }
216
217 /*
218  * Receive Router Advertisement Message.
219  *
220  * Based on RFC 2461
221  * TODO: on-link bit on prefix information
222  * TODO: ND_RA_FLAG_{OTHER,MANAGED} processing
223  */
224 void
225 nd6_ra_input(m, off, icmp6len)
226         struct  mbuf *m;
227         int off, icmp6len;
228 {
229         struct ifnet *ifp = m->m_pkthdr.rcvif;
230         struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
231         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
232         struct nd_router_advert *nd_ra;
233         struct in6_addr saddr6 = ip6->ip6_src;
234 #if 0
235         struct in6_addr daddr6 = ip6->ip6_dst;
236         int flags; /* = nd_ra->nd_ra_flags_reserved; */
237         int is_managed = ((flags & ND_RA_FLAG_MANAGED) != 0);
238         int is_other = ((flags & ND_RA_FLAG_OTHER) != 0);
239 #endif
240         union nd_opts ndopts;
241         struct nd_defrouter *dr;
242
243         /*
244          * We only accept RAs only when
245          * the system-wide variable allows the acceptance, and
246          * per-interface variable allows RAs on the receiving interface.  
247          */
248         if (ip6_accept_rtadv == 0)
249                 goto freeit;
250         if (!(nd_ifinfo[ifp->if_index].flags & ND6_IFF_ACCEPT_RTADV))
251                 goto freeit;
252
253         if (ip6->ip6_hlim != 255) {
254                 nd6log((LOG_ERR,
255                     "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n",
256                     ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
257                     ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
258                 goto bad;
259         }
260
261         if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
262                 nd6log((LOG_ERR,
263                     "nd6_ra_input: src %s is not link-local\n",
264                     ip6_sprintf(&saddr6)));
265                 goto bad;
266         }
267
268 #ifndef PULLDOWN_TEST
269         IP6_EXTHDR_CHECK(m, off, icmp6len,);
270         nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
271 #else
272         IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
273         if (nd_ra == NULL) {
274                 icmp6stat.icp6s_tooshort++;
275                 return;
276         }
277 #endif
278
279         icmp6len -= sizeof(*nd_ra);
280         nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
281         if (nd6_options(&ndopts) < 0) {
282                 nd6log((LOG_INFO,
283                     "nd6_ra_input: invalid ND option, ignored\n"));
284                 /* nd6_options have incremented stats */
285                 goto freeit;
286         }
287
288     {
289         struct nd_defrouter dr0;
290         u_int32_t advreachable = nd_ra->nd_ra_reachable;
291 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
292         long time_second = time.tv_sec;
293 #endif
294
295         Bzero(&dr0, sizeof(dr0));
296         dr0.rtaddr = saddr6;
297         dr0.flags  = nd_ra->nd_ra_flags_reserved;
298         dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
299         dr0.expire = time_second + dr0.rtlifetime;
300         dr0.ifp = ifp;
301         dr0.advint = 0;         /* Mobile IPv6 */
302         dr0.advint_expire = 0;  /* Mobile IPv6 */
303         dr0.advints_lost = 0;   /* Mobile IPv6 */
304         /* unspecified or not? (RFC 2461 6.3.4) */
305         if (advreachable) {
306                 NTOHL(advreachable);
307                 if (advreachable <= MAX_REACHABLE_TIME &&
308                     ndi->basereachable != advreachable) {
309                         ndi->basereachable = advreachable;
310                         ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
311                         ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */
312                 }
313         }
314         if (nd_ra->nd_ra_retransmit)
315                 ndi->retrans = ntohl(nd_ra->nd_ra_retransmit);
316         if (nd_ra->nd_ra_curhoplimit)
317                 ndi->chlim = nd_ra->nd_ra_curhoplimit;
318         dr = defrtrlist_update(&dr0);
319     }
320
321         /*
322          * prefix
323          */
324         if (ndopts.nd_opts_pi) {
325                 struct nd_opt_hdr *pt;
326                 struct nd_opt_prefix_info *pi = NULL;
327                 struct nd_prefix pr;
328 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
329                 long time_second = time.tv_sec;
330 #endif
331
332                 for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi;
333                      pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
334                      pt = (struct nd_opt_hdr *)((caddr_t)pt +
335                                                 (pt->nd_opt_len << 3))) {
336                         if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
337                                 continue;
338                         pi = (struct nd_opt_prefix_info *)pt;
339
340                         if (pi->nd_opt_pi_len != 4) {
341                                 nd6log((LOG_INFO,
342                                     "nd6_ra_input: invalid option "
343                                     "len %d for prefix information option, "
344                                     "ignored\n", pi->nd_opt_pi_len));
345                                 continue;
346                         }
347
348                         if (128 < pi->nd_opt_pi_prefix_len) {
349                                 nd6log((LOG_INFO,
350                                     "nd6_ra_input: invalid prefix "
351                                     "len %d for prefix information option, "
352                                     "ignored\n", pi->nd_opt_pi_prefix_len));
353                                 continue;
354                         }
355
356                         if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
357                          || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
358                                 nd6log((LOG_INFO,
359                                     "nd6_ra_input: invalid prefix "
360                                     "%s, ignored\n",
361                                     ip6_sprintf(&pi->nd_opt_pi_prefix)));
362                                 continue;
363                         }
364
365                         /* aggregatable unicast address, rfc2374 */
366                         if ((pi->nd_opt_pi_prefix.s6_addr8[0] & 0xe0) == 0x20
367                          && pi->nd_opt_pi_prefix_len != 64) {
368                                 nd6log((LOG_INFO,
369                                     "nd6_ra_input: invalid prefixlen "
370                                     "%d for rfc2374 prefix %s, ignored\n",
371                                     pi->nd_opt_pi_prefix_len,
372                                     ip6_sprintf(&pi->nd_opt_pi_prefix)));
373                                 continue;
374                         }
375
376                         bzero(&pr, sizeof(pr));
377                         pr.ndpr_prefix.sin6_family = AF_INET6;
378                         pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
379                         pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
380                         pr.ndpr_ifp = (struct ifnet *)m->m_pkthdr.rcvif;
381
382                         pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved &
383                                               ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
384                         pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
385                                             ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
386 #ifdef MIP6
387                         pr.ndpr_raf_router = (pi->nd_opt_pi_flags_reserved &
388                                               ND_OPT_PI_FLAG_ROUTER) ? 1 : 0;
389 #endif /* MIP6 */
390                         pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
391                         pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
392                         pr.ndpr_pltime =
393                                 ntohl(pi->nd_opt_pi_preferred_time);
394                         pr.ndpr_lastupdate = time_second;
395
396                         if (in6_init_prefix_ltimes(&pr))
397                                 continue; /* prefix lifetime init failed */
398 #ifdef MIP6
399                         if (MIP6_IS_MN) {
400                                 if (mip6_prefix_list_update(&saddr6, &pr, dr, m)) {
401                                         mip6log((LOG_ERR,
402                                                  "%s:%d: "
403                                                  "prefix info processing "
404                                                  "failed\n",
405                                                  __FILE__, __LINE__));
406                                         goto freeit;
407                                 }
408                         }
409 #endif /* MIP6 */
410                         (void)prelist_update(&pr, dr, m);
411                 }
412         }
413
414 #ifdef MIP6
415         if (MIP6_IS_MN) {
416                 /* check reachability of all routers. */
417                 mip6_probe_routers();
418         }
419
420         /* update home agent list. */
421         if ((MIP6_IS_MN || MIP6_IS_HA)
422             && dr
423             && (dr->flags & ND_RA_FLAG_HOME_AGENT)) {
424                 if (mip6_ha_list_update_hainfo(&mip6_ha_list,
425                                                dr, ndopts.nd_opts_hai)) {
426                         mip6log((LOG_ERR,
427                                  "%s:%d: global HA list update failed\n",
428                                  __FILE__, __LINE__));
429                 }
430         }
431         if (dr == NULL) {
432                 struct mip6_ha *mha;
433
434                 /* the home agent is shutting down. */
435                 mha = mip6_ha_list_find_withaddr(&mip6_ha_list, &saddr6);
436                 if (mha) {
437                         if (mip6_ha_list_remove(&mip6_ha_list, mha)) {
438                                 mip6log((LOG_ERR,
439                                          "%s:%d: HA entry remove failed.\n",
440                                          __FILE__, __LINE__));
441                         }
442                 }
443         }
444 #endif /* MIP6 */
445
446         /*
447          * MTU
448          */
449         if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
450                 u_int32_t mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
451
452                 /* lower bound */
453                 if (mtu < IPV6_MMTU) {
454                         nd6log((LOG_INFO, "nd6_ra_input: bogus mtu option "
455                             "mtu=%d sent from %s, ignoring\n",
456                             mtu, ip6_sprintf(&ip6->ip6_src)));
457                         goto skip;
458                 }
459
460                 /* upper bound */
461                 if (ndi->maxmtu) {
462                         if (mtu <= ndi->maxmtu) {
463                                 int change = (ndi->linkmtu != mtu);
464
465                                 ndi->linkmtu = mtu;
466                                 if (change) /* in6_maxmtu may change */
467                                         in6_setmaxmtu();
468                         } else {
469                                 nd6log((LOG_INFO, "nd6_ra_input: bogus mtu "
470                                     "mtu=%d sent from %s; "
471                                     "exceeds maxmtu %d, ignoring\n",
472                                     mtu, ip6_sprintf(&ip6->ip6_src),
473                                     ndi->maxmtu));
474                         }
475                 } else {
476                         nd6log((LOG_INFO, "nd6_ra_input: mtu option "
477                             "mtu=%d sent from %s; maxmtu unknown, "
478                             "ignoring\n",
479                             mtu, ip6_sprintf(&ip6->ip6_src)));
480                 }
481         }
482
483  skip:
484         
485         /*
486          * Source link layer address
487          */
488     {
489         char *lladdr = NULL;
490         int lladdrlen = 0;
491         
492         if (ndopts.nd_opts_src_lladdr) {
493                 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
494                 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
495         }
496
497         if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
498                 nd6log((LOG_INFO,
499                     "nd6_ra_input: lladdrlen mismatch for %s "
500                     "(if %d, RA packet %d)\n",
501                         ip6_sprintf(&saddr6), ifp->if_addrlen, lladdrlen - 2));
502                 goto bad;
503         }
504
505         nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
506
507         /*
508          * Installing a link-layer address might change the state of the
509          * router's neighbor cache, which might also affect our on-link
510          * detection of adveritsed prefixes.
511          */
512         pfxlist_onlink_check();
513     }
514
515  freeit:
516         m_freem(m);
517         return;
518
519  bad:
520         icmp6stat.icp6s_badra++;
521         m_freem(m);
522 }
523
524 /*
525  * default router list proccessing sub routines
526  */
527
528 /* tell the change to user processes watching the routing socket. */
529 static void
530 nd6_rtmsg(cmd, rt)
531         int cmd;
532         struct rtentry *rt;
533 {
534         struct rt_addrinfo info;
535
536         bzero((caddr_t)&info, sizeof(info));
537 #if (defined(__bsdi__) && _BSDI_VERSION >= 199802) /* BSDI4 */
538         /* maybe this is unnecessary */
539         info.rti_flags = rt->rt_flags;
540 #endif
541         info.rti_info[RTAX_DST] = rt_key(rt);
542         info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
543         info.rti_info[RTAX_NETMASK] = rt_mask(rt);
544 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
545         info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addrlist->ifa_addr;
546 #else
547         info.rti_info[RTAX_IFP] =
548                 (struct sockaddr *)TAILQ_FIRST(&rt->rt_ifp->if_addrlist);
549 #endif
550         info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
551
552         rt_missmsg(cmd, &info, rt->rt_flags, 0);
553 }
554
555 void
556 defrouter_addreq(new)
557         struct nd_defrouter *new;
558 {
559         struct sockaddr_in6 def, mask, gate;
560         struct rtentry *newrt = NULL;
561         int s;
562         int error;
563
564         Bzero(&def, sizeof(def));
565         Bzero(&mask, sizeof(mask));
566         Bzero(&gate, sizeof(gate));
567
568         def.sin6_len = mask.sin6_len = gate.sin6_len
569                 = sizeof(struct sockaddr_in6);
570         def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
571         gate.sin6_addr = new->rtaddr;
572
573 #ifdef __NetBSD__
574         s = splsoftnet();
575 #else
576         s = splnet();
577 #endif
578         error = rtrequest(RTM_ADD, (struct sockaddr *)&def,
579                 (struct sockaddr *)&gate, (struct sockaddr *)&mask,
580                 RTF_GATEWAY, &newrt);
581         if (newrt) {
582                 nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
583                 newrt->rt_refcnt--;
584         }
585         if (error == 0)
586                 new->installed = 1;
587         splx(s);
588         return;
589 }
590
591 /* Add a route to a given interface as default */
592 static void
593 defrouter_addifreq(ifp)
594         struct ifnet *ifp;
595 {
596         struct sockaddr_in6 def, mask;
597         struct ifaddr *ifa;
598         struct rtentry *newrt = NULL;
599         int error, flags;
600 #if (defined(__bsdi__) && _BSDI_VERSION >= 199802)
601         struct rt_addrinfo info;
602 #endif
603
604         /* remove one if we have already installed one */
605         if (nd6_defif_installed)
606                 defrouter_delifreq();
607
608         bzero(&def, sizeof(def));
609         bzero(&mask, sizeof(mask));
610
611         def.sin6_len = mask.sin6_len = sizeof(struct sockaddr_in6);
612         def.sin6_family = mask.sin6_family = AF_INET6;
613
614         /*
615          * Search for an ifaddr beloging to the specified interface.
616          * XXX: An IPv6 address are required to be assigned on the interface.
617          */
618         if ((ifa = ifaof_ifpforaddr((struct sockaddr *)&def, ifp)) == NULL) {
619                 nd6log((LOG_ERR,        /* better error? */
620                     "defrouter_addifreq: failed to find an ifaddr "
621                     "to install a route to interface %s\n",
622                     if_name(ifp)));
623                 return;
624         }
625
626         flags = ifa->ifa_flags;
627 #if (defined(__bsdi__) && _BSDI_VERSION >= 199802)
628         bzero(&info, sizeof(info));
629         info.rti_info[RTAX_DST] = (struct sockaddr *)&def;
630         info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)ifa->ifa_addr;
631         info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask;
632         info.rti_info[RTAX_IFA] = (struct sockaddr *)ifa->ifa_addr;
633         info.rti_flags = flags;
634         error = rtrequest1(RTM_ADD, &info, &newrt);
635 #else
636         error = rtrequest(RTM_ADD, (struct sockaddr *)&def, ifa->ifa_addr,
637                           (struct sockaddr *)&mask, flags, &newrt);
638 #endif
639         if (error != 0) {
640                 nd6log((LOG_ERR,
641                     "defrouter_addifreq: failed to install a route to "
642                     "interface %s (errno = %d)\n",
643                     if_name(ifp), error));
644
645                 if (newrt)      /* maybe unnecessary, but do it for safety */
646                         newrt->rt_refcnt--;
647         } else {
648                 if (newrt) {
649                         nd6_rtmsg(RTM_ADD, newrt);
650                         newrt->rt_refcnt--;
651                 }
652         }
653
654         nd6_defif_installed = ifa;
655         IFAREF(ifa);
656 }
657
658 /* Remove a default route points to interface */
659 static void
660 defrouter_delifreq()
661 {
662         struct sockaddr_in6 def, mask;
663         struct rtentry *oldrt = NULL;
664
665         if (!nd6_defif_installed)
666                 return;
667
668         Bzero(&def, sizeof(def));
669         Bzero(&mask, sizeof(mask));
670
671         def.sin6_len = mask.sin6_len = sizeof(struct sockaddr_in6);
672         def.sin6_family = mask.sin6_family = AF_INET6;
673
674         rtrequest(RTM_DELETE, (struct sockaddr *)&def,
675             (struct sockaddr *)nd6_defif_installed->ifa_addr,
676             (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt);
677         if (oldrt) {
678                 nd6_rtmsg(RTM_DELETE, oldrt);
679                 if (oldrt->rt_refcnt <= 0) {
680                         /*
681                          * XXX: borrowed from the RTM_DELETE case of
682                          * rtrequest().
683                          */
684                         oldrt->rt_refcnt++;
685                         rtfree(oldrt);
686                 }
687         }
688
689         IFAFREE(nd6_defif_installed);
690         nd6_defif_installed = NULL;
691 }
692
693 struct nd_defrouter *
694 defrouter_lookup(addr, ifp)
695         struct in6_addr *addr;
696         struct ifnet *ifp;
697 {
698         struct nd_defrouter *dr;
699
700         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
701              dr = TAILQ_NEXT(dr, dr_entry)) {
702                 if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
703                         return(dr);
704         }
705
706         return(NULL);           /* search failed */
707 }
708
709 void
710 defrtrlist_del(dr)
711         struct nd_defrouter *dr;
712 {
713         struct nd_defrouter *deldr = NULL;
714         struct nd_prefix *pr;
715
716         /*
717          * Flush all the routing table entries that use the router
718          * as a next hop.
719          */
720         if (!ip6_forwarding && ip6_accept_rtadv) {
721                 /* above is a good condition? */
722                 rt6_flush(&dr->rtaddr, dr->ifp);
723         }
724
725         if (dr->installed) {
726                 deldr = dr;
727                 defrouter_delreq(dr);
728         }
729         TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
730
731         /*
732          * Also delete all the pointers to the router in each prefix lists.
733          */
734         for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
735                 struct nd_pfxrouter *pfxrtr;
736                 if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
737                         pfxrtr_del(pfxrtr);
738         }
739         pfxlist_onlink_check();
740
741         /*
742          * If the router is the primary one, choose a new one.
743          * Note that defrouter_select() will remove the current gateway
744          * from the routing table.
745          */
746         if (deldr)
747                 defrouter_select();
748
749         free(dr, M_IP6NDP);
750 }
751
752 /*
753  * Remove the default route for a given router.
754  * This is just a subroutine function for defrouter_select(), and should
755  * not be called from anywhere else.
756  */
757 static void
758 defrouter_delreq(dr)
759         struct nd_defrouter *dr;
760 {
761         struct sockaddr_in6 def, mask, gw;
762         struct rtentry *oldrt = NULL;
763
764         Bzero(&def, sizeof(def));
765         Bzero(&mask, sizeof(mask));
766         Bzero(&gw, sizeof(gw));
767
768         def.sin6_len = mask.sin6_len = gw.sin6_len =
769             sizeof(struct sockaddr_in6);
770         def.sin6_family = mask.sin6_family = gw.sin6_family = AF_INET6;
771         if (dr)
772                 gw.sin6_addr = dr->rtaddr;
773
774         rtrequest(RTM_DELETE, (struct sockaddr *)&def,
775             dr ? (struct sockaddr *)&gw : NULL,
776             (struct sockaddr *)&mask, RTF_GATEWAY, &oldrt);
777         if (oldrt) {
778                 nd6_rtmsg(RTM_DELETE, oldrt);
779                 if (oldrt->rt_refcnt <= 0) {
780                         /*
781                          * XXX: borrowed from the RTM_DELETE case of
782                          * rtrequest().
783                          */
784                         oldrt->rt_refcnt++;
785                         rtfree(oldrt);
786                 }
787         }
788
789         if (dr)
790                 dr->installed = 0;
791 }
792
793 /*
794  * remove all default routes from default router list
795  */
796 void
797 defrouter_reset()
798 {
799         struct nd_defrouter *dr;
800
801         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
802              dr = TAILQ_NEXT(dr, dr_entry))
803                 defrouter_delreq(dr);
804         defrouter_delifreq();
805
806         /*
807          * XXX should we also nuke any default routers in the kernel, by 
808          * going through them by rtalloc1()?
809          */
810 }
811
812 /*
813  * Default Router Selection according to Section 6.3.6 of RFC 2461 and
814  * draft-ietf-ipngwg-router-selection:
815  * 1) Routers that are reachable or probably reachable should be preferred.
816  *    If we have more than one (probably) reachable router, prefer ones
817  *    with the highest router preference.
818  * 2) When no routers on the list are known to be reachable or
819  *    probably reachable, routers SHOULD be selected in a round-robin
820  *    fashion, regardless of router preference values.
821  * 3) If the Default Router List is empty, assume that all
822  *    destinations are on-link.
823  *
824  * We assume nd_defrouter is sorted by router preference value.
825  * Since the code below covers both with and without router preference cases,
826  * we do not need to classify the cases by ifdef.
827  *
828  * At this moment, we do not try to install more than one default router,
829  * even when the multipath routing is available, because we're not sure about
830  * the benefits for stub hosts comparing to the risk of making the code
831  * complicated and the possibility of introducing bugs.
832  */
833 void
834 defrouter_select()
835 {
836 #ifdef __NetBSD__
837         int s = splsoftnet();
838 #else
839         int s = splnet();
840 #endif
841         struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
842         struct rtentry *rt = NULL;
843         struct llinfo_nd6 *ln = NULL;
844
845         /*
846          * This function should be called only when acting as an autoconfigured
847          * host.  Although the remaining part of this function is not effective
848          * if the node is not an autoconfigured host, we explicitly exclude
849          * such cases here for safety.
850          */
851         if (ip6_forwarding || !ip6_accept_rtadv) {
852                 nd6log((LOG_WARNING,
853                     "defrouter_select: called unexpectedly (forwarding=%d, "
854                     "accept_rtadv=%d)\n", ip6_forwarding, ip6_accept_rtadv));
855                 splx(s);
856                 return;
857         }
858
859         /*
860          * Let's handle easy case (3) first:
861          * If default router list is empty, we should probably install
862          * an interface route and assume that all destinations are on-link.
863          */
864         if (!TAILQ_FIRST(&nd_defrouter)) {
865                 /*
866                  * XXX: The specification does not say this mechanism should
867                  * be restricted to hosts, but this would be not useful
868                  * (even harmful) for routers.
869                  * This test is meaningless due to a test at the beginning of
870                  * the function, but we intentionally keep it to make the note
871                  * clear.
872                  */
873                 if (!ip6_forwarding) {
874                         if (nd6_defifp) {
875                                 /*
876                                  * Install a route to the default interface
877                                  * as default route.
878                                  */
879                                 defrouter_addifreq(nd6_defifp);
880                         } else {
881                                 /*
882                                  * purge the existing route.
883                                  * XXX: is this really correct?
884                                  */
885                                 defrouter_delifreq();
886                                 nd6log((LOG_INFO, "defrouter_select: "
887                                     "there's no default router and no default"
888                                     " interface\n"));
889                         }
890                 }
891                 splx(s);
892                 return;
893         }
894
895         /*
896          * If we have a default route for the default interface, delete it.
897          * Note that the existence of the route is checked in the delete
898          * function.
899          */
900         defrouter_delifreq();
901
902         /*
903          * Search for a (probably) reachable router from the list.
904          * We just pick up the first reachable one (if any), assuming that
905          * the ordering rule of the list described in defrtrlist_update().
906          */
907         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
908              dr = TAILQ_NEXT(dr, dr_entry)) {
909                 if (!selected_dr &&
910                     (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
911                     (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
912                     ND6_IS_LLINFO_PROBREACH(ln)) {
913                         selected_dr = dr;
914                 }
915
916                 if (dr->installed && !installed_dr)
917                         installed_dr = dr;
918                 else if (dr->installed && installed_dr) {
919                         /* this should not happen.  warn for diagnosis. */
920                         log(LOG_ERR, "defrouter_select: more than one router"
921                             " is installed\n");
922                 }
923         }
924         /*
925          * If none of the default routers was found to be reachable,
926          * round-robin the list regardless of preference.
927          * Otherwise, if we have an installed router, check if the selected
928          * (reachable) router should really be preferred to the installed one.
929          * We only prefer the new router when the old one is not reachable
930          * or when the new one has a really higher preference value.
931          */
932         if (!selected_dr) {
933                 if (!installed_dr || !TAILQ_NEXT(installed_dr, dr_entry))
934                         selected_dr = TAILQ_FIRST(&nd_defrouter);
935                 else
936                         selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
937         } else if (installed_dr &&
938                    (rt = nd6_lookup(&installed_dr->rtaddr, 0,
939                                     installed_dr->ifp)) &&
940                    (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
941                    ND6_IS_LLINFO_PROBREACH(ln) &&
942                    rtpref(selected_dr) <= rtpref(installed_dr)) {
943                         selected_dr = installed_dr;
944         }
945
946         /*
947          * If the selected router is different than the installed one,
948          * remove the installed router and install the selected one.
949          * Note that the selected router is never NULL here.
950          */
951         if (installed_dr != selected_dr) {
952                 if (installed_dr)
953                         defrouter_delreq(installed_dr);
954                 defrouter_addreq(selected_dr);
955         }
956
957         splx(s);
958         return;
959 }
960
961 /* 
962  * for default router selection
963  * regards router-preference field as a 2-bit signed integer 
964  */
965 static int
966 rtpref(struct nd_defrouter *dr)
967 {
968 #ifdef RTPREF
969         switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
970         case ND_RA_FLAG_RTPREF_HIGH:
971                 return RTPREF_HIGH;
972         case ND_RA_FLAG_RTPREF_MEDIUM:
973         case ND_RA_FLAG_RTPREF_RSV:
974                 return RTPREF_MEDIUM;
975         case ND_RA_FLAG_RTPREF_LOW:
976                 return RTPREF_LOW;
977         default:
978                 /*
979                  * This case should never happen.  If it did, it would mean a
980                  * serious bug of kernel internal.  We thus always bark here.
981                  * Or, can we even panic?
982                  */
983                 log(LOG_ERR, "rtpref: impossible RA flag %x", dr->flags);
984                 return RTPREF_INVALID;
985         }
986         /* NOT REACH HERE */
987 #else
988         return RTPREF_MEDIUM;
989 #endif
990 }
991
992 static struct nd_defrouter *
993 defrtrlist_update(new)
994         struct nd_defrouter *new;
995 {
996         struct nd_defrouter *dr, *n;
997 #ifdef __NetBSD__
998         int s = splsoftnet();
999 #else
1000         int s = splnet();
1001 #endif
1002
1003         if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
1004                 /* entry exists */
1005                 if (new->rtlifetime == 0) {
1006                         defrtrlist_del(dr);
1007                         dr = NULL;
1008                 } else {
1009                         int oldpref = rtpref(dr);
1010
1011                         /* override */
1012                         dr->flags = new->flags; /* xxx flag check */
1013                         dr->rtlifetime = new->rtlifetime;
1014                         dr->expire = new->expire;
1015
1016                         /* 
1017                          * If the preference does not change, there's no need
1018                          * to sort the entries.
1019                          */
1020                         if (rtpref(new) == oldpref) {
1021                                 splx(s);
1022                                 return(dr);
1023                         }
1024
1025                         /*
1026                          * preferred router may be changed, so relocate
1027                          * this router.
1028                          * XXX: calling TAILQ_REMOVE directly is a bad manner.
1029                          * However, since defrtrlist_del() has many side
1030                          * effects, we intentionally do so here.
1031                          * defrouter_select() below will handle routing
1032                          * changes later.
1033                          */
1034                         TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
1035                         n = dr;
1036                         goto insert;
1037                 }
1038                 splx(s);
1039                 return(dr);
1040         }
1041
1042         /* entry does not exist */
1043         if (new->rtlifetime == 0) {
1044                 splx(s);
1045                 return(NULL);
1046         }
1047
1048         n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
1049         if (n == NULL) {
1050                 splx(s);
1051                 return(NULL);
1052         }
1053         bzero(n, sizeof(*n));
1054         *n = *new;
1055
1056 insert:
1057         /*
1058          * Insert the new router in the Default Router List;
1059          * The Default Router List should be in the descending order
1060          * of router-preferece.  Routers with the same preference are
1061          * sorted in the arriving time order.
1062          */
1063
1064         /* insert at the end of the group */
1065         for (dr = TAILQ_FIRST(&nd_defrouter); dr;
1066              dr = TAILQ_NEXT(dr, dr_entry)) {
1067                 if (rtpref(n) > rtpref(dr))
1068                         break;
1069         }
1070         if (dr)
1071                 TAILQ_INSERT_BEFORE(dr, n, dr_entry);
1072         else
1073                 TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry);
1074
1075         defrouter_select();
1076
1077         splx(s);
1078                 
1079         return(n);
1080 }
1081
1082 static struct nd_pfxrouter *
1083 pfxrtr_lookup(pr, dr)
1084         struct nd_prefix *pr;
1085         struct nd_defrouter *dr;
1086 {
1087         struct nd_pfxrouter *search;
1088         
1089         for (search = pr->ndpr_advrtrs.lh_first; search; search = search->pfr_next) {
1090                 if (search->router == dr)
1091                         break;
1092         }
1093
1094         return(search);
1095 }
1096
1097 static void
1098 pfxrtr_add(pr, dr)
1099         struct nd_prefix *pr;
1100         struct nd_defrouter *dr;
1101 {
1102         struct nd_pfxrouter *new;
1103
1104         new = (struct nd_pfxrouter *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
1105         if (new == NULL)
1106                 return;
1107         bzero(new, sizeof(*new));
1108         new->router = dr;
1109
1110         LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
1111
1112         pfxlist_onlink_check();
1113 }
1114
1115 static void
1116 pfxrtr_del(pfr)
1117         struct nd_pfxrouter *pfr;
1118 {
1119         LIST_REMOVE(pfr, pfr_entry);
1120         free(pfr, M_IP6NDP);
1121 }
1122
1123 struct nd_prefix *
1124 nd6_prefix_lookup(pr)
1125         struct nd_prefix *pr;
1126 {
1127         struct nd_prefix *search;
1128
1129         for (search = nd_prefix.lh_first; search; search = search->ndpr_next) {
1130                 if (pr->ndpr_ifp == search->ndpr_ifp &&
1131                     pr->ndpr_plen == search->ndpr_plen &&
1132                     in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
1133                                          &search->ndpr_prefix.sin6_addr,
1134                                          pr->ndpr_plen)
1135                     ) {
1136                         break;
1137                 }
1138         }
1139
1140         return(search);
1141 }
1142
1143 int
1144 nd6_prelist_add(pr, dr, newp)
1145         struct nd_prefix *pr, **newp;
1146         struct nd_defrouter *dr;
1147 {
1148         struct nd_prefix *new = NULL;
1149         int i, s;
1150
1151         new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
1152         if (new == NULL)
1153                 return ENOMEM;
1154         bzero(new, sizeof(*new));
1155         *new = *pr;
1156         if (newp != NULL)
1157                 *newp = new;
1158
1159         /* initilization */
1160         LIST_INIT(&new->ndpr_advrtrs);
1161         in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
1162         /* make prefix in the canonical form */
1163         for (i = 0; i < 4; i++)
1164                 new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
1165                         new->ndpr_mask.s6_addr32[i];
1166
1167 #ifdef __NetBSD__
1168         s = splsoftnet();
1169 #else
1170         s = splnet();
1171 #endif
1172         /* link ndpr_entry to nd_prefix list */
1173         LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
1174         splx(s);
1175
1176         /* ND_OPT_PI_FLAG_ONLINK processing */
1177         if (new->ndpr_raf_onlink) {
1178                 int e;
1179
1180                 if ((e = nd6_prefix_onlink(new)) != 0) {
1181                         nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
1182                             "the prefix %s/%d on-link on %s (errno=%d)\n",
1183                             ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1184                             pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
1185                         /* proceed anyway. XXX: is it correct? */
1186                 }
1187         }
1188
1189         if (dr)
1190                 pfxrtr_add(new, dr);
1191
1192         return 0;
1193 }
1194
1195 void
1196 prelist_remove(pr)
1197         struct nd_prefix *pr;
1198 {
1199         struct nd_pfxrouter *pfr, *next;
1200         int e, s;
1201
1202         /* make sure to invalidate the prefix until it is really freed. */
1203         pr->ndpr_vltime = 0;
1204         pr->ndpr_pltime = 0;
1205 #if 0
1206         /*
1207          * Though these flags are now meaningless, we'd rather keep the value
1208          * not to confuse users when executing "ndp -p".
1209          */
1210         pr->ndpr_raf_onlink = 0;
1211         pr->ndpr_raf_auto = 0;
1212 #endif
1213         if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
1214             (e = nd6_prefix_offlink(pr)) != 0) {
1215                 nd6log((LOG_ERR, "prelist_remove: failed to make %s/%d offlink "
1216                     "on %s, errno=%d\n",
1217                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1218                     pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
1219                 /* what should we do? */
1220         }
1221
1222         if (pr->ndpr_refcnt > 0)
1223                 return;         /* notice here? */
1224
1225 #ifdef __NetBSD__
1226         s = splsoftnet();
1227 #else
1228         s = splnet();
1229 #endif
1230
1231         /* unlink ndpr_entry from nd_prefix list */
1232         LIST_REMOVE(pr, ndpr_entry);
1233
1234         /* free list of routers that adversed the prefix */
1235         for (pfr = pr->ndpr_advrtrs.lh_first; pfr; pfr = next) {
1236                 next = pfr->pfr_next;
1237
1238                 free(pfr, M_IP6NDP);
1239         }
1240         splx(s);
1241
1242         free(pr, M_IP6NDP);
1243
1244         pfxlist_onlink_check();
1245 }
1246
1247 int
1248 prelist_update(new, dr, m)
1249         struct nd_prefix *new;
1250         struct nd_defrouter *dr; /* may be NULL */
1251         struct mbuf *m;
1252 {
1253         struct in6_ifaddr *ia6 = NULL, *ia6_match = NULL;
1254         struct ifaddr *ifa;
1255         struct ifnet *ifp = new->ndpr_ifp;
1256         struct nd_prefix *pr;
1257 #ifdef __NetBSD__
1258         int s = splsoftnet();
1259 #else
1260         int s = splnet();
1261 #endif
1262         int error = 0;
1263         int newprefix = 0;
1264         int auth;
1265         struct in6_addrlifetime lt6_tmp;
1266
1267         auth = 0;
1268         if (m) {
1269                 /*
1270                  * Authenticity for NA consists authentication for
1271                  * both IP header and IP datagrams, doesn't it ?
1272                  */
1273 #if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)
1274                 auth = (m->m_flags & M_AUTHIPHDR
1275                      && m->m_flags & M_AUTHIPDGM) ? 1 : 0;
1276 #endif
1277         }
1278
1279         if ((pr = nd6_prefix_lookup(new)) != NULL) {
1280                 /*
1281                  * nd6_prefix_lookup() ensures that pr and new have the same
1282                  * prefix on a same interface.
1283                  */
1284
1285                 /*
1286                  * Update prefix information.  Note that the on-link (L) bit
1287                  * and the autonomous (A) bit should NOT be changed from 1
1288                  * to 0.
1289                  */
1290                 if (new->ndpr_raf_onlink == 1)
1291                         pr->ndpr_raf_onlink = 1;
1292                 if (new->ndpr_raf_auto == 1)
1293                         pr->ndpr_raf_auto = 1;
1294                 if (new->ndpr_raf_onlink) {
1295                         pr->ndpr_vltime = new->ndpr_vltime;
1296                         pr->ndpr_pltime = new->ndpr_pltime;
1297                         pr->ndpr_preferred = new->ndpr_preferred;
1298                         pr->ndpr_expire = new->ndpr_expire;
1299                         pr->ndpr_lastupdate = new->ndpr_lastupdate;
1300                 }
1301
1302                 if (new->ndpr_raf_onlink &&
1303                     (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1304                         int e;
1305
1306                         if ((e = nd6_prefix_onlink(pr)) != 0) {
1307                                 nd6log((LOG_ERR,
1308                                     "prelist_update: failed to make "
1309                                     "the prefix %s/%d on-link on %s "
1310                                     "(errno=%d)\n",
1311                                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1312                                     pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
1313                                 /* proceed anyway. XXX: is it correct? */
1314                         }
1315                 }
1316
1317                 if (dr && pfxrtr_lookup(pr, dr) == NULL)
1318                         pfxrtr_add(pr, dr);
1319         } else {
1320                 struct nd_prefix *newpr = NULL;
1321
1322                 newprefix = 1;
1323
1324                 if (new->ndpr_vltime == 0)
1325                         goto end;
1326                 if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
1327                         goto end;
1328
1329                 error = nd6_prelist_add(new, dr, &newpr);
1330                 if (error != 0 || newpr == NULL) {
1331                         nd6log((LOG_NOTICE, "prelist_update: "
1332                             "nd6_prelist_add failed for %s/%d on %s "
1333                             "errno=%d, returnpr=%p\n",
1334                             ip6_sprintf(&new->ndpr_prefix.sin6_addr),
1335                                         new->ndpr_plen, if_name(new->ndpr_ifp),
1336                                         error, newpr));
1337                         goto end; /* we should just give up in this case. */
1338                 }
1339
1340                 /*
1341                  * XXX: from the ND point of view, we can ignore a prefix
1342                  * with the on-link bit being zero.  However, we need a
1343                  * prefix structure for references from autoconfigured
1344                  * addresses.  Thus, we explicitly make sure that the prefix
1345                  * itself expires now.
1346                  */
1347                 if (newpr->ndpr_raf_onlink == 0) {
1348                         newpr->ndpr_vltime = 0;
1349                         newpr->ndpr_pltime = 0;
1350                         in6_init_prefix_ltimes(newpr);
1351                 }
1352
1353                 pr = newpr;
1354         }
1355
1356         /*
1357          * Address autoconfiguration based on Section 5.5.3 of RFC 2462.
1358          * Note that pr must be non NULL at this point.
1359          */
1360
1361         /* 5.5.3 (a). Ignore the prefix without the A bit set. */
1362         if (!new->ndpr_raf_auto)
1363                 goto end;
1364
1365         /*
1366          * 5.5.3 (b). the link-local prefix should have been ignored in
1367          * nd6_ra_input.
1368          */
1369
1370         /*
1371          * 5.5.3 (c). Consistency check on lifetimes: pltime <= vltime.
1372          * This should have been done in nd6_ra_input.
1373          */
1374
1375         /*
1376          * 5.5.3 (d). If the prefix advertised does not match the prefix of an
1377          * address already in the list, and the Valid Lifetime is not 0,
1378          * form an address.  Note that even a manually configured address
1379          * should reject autoconfiguration of a new address.
1380          */
1381 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1382         for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1383 #elif defined(__FreeBSD__) && __FreeBSD__ >= 4
1384         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1385 #else
1386         for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
1387 #endif
1388         {
1389                 struct in6_ifaddr *ifa6;
1390                 int ifa_plen;
1391                 u_int32_t storedlifetime;
1392 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
1393                 long time_second = time.tv_sec;
1394 #endif
1395
1396                 if (ifa->ifa_addr->sa_family != AF_INET6)
1397                         continue;
1398
1399                 ifa6 = (struct in6_ifaddr *)ifa;
1400
1401                 /*
1402                  * Spec is not clear here, but I believe we should concentrate
1403                  * on unicast (i.e. not anycast) addresses.
1404                  * XXX: other ia6_flags? detached or duplicated?
1405                  */
1406                 if ((ifa6->ia6_flags & IN6_IFF_ANYCAST) != 0)
1407                         continue;
1408                 
1409                 ifa_plen = in6_mask2len(&ifa6->ia_prefixmask.sin6_addr, NULL);
1410                 if (ifa_plen != new->ndpr_plen ||
1411                     !in6_are_prefix_equal(&ifa6->ia_addr.sin6_addr,
1412                                           &new->ndpr_prefix.sin6_addr,
1413                                           ifa_plen))
1414                         continue;
1415
1416                 if (ia6_match == NULL) /* remember the first one */
1417                         ia6_match = ifa6;
1418
1419                 if ((ifa6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1420                         continue;
1421
1422                 /*
1423                  * An already autoconfigured address matched.  Now that we
1424                  * are sure there is at least one matched address, we can
1425                  * proceed to 5.5.3. (e): update the lifetimes according to the
1426                  * "two hours" rule and the privacy extension.
1427                  */
1428 #define TWOHOUR         (120*60)
1429                 /*
1430                  * RFC2462 introduces the notion of StoredLifetime to the
1431                  * "two hours" rule as follows:
1432                  *   the Lifetime associated with the previously autoconfigured
1433                  *   address.
1434                  * Our interpretation of this definition is "the remaining
1435                  * lifetime to expiration at the evaluation time".  One might
1436                  * be wondering if this interpretation is really conform to the
1437                  * RFC, because the text can read that "Lifetimes" are never
1438                  * decreased, and our definition of the "storedlifetime" below
1439                  * essentially reduces the "Valid Lifetime" advertised in the
1440                  * previous RA.  But, this is due to the wording of the text,
1441                  * and our interpretation is the same as an author's intention.
1442                  * See the discussion in the IETF ipngwg ML in August 2001,
1443                  * with the Subject "StoredLifetime in RFC 2462".
1444                  */
1445                 lt6_tmp = ifa6->ia6_lifetime;
1446                 if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
1447                         storedlifetime = ND6_INFINITE_LIFETIME;
1448                 else if (time_second - ifa6->ia6_updatetime >
1449                          lt6_tmp.ia6t_vltime) {
1450                         /*
1451                          * The case of "invalid" address.  We should usually
1452                          * not see this case.
1453                          */
1454                         storedlifetime = 0;
1455                 } else
1456                         storedlifetime = lt6_tmp.ia6t_vltime -
1457                                 (time_second - ifa6->ia6_updatetime);
1458                 if (TWOHOUR < new->ndpr_vltime ||
1459                     storedlifetime < new->ndpr_vltime) {
1460                         lt6_tmp.ia6t_vltime = new->ndpr_vltime;
1461                 } else if (storedlifetime <= TWOHOUR
1462 #if 0
1463                            /*
1464                             * This condition is logically redundant, so we just
1465                             * omit it.
1466                             * See IPng 6712, 6717, and 6721.
1467                             */
1468                            && new->ndpr_vltime <= storedlifetime
1469 #endif
1470                         ) {
1471                         if (auth) {
1472                                 lt6_tmp.ia6t_vltime = new->ndpr_vltime;
1473                         }
1474                 } else {
1475                         /*
1476                          * new->ndpr_vltime <= TWOHOUR &&
1477                          * TWOHOUR < storedlifetime
1478                          */
1479                         lt6_tmp.ia6t_vltime = TWOHOUR;
1480                 }
1481
1482                 /* The 2 hour rule is not imposed for preferred lifetime. */
1483                 lt6_tmp.ia6t_pltime = new->ndpr_pltime;
1484
1485                 in6_init_address_ltimes(pr, &lt6_tmp);
1486
1487                 /*
1488                  * We need to treat lifetimes for temporary addresses
1489                  * differently, according to
1490                  * draft-ietf-ipngwg-temp-addresses-v2-00.txt 3.3 (1);
1491                  * we only update the lifetimes when they are in the maximum
1492                  * intervals.
1493                  */
1494                 if ((ifa6->ia6_flags & IN6_IFF_TEMPORARY) != 0) {
1495                         u_int32_t maxvltime, maxpltime;
1496
1497                         if (ip6_temp_valid_lifetime >
1498                             (u_int32_t)(time_second - ifa6->ia6_createtime)) {
1499                                 maxvltime = ip6_temp_valid_lifetime -
1500                                         (time_second - ifa6->ia6_createtime);
1501                         } else
1502                                 maxvltime = 0;
1503                         if (ip6_temp_preferred_lifetime >
1504                             (u_int32_t)((time_second - ifa6->ia6_createtime) +
1505                                         ip6_desync_factor)) {
1506                                 maxpltime = ip6_temp_preferred_lifetime -
1507                                         (time_second - ifa6->ia6_createtime) -
1508                                         ip6_desync_factor;
1509                         } else
1510                                 maxpltime = 0;
1511
1512                         if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME ||
1513                             lt6_tmp.ia6t_vltime > maxvltime) {
1514                                 lt6_tmp.ia6t_vltime = maxvltime;
1515                         }
1516                         if (lt6_tmp.ia6t_pltime == ND6_INFINITE_LIFETIME ||
1517                             lt6_tmp.ia6t_pltime > maxpltime) {
1518                                 lt6_tmp.ia6t_pltime = maxpltime;
1519                         }
1520                 }
1521
1522                 ifa6->ia6_lifetime = lt6_tmp;
1523                 ifa6->ia6_updatetime = time_second;
1524         }
1525         if (ia6_match == NULL && new->ndpr_vltime) {
1526                 /*
1527                  * No address matched and the valid lifetime is non-zero.
1528                  * Create a new address.
1529                  */
1530                 if ((ia6 = in6_ifadd(new)) != NULL) {
1531                         /*
1532                          * note that we should use pr (not new) for reference.
1533                          */
1534                         pr->ndpr_refcnt++;
1535                         ia6->ia6_ndpr = pr;
1536
1537                         /*
1538                          * draft-ietf-ipngwg-temp-addresses-v2-00 3.3 (2).
1539                          * When a new public address is created as described
1540                          * in RFC2462, also create a new temporary address.
1541                          *
1542                          * draft-ietf-ipngwg-temp-addresses-v2-00 3.5.
1543                          * When an interface connects to a new link, a new
1544                          * randomized interface identifier should be generated
1545                          * immediately together with a new set of temporary
1546                          * addresses.  Thus, we specifiy 1 as the 2nd arg of
1547                          * in6_tmpifadd().
1548                          */
1549                         if (ip6_use_tempaddr) {
1550                                 int e;
1551                                 if ((e = in6_tmpifadd(ia6, 1)) != 0) {
1552                                         nd6log((LOG_NOTICE, "prelist_update: "
1553                                             "failed to create a temporary "
1554                                             "address, errno=%d\n",
1555                                             e));
1556                                 }
1557                         }
1558
1559                         /*
1560                          * A newly added address might affect the status
1561                          * of other addresses, so we check and update it.
1562                          * XXX: what if address duplication happens?
1563                          */
1564                         pfxlist_onlink_check();
1565                 } else {
1566                         /* just set an error. do not bark here. */
1567                         error = EADDRNOTAVAIL; /* XXX: might be unused. */
1568                 }
1569         }
1570
1571  end:
1572         splx(s);
1573         return error;
1574 }
1575
1576 /*
1577  * A supplement function used in the on-link detection below;
1578  * detect if a given prefix has a (probably) reachable advertising router.
1579  * XXX: lengthy function name...
1580  */
1581 static struct nd_pfxrouter *
1582 find_pfxlist_reachable_router(pr)
1583         struct nd_prefix *pr;
1584 {
1585         struct nd_pfxrouter *pfxrtr;
1586         struct rtentry *rt;
1587         struct llinfo_nd6 *ln;
1588
1589         for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
1590              pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
1591                 if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
1592                                      pfxrtr->router->ifp)) &&
1593                     (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
1594                     ND6_IS_LLINFO_PROBREACH(ln))
1595                         break;  /* found */
1596         }
1597
1598         return(pfxrtr);
1599
1600 }
1601
1602 /*
1603  * Check if each prefix in the prefix list has at least one available router
1604  * that advertised the prefix (a router is "available" if its neighbor cache
1605  * entry is reachable or probably reachable).
1606  * If the check fails, the prefix may be off-link, because, for example,
1607  * we have moved from the network but the lifetime of the prefix has not
1608  * expired yet.  So we should not use the prefix if there is another prefix
1609  * that has an available router.
1610  * But, if there is no prefix that has an available router, we still regards
1611  * all the prefixes as on-link.  This is because we can't tell if all the
1612  * routers are simply dead or if we really moved from the network and there
1613  * is no router around us.
1614  */
1615 void
1616 pfxlist_onlink_check()
1617 {
1618         struct nd_prefix *pr;
1619         struct in6_ifaddr *ifa;
1620
1621         /*
1622          * Check if there is a prefix that has a reachable advertising
1623          * router.
1624          */
1625         for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1626                 if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr))
1627                         break;
1628         }
1629
1630         if (pr != NULL || TAILQ_FIRST(&nd_defrouter) != NULL) {
1631                 /*
1632                  * There is at least one prefix that has a reachable router,
1633                  * or at least a router which probably does not advertise
1634                  * any prefixes.  The latter would be the case when we move
1635                  * to a new link where we have a router that does not provide
1636                  * prefixes and we configure an address by hand.
1637                  * Detach prefixes which have no reachable advertising
1638                  * router, and attach other prefixes.
1639                  */
1640                 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1641                         /* XXX: a link-local prefix should never be detached */
1642                         if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1643                                 continue;
1644
1645                         /*
1646                          * we aren't interested in prefixes without the L bit
1647                          * set.
1648                          */
1649                         if (pr->ndpr_raf_onlink == 0)
1650                                 continue;
1651
1652                         if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
1653                             find_pfxlist_reachable_router(pr) == NULL)
1654                                 pr->ndpr_stateflags |= NDPRF_DETACHED;
1655                         if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
1656                             find_pfxlist_reachable_router(pr) != 0)
1657                                 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
1658                 }
1659         } else {
1660                 /* there is no prefix that has a reachable router */
1661                 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1662                         if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1663                                 continue;
1664
1665                         if (pr->ndpr_raf_onlink == 0)
1666                                 continue;
1667
1668                         if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
1669                                 pr->ndpr_stateflags &= ~NDPRF_DETACHED;
1670                 }
1671         }
1672
1673         /*
1674          * Remove each interface route associated with a (just) detached
1675          * prefix, and reinstall the interface route for a (just) attached
1676          * prefix.  Note that all attempt of reinstallation does not
1677          * necessarily success, when a same prefix is shared among multiple
1678          * interfaces.  Such cases will be handled in nd6_prefix_onlink,
1679          * so we don't have to care about them.
1680          */
1681         for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1682                 int e;
1683
1684                 if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1685                         continue;
1686
1687                 if (pr->ndpr_raf_onlink == 0)
1688                         continue;
1689
1690                 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
1691                     (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1692                         if ((e = nd6_prefix_offlink(pr)) != 0) {
1693                                 nd6log((LOG_ERR,
1694                                     "pfxlist_onlink_check: failed to "
1695                                     "make %s/%d offlink, errno=%d\n",
1696                                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1697                                     pr->ndpr_plen, e));
1698                         }
1699                 }
1700                 if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
1701                     (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
1702                     pr->ndpr_raf_onlink) {
1703                         if ((e = nd6_prefix_onlink(pr)) != 0) {
1704                                 nd6log((LOG_ERR,
1705                                     "pfxlist_onlink_check: failed to "
1706                                     "make %s/%d offlink, errno=%d\n",
1707                                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1708                                     pr->ndpr_plen, e));
1709                         }
1710                 }
1711         }
1712
1713         /*
1714          * Changes on the prefix status might affect address status as well.
1715          * Make sure that all addresses derived from an attached prefix are
1716          * attached, and that all addresses derived from a detached prefix are
1717          * detached.  Note, however, that a manually configured address should
1718          * always be attached.
1719          * The precise detection logic is same as the one for prefixes.
1720          */
1721         for (ifa = in6_ifaddr; ifa; ifa = ifa->ia_next) {
1722                 if (!(ifa->ia6_flags & IN6_IFF_AUTOCONF))
1723                         continue;
1724
1725                 if (ifa->ia6_ndpr == NULL) {
1726                         /*
1727                          * This can happen when we first configure the address
1728                          * (i.e. the address exists, but the prefix does not).
1729                          * XXX: complicated relationships...
1730                          */
1731                         continue;
1732                 }
1733
1734                 if (find_pfxlist_reachable_router(ifa->ia6_ndpr))
1735                         break;
1736         }
1737         if (ifa) {
1738                 for (ifa = in6_ifaddr; ifa; ifa = ifa->ia_next) {
1739                         if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1740                                 continue;
1741
1742                         if (ifa->ia6_ndpr == NULL) /* XXX: see above. */
1743                                 continue;
1744
1745                         if (find_pfxlist_reachable_router(ifa->ia6_ndpr))
1746                                 ifa->ia6_flags &= ~IN6_IFF_DETACHED;
1747                         else
1748                                 ifa->ia6_flags |= IN6_IFF_DETACHED;
1749                 }
1750         }
1751         else {
1752                 for (ifa = in6_ifaddr; ifa; ifa = ifa->ia_next) {
1753                         if ((ifa->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1754                                 continue;
1755
1756                         ifa->ia6_flags &= ~IN6_IFF_DETACHED;
1757                 }
1758         }
1759
1760 #ifdef MIP6
1761         if (MIP6_IS_MN) {
1762                 int coa_changed = 0;
1763
1764                 hif_save_location();
1765                 coa_changed = mip6_select_coa2();
1766                 (void)mip6_process_pfxlist_status_change(&hif_coa);
1767                 if (coa_changed == 1)
1768                         mip6_process_movement();
1769                 else
1770                         hif_restore_location();
1771         }
1772 #endif /* MIP6 */
1773 }
1774
1775 int
1776 nd6_prefix_onlink(pr)
1777         struct nd_prefix *pr;
1778 {
1779         struct ifaddr *ifa;
1780         struct ifnet *ifp = pr->ndpr_ifp;
1781         struct sockaddr_in6 mask6;
1782         struct nd_prefix *opr;
1783         u_long rtflags;
1784         int error = 0;
1785         struct rtentry *rt = NULL;
1786
1787         /* sanity check */
1788         if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1789                 nd6log((LOG_ERR,
1790                     "nd6_prefix_onlink: %s/%d is already on-link\n",
1791                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen);
1792                 return(EEXIST));
1793         }
1794
1795         /*
1796          * Add the interface route associated with the prefix.  Before
1797          * installing the route, check if there's the same prefix on another
1798          * interface, and the prefix has already installed the interface route.
1799          * Although such a configuration is expected to be rare, we explicitly
1800          * allow it.
1801          */
1802         for (opr = nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
1803                 if (opr == pr)
1804                         continue;
1805
1806                 if ((opr->ndpr_stateflags & NDPRF_ONLINK) == 0)
1807                         continue;
1808
1809                 if (opr->ndpr_plen == pr->ndpr_plen &&
1810                     in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
1811                                          &opr->ndpr_prefix.sin6_addr,
1812                                          pr->ndpr_plen))
1813                         return(0);
1814         }
1815
1816         /*
1817          * We prefer link-local addresses as the associated interface address. 
1818          */
1819         /* search for a link-local addr */
1820         ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
1821                                                       IN6_IFF_NOTREADY|
1822                                                       IN6_IFF_ANYCAST);
1823         if (ifa == NULL) {
1824                 /* XXX: freebsd does not have ifa_ifwithaf */
1825 #if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
1826                 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
1827 #elif defined(__FreeBSD__) && __FreeBSD__ >= 4
1828                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)
1829 #else
1830                 for (ifa = ifp->if_addrlist.tqh_first;
1831                      ifa;
1832                      ifa = ifa->ifa_list.tqe_next)
1833 #endif
1834                 {
1835                         if (ifa->ifa_addr->sa_family == AF_INET6)
1836                                 break;
1837                 }
1838                 /* should we care about ia6_flags? */
1839         }
1840         if (ifa == NULL) {
1841                 /*
1842                  * This can still happen, when, for example, we receive an RA
1843                  * containing a prefix with the L bit set and the A bit clear,
1844                  * after removing all IPv6 addresses on the receiving
1845                  * interface.  This should, of course, be rare though.
1846                  */
1847                 nd6log((LOG_NOTICE,
1848                     "nd6_prefix_onlink: failed to find any ifaddr"
1849                     " to add route for a prefix(%s/%d) on %s\n",
1850                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1851                     pr->ndpr_plen, if_name(ifp)));
1852                 return(0);
1853         }
1854
1855         /*
1856          * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
1857          * ifa->ifa_rtrequest = nd6_rtrequest;
1858          */
1859         bzero(&mask6, sizeof(mask6));
1860         mask6.sin6_len = sizeof(mask6);
1861         mask6.sin6_addr = pr->ndpr_mask;
1862         /* rtrequest() will probably set RTF_UP, but we're not sure. */
1863         rtflags = ifa->ifa_flags | RTF_UP;
1864         if (nd6_need_cache(ifp)) {
1865                 /* explicitly set in case ifa_flags does not set the flag. */
1866                 rtflags |= RTF_CLONING;
1867         } else {
1868                 /*
1869                  * explicitly clear the cloning bit in case ifa_flags sets it.
1870                  */
1871                 rtflags &= ~RTF_CLONING;
1872         }
1873         error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
1874                           ifa->ifa_addr, (struct sockaddr *)&mask6,
1875                           rtflags, &rt);
1876         if (error == 0) {
1877                 if (rt != NULL) /* this should be non NULL, though */
1878                         nd6_rtmsg(RTM_ADD, rt);
1879                 pr->ndpr_stateflags |= NDPRF_ONLINK;
1880         }
1881         else {
1882                 nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
1883                     " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
1884                     "errno = %d\n",
1885                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1886                     pr->ndpr_plen, if_name(ifp),
1887                     ip6_sprintf(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
1888                     ip6_sprintf(&mask6.sin6_addr), rtflags, error));
1889         }
1890
1891         if (rt != NULL)
1892                 rt->rt_refcnt--;
1893
1894         return(error);
1895 }
1896
1897 int
1898 nd6_prefix_offlink(pr)
1899         struct nd_prefix *pr;
1900 {
1901         int error = 0;
1902         struct ifnet *ifp = pr->ndpr_ifp;
1903         struct nd_prefix *opr;
1904         struct sockaddr_in6 sa6, mask6;
1905         struct rtentry *rt = NULL;
1906
1907         /* sanity check */
1908         if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1909                 nd6log((LOG_ERR,
1910                     "nd6_prefix_offlink: %s/%d is already off-link\n",
1911                     ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen));
1912                 return(EEXIST);
1913         }
1914
1915         bzero(&sa6, sizeof(sa6));
1916         sa6.sin6_family = AF_INET6;
1917         sa6.sin6_len = sizeof(sa6);
1918         bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
1919               sizeof(struct in6_addr));
1920         bzero(&mask6, sizeof(mask6));
1921         mask6.sin6_family = AF_INET6;
1922         mask6.sin6_len = sizeof(sa6);
1923         bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
1924         error = rtrequest(RTM_DELETE, (struct sockaddr *)&sa6, NULL,
1925                           (struct sockaddr *)&mask6, 0, &rt);
1926         if (error == 0) {
1927                 pr->ndpr_stateflags &= ~NDPRF_ONLINK;
1928
1929                 /* report the route deletion to the routing socket. */
1930                 if (rt != NULL)
1931                         nd6_rtmsg(RTM_DELETE, rt);
1932
1933                 /*
1934                  * There might be the same prefix on another interface,
1935                  * the prefix which could not be on-link just because we have
1936                  * the interface route (see comments in nd6_prefix_onlink).
1937                  * If there's one, try to make the prefix on-link on the
1938                  * interface.
1939                  */
1940                 for (opr = nd_prefix.lh_first; opr; opr = opr->ndpr_next) {
1941                         if (opr == pr)
1942                                 continue;
1943
1944                         if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0)
1945                                 continue;
1946
1947                         /*
1948                          * KAME specific: detached prefixes should not be
1949                          * on-link.
1950                          */
1951                         if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0)
1952                                 continue;
1953
1954                         if (opr->ndpr_plen == pr->ndpr_plen &&
1955                             in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
1956                                                  &opr->ndpr_prefix.sin6_addr,
1957                                                  pr->ndpr_plen)) {
1958                                 int e;
1959
1960                                 if ((e = nd6_prefix_onlink(opr)) != 0) {
1961                                         nd6log((LOG_ERR,
1962                                             "nd6_prefix_offlink: failed to "
1963                                             "recover a prefix %s/%d from %s "
1964                                             "to %s (errno = %d)\n",
1965                                             ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
1966                                             opr->ndpr_plen, if_name(ifp),
1967                                             if_name(opr->ndpr_ifp), e));
1968                                 }
1969                         }
1970                 }
1971         }
1972         else {
1973                 /* XXX: can we still set the NDPRF_ONLINK flag? */
1974                 nd6log((LOG_ERR,
1975                     "nd6_prefix_offlink: failed to delete route: "
1976                     "%s/%d on %s (errno = %d)\n",
1977                     ip6_sprintf(&sa6.sin6_addr), pr->ndpr_plen, if_name(ifp),
1978                     error));
1979         }
1980
1981         if (rt != NULL) {
1982                 if (rt->rt_refcnt <= 0) {
1983                         /* XXX: we should free the entry ourselves. */
1984                         rt->rt_refcnt++;
1985                         rtfree(rt);
1986                 }
1987         }
1988
1989         return(error);
1990 }
1991
1992 static struct in6_ifaddr *
1993 in6_ifadd(pr)
1994         struct nd_prefix *pr;
1995 {
1996         struct ifnet *ifp = pr->ndpr_ifp;
1997         struct ifaddr *ifa;
1998         struct in6_aliasreq ifra;
1999         struct in6_ifaddr *ia, *ib;
2000         int error, plen0;
2001         struct in6_addr mask;
2002         int prefixlen = pr->ndpr_plen;
2003
2004         in6_prefixlen2mask(&mask, prefixlen);
2005
2006         /*
2007          * find a link-local address (will be interface ID).
2008          * Is it really mandatory? Theoretically, a global or a site-local
2009          * address can be configured without a link-local address, if we
2010          * have a unique interface identifier...
2011          *
2012          * it is not mandatory to have a link-local address, we can generate
2013          * interface identifier on the fly.  we do this because:
2014          * (1) it should be the easiest way to find interface identifier.
2015          * (2) RFC2462 5.4 suggesting the use of the same interface identifier
2016          * for multiple addresses on a single interface, and possible shortcut
2017          * of DAD.  we omitted DAD for this reason in the past.
2018          * (3) a user can prevent autoconfiguration of global address 
2019          * by removing link-local address by hand (this is partly because we
2020          * don't have other way to control the use of IPv6 on a interface.
2021          * this has been our design choice - cf. NRL's "ifconfig auto").
2022          * (4) it is easier to manage when an interface has addresses
2023          * with the same interface identifier, than to have multiple addresses
2024          * with different interface identifiers.
2025          */
2026         ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */
2027         if (ifa)
2028                 ib = (struct in6_ifaddr *)ifa;
2029         else
2030                 return NULL;
2031
2032 #if 0 /* don't care link local addr state, and always do DAD */
2033         /* if link-local address is not eligible, do not autoconfigure. */
2034         if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY) {
2035                 printf("in6_ifadd: link-local address not ready\n");
2036                 return NULL;
2037         }
2038 #endif
2039
2040         /* prefixlen + ifidlen must be equal to 128 */
2041         plen0 = in6_mask2len(&ib->ia_prefixmask.sin6_addr, NULL);
2042         if (prefixlen != plen0) {
2043                 nd6log((LOG_INFO, "in6_ifadd: wrong prefixlen for %s "
2044                     "(prefix=%d ifid=%d)\n",
2045                     if_name(ifp), prefixlen, 128 - plen0));
2046                 return NULL;
2047         }
2048
2049         /* make ifaddr */
2050
2051         bzero(&ifra, sizeof(ifra));
2052         /*
2053          * in6_update_ifa() does not use ifra_name, but we accurately set it
2054          * for safety.
2055          */
2056         strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
2057         ifra.ifra_addr.sin6_family = AF_INET6;
2058         ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
2059         /* prefix */
2060         bcopy(&pr->ndpr_prefix.sin6_addr, &ifra.ifra_addr.sin6_addr,
2061               sizeof(ifra.ifra_addr.sin6_addr));
2062         ifra.ifra_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
2063         ifra.ifra_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
2064         ifra.ifra_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
2065         ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
2066
2067         /* interface ID */
2068         ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
2069             (ib->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
2070         ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
2071             (ib->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
2072         ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
2073             (ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
2074         ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
2075             (ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
2076             
2077         /* new prefix mask. */
2078         ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
2079         ifra.ifra_prefixmask.sin6_family = AF_INET6;
2080         bcopy(&mask, &ifra.ifra_prefixmask.sin6_addr,
2081               sizeof(ifra.ifra_prefixmask.sin6_addr));
2082
2083         /*
2084          * lifetime.
2085          * XXX: in6_init_address_ltimes would override these values later.
2086          * We should reconsider this logic. 
2087          */
2088         ifra.ifra_lifetime.ia6t_vltime = pr->ndpr_vltime;
2089         ifra.ifra_lifetime.ia6t_pltime = pr->ndpr_pltime;
2090
2091         /* XXX: scope zone ID? */
2092
2093         ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
2094
2095         /* allocate ifaddr structure, link into chain, etc. */
2096         if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
2097                 nd6log((LOG_ERR,
2098                     "in6_ifadd: failed to make ifaddr %s on %s (errno=%d)\n",
2099                     ip6_sprintf(&ifra.ifra_addr.sin6_addr), if_name(ifp),
2100                     error));
2101                 return(NULL);   /* ifaddr must not have been allocated. */
2102         }
2103
2104         ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
2105
2106         return(ia);             /* this is always non-NULL */
2107 }
2108
2109 int
2110 in6_tmpifadd(ia0, forcegen)
2111         const struct in6_ifaddr *ia0; /* corresponding public address */
2112         int forcegen;
2113 {
2114         struct ifnet *ifp = ia0->ia_ifa.ifa_ifp;
2115         struct in6_ifaddr *newia, *ia;
2116         struct in6_aliasreq ifra;
2117         int i, error;
2118         int trylimit = 3;       /* XXX: adhoc value */
2119         u_int32_t randid[2];
2120         u_int32_t vltime0, pltime0;
2121 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
2122         time_t time_second = (time_t)time.tv_sec;
2123 #endif
2124
2125         bzero(&ifra, sizeof(ifra));
2126         strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
2127         ifra.ifra_addr = ia0->ia_addr;
2128         /* copy prefix mask */
2129         ifra.ifra_prefixmask = ia0->ia_prefixmask;
2130         /* clear the old IFID */
2131         for (i = 0; i < 4; i++) {
2132                 ifra.ifra_addr.sin6_addr.s6_addr32[i]
2133                         &= ifra.ifra_prefixmask.sin6_addr.s6_addr32[i];
2134         }
2135
2136   again:
2137         if (in6_get_tmpifid(ifp, (u_int8_t *)randid,
2138                             (const u_int8_t *)&ia0->ia_addr.sin6_addr.s6_addr[8],
2139                             forcegen)) {
2140                 nd6log((LOG_NOTICE, "in6_tmpifadd: failed to find a good "
2141                         "random IFID\n"));
2142                 return(EINVAL);
2143         }
2144         ifra.ifra_addr.sin6_addr.s6_addr32[2]
2145                 |= (randid[0] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[2]));
2146         ifra.ifra_addr.sin6_addr.s6_addr32[3]
2147                 |= (randid[1] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[3]));
2148
2149         /*
2150          * in6_get_tmpifid() quite likely provided a unique interface ID.
2151          * However, we may still have a chance to see collision, because
2152          * there may be a time lag between generation of the ID and generation
2153          * of the address.  So, we'll do one more sanity check.
2154          */
2155         for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
2156                 if (SA6_ARE_ADDR_EQUAL(&ia->ia_addr,
2157                                        &ifra.ifra_addr)) {
2158                         if (trylimit-- == 0) {
2159                                 /*
2160                                  * Give up.  Something strange should have
2161                                  * happened.
2162                                  */
2163                                 nd6log((LOG_NOTICE, "in6_tmpifadd: failed to "
2164                                         "find a unique random IFID\n"));
2165                                 return(EEXIST);
2166                         }
2167                         forcegen = 1;
2168                         goto again;
2169                 }
2170         }
2171
2172         /*
2173          * The Valid Lifetime is the lower of the Valid Lifetime of the
2174          * public address or TEMP_VALID_LIFETIME.
2175          * The Preferred Lifetime is the lower of the Preferred Lifetime
2176          * of the public address or TEMP_PREFERRED_LIFETIME -
2177          * DESYNC_FACTOR.
2178          */
2179         if (ia0->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
2180                 vltime0 = IFA6_IS_INVALID(ia0) ? 0 :
2181                         (ia0->ia6_lifetime.ia6t_vltime -
2182                          (time_second - ia0->ia6_updatetime));
2183                 if (vltime0 > ip6_temp_valid_lifetime)
2184                         vltime0 = ip6_temp_valid_lifetime;
2185         } else
2186                 vltime0 = ip6_temp_valid_lifetime;
2187         if (ia0->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
2188                 pltime0 = IFA6_IS_DEPRECATED(ia0) ? 0 :
2189                         (ia0->ia6_lifetime.ia6t_pltime -
2190                          (time_second - ia0->ia6_updatetime));
2191                 if (pltime0 > ip6_temp_preferred_lifetime - ip6_desync_factor){
2192                         pltime0 = ip6_temp_preferred_lifetime -
2193                                 ip6_desync_factor;
2194                 }
2195         } else
2196                 pltime0 = ip6_temp_preferred_lifetime - ip6_desync_factor;
2197         ifra.ifra_lifetime.ia6t_vltime = vltime0;
2198         ifra.ifra_lifetime.ia6t_pltime = pltime0;
2199
2200         /*
2201          * A temporary address is created only if this calculated Preferred
2202          * Lifetime is greater than REGEN_ADVANCE time units.
2203          */
2204         if (ifra.ifra_lifetime.ia6t_pltime <= ip6_temp_regen_advance)
2205                 return(0);
2206
2207         /* XXX: scope zone ID? */
2208
2209         ifra.ifra_flags |= (IN6_IFF_AUTOCONF|IN6_IFF_TEMPORARY);
2210
2211         /* allocate ifaddr structure, link into chain, etc. */
2212         if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0)
2213                 return(error);
2214
2215         newia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
2216         if (newia == NULL) {    /* XXX: can it happen? */
2217                 nd6log((LOG_ERR,
2218                     "in6_tmpifadd: ifa update succeeded, but we got "
2219                     "no ifaddr\n"));
2220                 return(EINVAL); /* XXX */
2221         }
2222         newia->ia6_ndpr = ia0->ia6_ndpr;
2223         newia->ia6_ndpr->ndpr_refcnt++;
2224
2225         /*
2226          * A newly added address might affect the status of other addresses.
2227          * XXX: when the temporary address is generated with a new public
2228          * address, the onlink check is redundant.  However, it would be safe
2229          * to do the check explicitly everywhere a new address is generated,
2230          * and, in fact, we surely need the check when we create a new
2231          * temporary address due to deprecation of an old temporary address.
2232          */
2233         pfxlist_onlink_check();
2234
2235         return(0);
2236 }           
2237
2238 int
2239 in6_init_prefix_ltimes(struct nd_prefix *ndpr)
2240 {
2241 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
2242         long time_second = time.tv_sec;
2243 #endif
2244
2245         /* check if preferred lifetime > valid lifetime.  RFC2462 5.5.3 (c) */
2246         if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
2247                 nd6log((LOG_INFO, "in6_init_prefix_ltimes: preferred lifetime"
2248                     "(%d) is greater than valid lifetime(%d)\n",
2249                     (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime));
2250                 return (EINVAL);
2251         }
2252         if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
2253                 ndpr->ndpr_preferred = 0;
2254         else
2255                 ndpr->ndpr_preferred = time_second + ndpr->ndpr_pltime;
2256         if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
2257                 ndpr->ndpr_expire = 0;
2258         else
2259                 ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
2260
2261         return 0;
2262 }
2263
2264 static void
2265 in6_init_address_ltimes(struct nd_prefix *new, struct in6_addrlifetime *lt6)
2266 {
2267 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
2268         long time_second = time.tv_sec;
2269 #endif
2270
2271         /* Valid lifetime must not be updated unless explicitly specified. */
2272         /* init ia6t_expire */
2273         if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
2274                 lt6->ia6t_expire = 0;
2275         else {
2276                 lt6->ia6t_expire = time_second;
2277                 lt6->ia6t_expire += lt6->ia6t_vltime;
2278         }
2279
2280         /* init ia6t_preferred */
2281         if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
2282                 lt6->ia6t_preferred = 0;
2283         else {
2284                 lt6->ia6t_preferred = time_second;
2285                 lt6->ia6t_preferred += lt6->ia6t_pltime;
2286         }
2287 }
2288
2289 /*
2290  * Delete all the routing table entries that use the specified gateway.
2291  * XXX: this function causes search through all entries of routing table, so
2292  * it shouldn't be called when acting as a router.
2293  */
2294 void
2295 rt6_flush(gateway, ifp)
2296         struct in6_addr *gateway;
2297         struct ifnet *ifp;
2298 {
2299         struct radix_node_head *rnh = rt_tables[AF_INET6];
2300 #ifdef __NetBSD__
2301         int s = splsoftnet();
2302 #else
2303         int s = splnet();
2304 #endif
2305
2306         /* We'll care only link-local addresses */
2307         if (!IN6_IS_ADDR_LINKLOCAL(gateway)) {
2308                 splx(s);
2309                 return;
2310         }
2311         /* XXX: hack for KAME's link-local address kludge */
2312         gateway->s6_addr16[1] = htons(ifp->if_index);
2313
2314         rnh->rnh_walktree(rnh, rt6_deleteroute, (void *)gateway);
2315         splx(s);
2316 }
2317
2318 static int
2319 rt6_deleteroute(rn, arg)
2320         struct radix_node *rn;
2321         void *arg;
2322 {
2323 #define SIN6(s) ((struct sockaddr_in6 *)s)
2324         struct rtentry *rt = (struct rtentry *)rn;
2325         struct in6_addr *gate = (struct in6_addr *)arg;
2326
2327         if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
2328                 return(0);
2329
2330         if (!IN6_ARE_ADDR_EQUAL(gate, &SIN6(rt->rt_gateway)->sin6_addr))
2331                 return(0);
2332
2333         /*
2334          * Do not delete a static route.
2335          * XXX: this seems to be a bit ad-hoc. Should we consider the
2336          * 'cloned' bit instead?
2337          */
2338         if ((rt->rt_flags & RTF_STATIC) != 0)
2339                 return(0);
2340
2341         /*
2342          * We delete only host route. This means, in particular, we don't
2343          * delete default route.
2344          */
2345         if ((rt->rt_flags & RTF_HOST) == 0)
2346                 return(0);
2347
2348         return(rtrequest(RTM_DELETE, rt_key(rt),
2349                          rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0));
2350 #undef SIN6
2351 }
2352
2353 int
2354 nd6_setdefaultiface(ifindex)
2355         int ifindex;
2356 {
2357         int error = 0;
2358
2359         if (ifindex < 0 || if_index < ifindex)
2360                 return(EINVAL);
2361
2362         if (nd6_defifindex != ifindex) {
2363                 nd6_defifindex = ifindex;
2364                 if (nd6_defifindex > 0) {
2365 #if defined(__FreeBSD__) && __FreeBSD__ >= 5
2366                         nd6_defifp = ifnet_byindex[nd6_defifindex];
2367 #else
2368                         nd6_defifp = ifindex2ifnet[nd6_defifindex];
2369 #endif
2370                 } else
2371                         nd6_defifp = NULL;
2372
2373                 /*
2374                  * Rescan default router list, refresh default route(s).
2375                  */
2376                 defrouter_select();
2377
2378                 /*
2379                  * Our current implementation assumes one-to-one maping between
2380                  * interfaces and links, so it would be natural to use the
2381                  * default interface as the default link.
2382                  */
2383                 scope6_setdefault(nd6_defifp);
2384         }
2385
2386         return(error);
2387 }