This source file includes following definitions.
- nd6_init
- nd6_ifattach
- nd6_ifdetach
- nd6_setmtu
- nd6_setmtu0
- nd6_option_init
- nd6_option
- nd6_options
- nd6_llinfo_settimer
- nd6_llinfo_timer
- nd6_timer
- nd6_purge
- nd6_lookup
- nd6_is_addr_neighbor
- nd6_free
- nd6_nud_hint
- nd6_rtrequest
- nd6_ioctl
- nd6_cache_lladdr
- nd6_slowtimo
- nd6_output
- nd6_need_cache
- nd6_storelladdr
- nd6_sysctl
- fill_drlist
- fill_prlist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/timeout.h>
36 #include <sys/malloc.h>
37 #include <sys/mbuf.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/time.h>
41 #include <sys/kernel.h>
42 #include <sys/protosw.h>
43 #include <sys/errno.h>
44 #include <sys/ioctl.h>
45 #include <sys/syslog.h>
46 #include <sys/queue.h>
47 #include <dev/rndvar.h>
48
49 #include <net/if.h>
50 #include <net/if_dl.h>
51 #include <net/if_types.h>
52 #include <net/if_fddi.h>
53 #include <net/route.h>
54
55 #include <netinet/in.h>
56 #include <netinet/if_ether.h>
57 #include <netinet/ip_ipsp.h>
58
59 #include <netinet6/in6_var.h>
60 #include <netinet/ip6.h>
61 #include <netinet6/ip6_var.h>
62 #include <netinet6/nd6.h>
63 #include <netinet/icmp6.h>
64
65 #define ND6_SLOWTIMER_INTERVAL (60 * 60)
66 #define ND6_RECALC_REACHTM_INTERVAL (60 * 120)
67
68 #define SIN6(s) ((struct sockaddr_in6 *)s)
69 #define SDL(s) ((struct sockaddr_dl *)s)
70
71
72 int nd6_prune = 1;
73 int nd6_delay = 5;
74 int nd6_umaxtries = 3;
75 int nd6_mmaxtries = 3;
76 int nd6_useloopback = 1;
77 int nd6_gctimer = (60 * 60 * 24);
78
79
80 int nd6_maxndopt = 10;
81
82 int nd6_maxnudhint = 0;
83
84 #ifdef ND6_DEBUG
85 int nd6_debug = 1;
86 #else
87 int nd6_debug = 0;
88 #endif
89
90
91 static int nd6_inuse, nd6_allocated;
92
93 struct llinfo_nd6 llinfo_nd6 = {&llinfo_nd6, &llinfo_nd6};
94 struct nd_drhead nd_defrouter;
95 struct nd_prhead nd_prefix = { 0 };
96
97 int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL;
98 static struct sockaddr_in6 all1_sa;
99
100 static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
101 static void nd6_slowtimo(void *);
102 static struct llinfo_nd6 *nd6_free(struct rtentry *, int);
103 static void nd6_llinfo_timer(void *);
104
105 struct timeout nd6_slowtimo_ch;
106 struct timeout nd6_timer_ch;
107 extern struct timeout in6_tmpaddrtimer_ch;
108
109 static int fill_drlist(void *, size_t *, size_t);
110 static int fill_prlist(void *, size_t *, size_t);
111
112 void
113 nd6_init()
114 {
115 static int nd6_init_done = 0;
116 int i;
117
118 if (nd6_init_done) {
119 log(LOG_NOTICE, "nd6_init called more than once(ignored)\n");
120 return;
121 }
122
123 all1_sa.sin6_family = AF_INET6;
124 all1_sa.sin6_len = sizeof(struct sockaddr_in6);
125 for (i = 0; i < sizeof(all1_sa.sin6_addr); i++)
126 all1_sa.sin6_addr.s6_addr[i] = 0xff;
127
128
129 TAILQ_INIT(&nd_defrouter);
130
131 nd6_init_done = 1;
132
133
134 timeout_set(&nd6_slowtimo_ch, nd6_slowtimo, NULL);
135 timeout_add(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz);
136 }
137
138 struct nd_ifinfo *
139 nd6_ifattach(ifp)
140 struct ifnet *ifp;
141 {
142 struct nd_ifinfo *nd;
143
144 nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK);
145 bzero(nd, sizeof(*nd));
146
147 nd->initialized = 1;
148
149 nd->chlim = IPV6_DEFHLIM;
150 nd->basereachable = REACHABLE_TIME;
151 nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
152 nd->retrans = RETRANS_TIMER;
153
154
155
156
157
158 nd->flags = (ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV);
159
160
161 nd6_setmtu0(ifp, nd);
162
163 return nd;
164 }
165
166 void
167 nd6_ifdetach(nd)
168 struct nd_ifinfo *nd;
169 {
170
171 free(nd, M_IP6NDP);
172 }
173
174 void
175 nd6_setmtu(ifp)
176 struct ifnet *ifp;
177 {
178 nd6_setmtu0(ifp, ND_IFINFO(ifp));
179 }
180
181 void
182 nd6_setmtu0(ifp, ndi)
183 struct ifnet *ifp;
184 struct nd_ifinfo *ndi;
185 {
186 u_int32_t omaxmtu;
187
188 omaxmtu = ndi->maxmtu;
189
190 if (ifp->if_type == IFT_FDDI)
191 ndi->maxmtu = MIN(FDDIMTU, ifp->if_mtu);
192 else
193 ndi->maxmtu = ifp->if_mtu;
194
195
196
197
198
199
200
201 if (omaxmtu >= IPV6_MMTU && ndi->maxmtu < IPV6_MMTU) {
202 log(LOG_NOTICE, "nd6_setmtu0: "
203 "new link MTU on %s (%lu) is too small for IPv6\n",
204 ifp->if_xname, (unsigned long)ndi->maxmtu);
205 }
206
207 if (ndi->maxmtu > in6_maxmtu)
208 in6_setmaxmtu();
209 }
210
211 void
212 nd6_option_init(opt, icmp6len, ndopts)
213 void *opt;
214 int icmp6len;
215 union nd_opts *ndopts;
216 {
217
218 bzero(ndopts, sizeof(*ndopts));
219 ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;
220 ndopts->nd_opts_last
221 = (struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);
222
223 if (icmp6len == 0) {
224 ndopts->nd_opts_done = 1;
225 ndopts->nd_opts_search = NULL;
226 }
227 }
228
229
230
231
232 struct nd_opt_hdr *
233 nd6_option(ndopts)
234 union nd_opts *ndopts;
235 {
236 struct nd_opt_hdr *nd_opt;
237 int olen;
238
239 if (!ndopts)
240 panic("ndopts == NULL in nd6_option");
241 if (!ndopts->nd_opts_last)
242 panic("uninitialized ndopts in nd6_option");
243 if (!ndopts->nd_opts_search)
244 return NULL;
245 if (ndopts->nd_opts_done)
246 return NULL;
247
248 nd_opt = ndopts->nd_opts_search;
249
250
251 if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
252 bzero(ndopts, sizeof(*ndopts));
253 return NULL;
254 }
255
256 olen = nd_opt->nd_opt_len << 3;
257 if (olen == 0) {
258
259
260
261
262 bzero(ndopts, sizeof(*ndopts));
263 return NULL;
264 }
265
266 ndopts->nd_opts_search = (struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
267 if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
268
269 bzero(ndopts, sizeof(*ndopts));
270 return NULL;
271 } else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
272
273 ndopts->nd_opts_done = 1;
274 ndopts->nd_opts_search = NULL;
275 }
276 return nd_opt;
277 }
278
279
280
281
282
283
284 int
285 nd6_options(ndopts)
286 union nd_opts *ndopts;
287 {
288 struct nd_opt_hdr *nd_opt;
289 int i = 0;
290
291 if (!ndopts)
292 panic("ndopts == NULL in nd6_options");
293 if (!ndopts->nd_opts_last)
294 panic("uninitialized ndopts in nd6_options");
295 if (!ndopts->nd_opts_search)
296 return 0;
297
298 while (1) {
299 nd_opt = nd6_option(ndopts);
300 if (!nd_opt && !ndopts->nd_opts_last) {
301
302
303
304
305 icmp6stat.icp6s_nd_badopt++;
306 bzero(ndopts, sizeof(*ndopts));
307 return -1;
308 }
309
310 if (!nd_opt)
311 goto skip1;
312
313 switch (nd_opt->nd_opt_type) {
314 case ND_OPT_SOURCE_LINKADDR:
315 case ND_OPT_TARGET_LINKADDR:
316 case ND_OPT_MTU:
317 case ND_OPT_REDIRECTED_HEADER:
318 if (ndopts->nd_opt_array[nd_opt->nd_opt_type]) {
319 nd6log((LOG_INFO,
320 "duplicated ND6 option found (type=%d)\n",
321 nd_opt->nd_opt_type));
322
323 } else {
324 ndopts->nd_opt_array[nd_opt->nd_opt_type]
325 = nd_opt;
326 }
327 break;
328 case ND_OPT_PREFIX_INFORMATION:
329 if (ndopts->nd_opt_array[nd_opt->nd_opt_type] == 0) {
330 ndopts->nd_opt_array[nd_opt->nd_opt_type]
331 = nd_opt;
332 }
333 ndopts->nd_opts_pi_end =
334 (struct nd_opt_prefix_info *)nd_opt;
335 break;
336 default:
337
338
339
340
341 nd6log((LOG_DEBUG,
342 "nd6_options: unsupported option %d - "
343 "option ignored\n", nd_opt->nd_opt_type));
344 }
345
346 skip1:
347 i++;
348 if (i > nd6_maxndopt) {
349 icmp6stat.icp6s_nd_toomanyopt++;
350 nd6log((LOG_INFO, "too many loop in nd opt\n"));
351 break;
352 }
353
354 if (ndopts->nd_opts_done)
355 break;
356 }
357
358 return 0;
359 }
360
361
362
363
364 void
365 nd6_llinfo_settimer(struct llinfo_nd6 *ln, long tick)
366 {
367 int s;
368
369 s = splsoftnet();
370
371 if (tick < 0) {
372 ln->ln_expire = 0;
373 ln->ln_ntick = 0;
374 timeout_del(&ln->ln_timer_ch);
375 } else {
376 ln->ln_expire = time_second + tick / hz;
377 if (tick > INT_MAX) {
378 ln->ln_ntick = tick - INT_MAX;
379 timeout_add(&ln->ln_timer_ch, INT_MAX);
380 } else {
381 ln->ln_ntick = 0;
382 timeout_add(&ln->ln_timer_ch, tick);
383 }
384 }
385
386 splx(s);
387 }
388
389 static void
390 nd6_llinfo_timer(void *arg)
391 {
392 int s;
393 struct llinfo_nd6 *ln;
394 struct rtentry *rt;
395 struct sockaddr_in6 *dst;
396 struct ifnet *ifp;
397 struct nd_ifinfo *ndi = NULL;
398
399 s = splsoftnet();
400
401 ln = (struct llinfo_nd6 *)arg;
402
403 if (ln->ln_ntick > 0) {
404 if (ln->ln_ntick > INT_MAX) {
405 ln->ln_ntick -= INT_MAX;
406 nd6_llinfo_settimer(ln, INT_MAX);
407 } else {
408 ln->ln_ntick = 0;
409 nd6_llinfo_settimer(ln, ln->ln_ntick);
410 }
411 splx(s);
412 return;
413 }
414
415 if ((rt = ln->ln_rt) == NULL)
416 panic("ln->ln_rt == NULL");
417 if ((ifp = rt->rt_ifp) == NULL)
418 panic("ln->ln_rt->rt_ifp == NULL");
419 ndi = ND_IFINFO(ifp);
420 dst = (struct sockaddr_in6 *)rt_key(rt);
421
422
423 if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln)
424 panic("rt_llinfo(%p) is not equal to ln(%p)",
425 rt->rt_llinfo, ln);
426 if (!dst)
427 panic("dst=0 in nd6_timer(ln=%p)", ln);
428
429 switch (ln->ln_state) {
430 case ND6_LLINFO_INCOMPLETE:
431 if (ln->ln_asked < nd6_mmaxtries) {
432 ln->ln_asked++;
433 nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
434 nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
435 } else {
436 struct mbuf *m = ln->ln_hold;
437 if (m) {
438 ln->ln_hold = NULL;
439
440
441
442
443
444
445
446 m->m_pkthdr.rcvif = rt->rt_ifp;
447
448 icmp6_error(m, ICMP6_DST_UNREACH,
449 ICMP6_DST_UNREACH_ADDR, 0);
450 }
451 (void)nd6_free(rt, 0);
452 ln = NULL;
453 }
454 break;
455 case ND6_LLINFO_REACHABLE:
456 if (!ND6_LLINFO_PERMANENT(ln)) {
457 ln->ln_state = ND6_LLINFO_STALE;
458 nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
459 }
460 break;
461
462 case ND6_LLINFO_STALE:
463
464 if (!ND6_LLINFO_PERMANENT(ln)) {
465 (void)nd6_free(rt, 1);
466 ln = NULL;
467 }
468 break;
469
470 case ND6_LLINFO_DELAY:
471 if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
472
473 ln->ln_asked = 1;
474 ln->ln_state = ND6_LLINFO_PROBE;
475 nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
476 nd6_ns_output(ifp, &dst->sin6_addr,
477 &dst->sin6_addr, ln, 0);
478 } else {
479 ln->ln_state = ND6_LLINFO_STALE;
480 nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
481 }
482 break;
483 case ND6_LLINFO_PROBE:
484 if (ln->ln_asked < nd6_umaxtries) {
485 ln->ln_asked++;
486 nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
487 nd6_ns_output(ifp, &dst->sin6_addr,
488 &dst->sin6_addr, ln, 0);
489 } else {
490 (void)nd6_free(rt, 0);
491 ln = NULL;
492 }
493 break;
494 }
495
496 splx(s);
497 }
498
499
500
501
502 void
503 nd6_timer(ignored_arg)
504 void *ignored_arg;
505 {
506 int s;
507 struct nd_defrouter *dr;
508 struct nd_prefix *pr;
509 struct in6_ifaddr *ia6, *nia6;
510 struct in6_addrlifetime *lt6;
511
512 s = splsoftnet();
513 timeout_set(&nd6_timer_ch, nd6_timer, NULL);
514 timeout_add(&nd6_timer_ch, nd6_prune * hz);
515
516
517 dr = TAILQ_FIRST(&nd_defrouter);
518 while (dr) {
519 if (dr->expire && dr->expire < time_second) {
520 struct nd_defrouter *t;
521 t = TAILQ_NEXT(dr, dr_entry);
522 defrtrlist_del(dr);
523 dr = t;
524 } else {
525 dr = TAILQ_NEXT(dr, dr_entry);
526 }
527 }
528
529
530
531
532
533
534
535 for (ia6 = in6_ifaddr; ia6; ia6 = nia6) {
536 nia6 = ia6->ia_next;
537
538 lt6 = &ia6->ia6_lifetime;
539 if (IFA6_IS_INVALID(ia6)) {
540 in6_purgeaddr(&ia6->ia_ifa);
541 } else if (IFA6_IS_DEPRECATED(ia6)) {
542 ia6->ia6_flags |= IN6_IFF_DEPRECATED;
543 } else {
544
545
546
547
548 ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
549 }
550 }
551
552
553 pr = LIST_FIRST(&nd_prefix);
554 while (pr != NULL) {
555
556
557
558
559
560 if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
561 time_second - pr->ndpr_lastupdate > pr->ndpr_vltime) {
562 struct nd_prefix *t;
563 t = LIST_NEXT(pr, ndpr_entry);
564
565
566
567
568
569
570 prelist_remove(pr);
571 pr = t;
572 } else
573 pr = LIST_NEXT(pr, ndpr_entry);
574 }
575 splx(s);
576 }
577
578
579
580
581
582 void
583 nd6_purge(ifp)
584 struct ifnet *ifp;
585 {
586 struct llinfo_nd6 *ln, *nln;
587 struct nd_defrouter *dr, *ndr;
588 struct nd_prefix *pr, *npr;
589
590
591
592
593
594
595
596 for (dr = TAILQ_FIRST(&nd_defrouter); dr; dr = ndr) {
597 ndr = TAILQ_NEXT(dr, dr_entry);
598 if (dr->installed)
599 continue;
600
601 if (dr->ifp == ifp)
602 defrtrlist_del(dr);
603 }
604 for (dr = TAILQ_FIRST(&nd_defrouter); dr; dr = ndr) {
605 ndr = TAILQ_NEXT(dr, dr_entry);
606 if (!dr->installed)
607 continue;
608
609 if (dr->ifp == ifp)
610 defrtrlist_del(dr);
611 }
612
613
614 for (pr = LIST_FIRST(&nd_prefix); pr != NULL; pr = npr) {
615 npr = LIST_NEXT(pr, ndpr_entry);
616 if (pr->ndpr_ifp == ifp) {
617
618
619
620
621
622
623 pr->ndpr_refcnt = 0;
624
625
626
627
628
629
630
631
632 prelist_remove(pr);
633 }
634 }
635
636
637 if (nd6_defifindex == ifp->if_index)
638 nd6_setdefaultiface(0);
639
640 if (!ip6_forwarding && ip6_accept_rtadv) {
641
642 defrouter_select();
643 }
644
645
646
647
648
649
650
651 ln = llinfo_nd6.ln_next;
652 while (ln && ln != &llinfo_nd6) {
653 struct rtentry *rt;
654 struct sockaddr_dl *sdl;
655
656 nln = ln->ln_next;
657 rt = ln->ln_rt;
658 if (rt && rt->rt_gateway &&
659 rt->rt_gateway->sa_family == AF_LINK) {
660 sdl = (struct sockaddr_dl *)rt->rt_gateway;
661 if (sdl->sdl_index == ifp->if_index)
662 nln = nd6_free(rt, 0);
663 }
664 ln = nln;
665 }
666 }
667
668 struct rtentry *
669 nd6_lookup(addr6, create, ifp)
670 struct in6_addr *addr6;
671 int create;
672 struct ifnet *ifp;
673 {
674 struct rtentry *rt;
675 struct sockaddr_in6 sin6;
676
677 bzero(&sin6, sizeof(sin6));
678 sin6.sin6_len = sizeof(struct sockaddr_in6);
679 sin6.sin6_family = AF_INET6;
680 sin6.sin6_addr = *addr6;
681
682 rt = rtalloc1((struct sockaddr *)&sin6, create, 0);
683 if (rt && (rt->rt_flags & RTF_LLINFO) == 0) {
684
685
686
687
688
689
690 if (create) {
691 RTFREE(rt);
692 rt = 0;
693 }
694 }
695 if (!rt) {
696 if (create && ifp) {
697 int e;
698
699
700
701
702
703
704
705
706 struct ifaddr *ifa =
707 ifaof_ifpforaddr((struct sockaddr *)&sin6, ifp);
708 if (ifa == NULL)
709 return (NULL);
710
711
712
713
714
715
716
717 if ((e = rtrequest(RTM_ADD, (struct sockaddr *)&sin6,
718 ifa->ifa_addr, (struct sockaddr *)&all1_sa,
719 (ifa->ifa_flags | RTF_HOST | RTF_LLINFO) &
720 ~RTF_CLONING, &rt, 0)) != 0) {
721 #if 0
722 log(LOG_ERR,
723 "nd6_lookup: failed to add route for a "
724 "neighbor(%s), errno=%d\n",
725 ip6_sprintf(addr6), e);
726 #endif
727 return (NULL);
728 }
729 if (rt == NULL)
730 return (NULL);
731 if (rt->rt_llinfo) {
732 struct llinfo_nd6 *ln =
733 (struct llinfo_nd6 *)rt->rt_llinfo;
734 ln->ln_state = ND6_LLINFO_NOSTATE;
735 }
736 } else
737 return (NULL);
738 }
739 rt->rt_refcnt--;
740
741
742
743
744
745
746
747
748
749
750
751
752 if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
753 rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL ||
754 (ifp && rt->rt_ifa->ifa_ifp != ifp)) {
755 if (create) {
756 nd6log((LOG_DEBUG,
757 "nd6_lookup: failed to lookup %s (if = %s)\n",
758 ip6_sprintf(addr6),
759 ifp ? ifp->if_xname : "unspec"));
760 }
761 return (NULL);
762 }
763 return (rt);
764 }
765
766
767
768
769
770 int
771 nd6_is_addr_neighbor(addr, ifp)
772 struct sockaddr_in6 *addr;
773 struct ifnet *ifp;
774 {
775 struct nd_prefix *pr;
776 struct rtentry *rt;
777
778
779
780
781
782
783
784 if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr) &&
785 ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]) == ifp->if_index)
786 return (1);
787
788
789
790
791
792 LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
793 if (pr->ndpr_ifp != ifp)
794 continue;
795
796 if (!(pr->ndpr_stateflags & NDPRF_ONLINK))
797 continue;
798
799 if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
800 &addr->sin6_addr, &pr->ndpr_mask))
801 return (1);
802 }
803
804
805
806
807
808
809
810 if (!ip6_forwarding && TAILQ_FIRST(&nd_defrouter) == NULL &&
811 nd6_defifindex == ifp->if_index) {
812 return (1);
813 }
814
815
816
817
818
819 if ((rt = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL)
820 return (1);
821
822 return (0);
823 }
824
825
826
827
828
829
830
831 static struct llinfo_nd6 *
832 nd6_free(rt, gc)
833 struct rtentry *rt;
834 int gc;
835 {
836 struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
837 struct in6_addr in6 = ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
838 struct nd_defrouter *dr;
839
840
841
842
843
844
845 if (!ip6_forwarding) {
846 int s;
847 s = splsoftnet();
848 dr = defrouter_lookup(&((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
849 rt->rt_ifp);
850
851 if (dr != NULL && dr->expire &&
852 ln->ln_state == ND6_LLINFO_STALE && gc) {
853
854
855
856
857
858
859
860
861
862
863
864
865 if (dr->expire > time_second * hz) {
866 nd6_llinfo_settimer(ln,
867 dr->expire - time_second * hz);
868 } else
869 nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
870 splx(s);
871 return (ln->ln_next);
872 }
873
874 if (ln->ln_router || dr) {
875
876
877
878
879
880 rt6_flush(&in6, rt->rt_ifp);
881 }
882
883 if (dr) {
884
885
886
887
888
889
890
891
892
893
894
895
896
897 ln->ln_state = ND6_LLINFO_INCOMPLETE;
898
899
900
901
902
903
904
905 pfxlist_onlink_check();
906
907
908
909
910 defrouter_select();
911 }
912 splx(s);
913 }
914
915
916
917
918
919
920
921 next = ln->ln_next;
922
923
924
925
926
927
928 rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
929 rt_mask(rt), 0, (struct rtentry **)0, 0);
930
931 return (next);
932 }
933
934
935
936
937
938
939 void
940 nd6_nud_hint(rt, dst6, force)
941 struct rtentry *rt;
942 struct in6_addr *dst6;
943 int force;
944 {
945 struct llinfo_nd6 *ln;
946
947
948
949
950
951 if (!rt) {
952 if (!dst6)
953 return;
954 if (!(rt = nd6_lookup(dst6, 0, NULL)))
955 return;
956 }
957
958 if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
959 (rt->rt_flags & RTF_LLINFO) == 0 ||
960 !rt->rt_llinfo || !rt->rt_gateway ||
961 rt->rt_gateway->sa_family != AF_LINK) {
962
963 return;
964 }
965
966 ln = (struct llinfo_nd6 *)rt->rt_llinfo;
967 if (ln->ln_state < ND6_LLINFO_REACHABLE)
968 return;
969
970
971
972
973
974 if (!force) {
975 ln->ln_byhint++;
976 if (ln->ln_byhint > nd6_maxnudhint)
977 return;
978 }
979
980 ln->ln_state = ND6_LLINFO_REACHABLE;
981 if (!ND6_LLINFO_PERMANENT(ln)) {
982 nd6_llinfo_settimer(ln,
983 (long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
984 }
985 }
986
987 void
988 nd6_rtrequest(req, rt, info)
989 int req;
990 struct rtentry *rt;
991 struct rt_addrinfo *info;
992 {
993 struct sockaddr *gate = rt->rt_gateway;
994 struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
995 static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
996 struct ifnet *ifp = rt->rt_ifp;
997 struct ifaddr *ifa;
998 int mine = 0;
999
1000 if ((rt->rt_flags & RTF_GATEWAY) != 0)
1001 return;
1002
1003 if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
1004
1005
1006
1007
1008
1009
1010
1011 return;
1012 }
1013
1014 if (req == RTM_RESOLVE &&
1015 (nd6_need_cache(ifp) == 0 ||
1016 !nd6_is_addr_neighbor((struct sockaddr_in6 *)rt_key(rt), ifp))) {
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031 rt->rt_flags &= ~RTF_LLINFO;
1032 return;
1033 }
1034
1035 switch (req) {
1036 case RTM_ADD:
1037
1038
1039
1040
1041
1042
1043
1044 if ((rt->rt_flags & RTF_CLONING) ||
1045 ((rt->rt_flags & RTF_LLINFO) && !ln)) {
1046
1047
1048
1049
1050
1051
1052 rt_setgate(rt, rt_key(rt),
1053 (struct sockaddr *)&null_sdl, 0);
1054 gate = rt->rt_gateway;
1055 SDL(gate)->sdl_type = ifp->if_type;
1056 SDL(gate)->sdl_index = ifp->if_index;
1057 if (ln)
1058 nd6_llinfo_settimer(ln, 0);
1059 if ((rt->rt_flags & RTF_CLONING) != 0)
1060 break;
1061 }
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 #if 0
1081
1082 if (rt->rt_flags & RTF_ANNOUNCE)
1083 nd6_na_output(ifp,
1084 &SIN6(rt_key(rt))->sin6_addr,
1085 &SIN6(rt_key(rt))->sin6_addr,
1086 ip6_forwarding ? ND_NA_FLAG_ROUTER : 0,
1087 1, NULL);
1088 #endif
1089
1090 case RTM_RESOLVE:
1091 if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
1092
1093
1094
1095
1096 if (gate->sa_family != AF_LINK ||
1097 gate->sa_len < sizeof(null_sdl)) {
1098 log(LOG_DEBUG,
1099 "nd6_rtrequest: bad gateway value: %s\n",
1100 ifp->if_xname);
1101 break;
1102 }
1103 SDL(gate)->sdl_type = ifp->if_type;
1104 SDL(gate)->sdl_index = ifp->if_index;
1105 }
1106 if (ln != NULL)
1107 break;
1108
1109
1110
1111
1112 R_Malloc(ln, struct llinfo_nd6 *, sizeof(*ln));
1113 rt->rt_llinfo = (caddr_t)ln;
1114 if (!ln) {
1115 log(LOG_DEBUG, "nd6_rtrequest: malloc failed\n");
1116 break;
1117 }
1118 nd6_inuse++;
1119 nd6_allocated++;
1120 Bzero(ln, sizeof(*ln));
1121 ln->ln_rt = rt;
1122 timeout_set(&ln->ln_timer_ch, nd6_llinfo_timer, ln);
1123
1124 if (req == RTM_ADD) {
1125
1126
1127
1128
1129
1130 ln->ln_state = ND6_LLINFO_REACHABLE;
1131 ln->ln_byhint = 0;
1132 } else {
1133
1134
1135
1136
1137 ln->ln_state = ND6_LLINFO_NOSTATE;
1138 nd6_llinfo_settimer(ln, 0);
1139 }
1140 rt->rt_flags |= RTF_LLINFO;
1141 ln->ln_next = llinfo_nd6.ln_next;
1142 llinfo_nd6.ln_next = ln;
1143 ln->ln_prev = &llinfo_nd6;
1144 ln->ln_next->ln_prev = ln;
1145
1146
1147
1148
1149
1150 ifa = (struct ifaddr *)in6ifa_ifpwithaddr(rt->rt_ifp,
1151 &SIN6(rt_key(rt))->sin6_addr);
1152 if (ifa) {
1153 caddr_t macp = nd6_ifptomac(ifp);
1154 nd6_llinfo_settimer(ln, -1);
1155 ln->ln_state = ND6_LLINFO_REACHABLE;
1156 ln->ln_byhint = 0;
1157 mine = 1;
1158 if (macp) {
1159 Bcopy(macp, LLADDR(SDL(gate)), ifp->if_addrlen);
1160 SDL(gate)->sdl_alen = ifp->if_addrlen;
1161 }
1162 if (nd6_useloopback) {
1163 rt->rt_ifp = lo0ifp;
1164
1165
1166
1167
1168
1169
1170
1171
1172 if (ifa != rt->rt_ifa) {
1173 IFAFREE(rt->rt_ifa);
1174 ifa->ifa_refcnt++;
1175 rt->rt_ifa = ifa;
1176 }
1177 }
1178 } else if (rt->rt_flags & RTF_ANNOUNCE) {
1179 nd6_llinfo_settimer(ln, -1);
1180 ln->ln_state = ND6_LLINFO_REACHABLE;
1181 ln->ln_byhint = 0;
1182
1183
1184 if (ifp->if_flags & IFF_MULTICAST) {
1185 struct in6_addr llsol;
1186 int error;
1187
1188 llsol = SIN6(rt_key(rt))->sin6_addr;
1189 llsol.s6_addr16[0] = htons(0xff02);
1190 llsol.s6_addr16[1] = htons(ifp->if_index);
1191 llsol.s6_addr32[1] = 0;
1192 llsol.s6_addr32[2] = htonl(1);
1193 llsol.s6_addr8[12] = 0xff;
1194
1195 if (in6_addmulti(&llsol, ifp, &error)) {
1196 nd6log((LOG_ERR, "%s: failed to join "
1197 "%s (errno=%d)\n", ifp->if_xname,
1198 ip6_sprintf(&llsol), error));
1199 }
1200 }
1201 }
1202 break;
1203
1204 case RTM_DELETE:
1205 if (!ln)
1206 break;
1207
1208 if ((rt->rt_flags & RTF_ANNOUNCE) != 0 &&
1209 (ifp->if_flags & IFF_MULTICAST) != 0) {
1210 struct in6_addr llsol;
1211 struct in6_multi *in6m;
1212
1213 llsol = SIN6(rt_key(rt))->sin6_addr;
1214 llsol.s6_addr16[0] = htons(0xff02);
1215 llsol.s6_addr16[1] = htons(ifp->if_index);
1216 llsol.s6_addr32[1] = 0;
1217 llsol.s6_addr32[2] = htonl(1);
1218 llsol.s6_addr8[12] = 0xff;
1219
1220 IN6_LOOKUP_MULTI(llsol, ifp, in6m);
1221 if (in6m)
1222 in6_delmulti(in6m);
1223 }
1224 nd6_inuse--;
1225 ln->ln_next->ln_prev = ln->ln_prev;
1226 ln->ln_prev->ln_next = ln->ln_next;
1227 ln->ln_prev = NULL;
1228 nd6_llinfo_settimer(ln, -1);
1229 rt->rt_llinfo = 0;
1230 rt->rt_flags &= ~RTF_LLINFO;
1231 if (ln->ln_hold)
1232 m_freem(ln->ln_hold);
1233 Free((caddr_t)ln);
1234 }
1235 }
1236
1237 int
1238 nd6_ioctl(cmd, data, ifp)
1239 u_long cmd;
1240 caddr_t data;
1241 struct ifnet *ifp;
1242 {
1243 struct in6_drlist *drl = (struct in6_drlist *)data;
1244 struct in6_oprlist *oprl = (struct in6_oprlist *)data;
1245 struct in6_ndireq *ndi = (struct in6_ndireq *)data;
1246 struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
1247 struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
1248 struct nd_defrouter *dr;
1249 struct nd_prefix *pr;
1250 struct rtentry *rt;
1251 int i = 0, error = 0;
1252 int s;
1253
1254 switch (cmd) {
1255 case SIOCGDRLST_IN6:
1256
1257
1258
1259 bzero(drl, sizeof(*drl));
1260 s = splsoftnet();
1261 dr = TAILQ_FIRST(&nd_defrouter);
1262 while (dr && i < DRLSTSIZ) {
1263 drl->defrouter[i].rtaddr = dr->rtaddr;
1264 if (IN6_IS_ADDR_LINKLOCAL(&drl->defrouter[i].rtaddr)) {
1265
1266 drl->defrouter[i].rtaddr.s6_addr16[1] = 0;
1267 } else
1268 log(LOG_ERR,
1269 "default router list contains a "
1270 "non-linklocal address(%s)\n",
1271 ip6_sprintf(&drl->defrouter[i].rtaddr));
1272
1273 drl->defrouter[i].flags = dr->flags;
1274 drl->defrouter[i].rtlifetime = dr->rtlifetime;
1275 drl->defrouter[i].expire = dr->expire;
1276 drl->defrouter[i].if_index = dr->ifp->if_index;
1277 i++;
1278 dr = TAILQ_NEXT(dr, dr_entry);
1279 }
1280 splx(s);
1281 break;
1282 case SIOCGPRLST_IN6:
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295 bzero(oprl, sizeof(*oprl));
1296 s = splsoftnet();
1297 pr = LIST_FIRST(&nd_prefix);
1298 while (pr && i < PRLSTSIZ) {
1299 struct nd_pfxrouter *pfr;
1300 int j;
1301
1302 oprl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
1303 oprl->prefix[i].raflags = pr->ndpr_raf;
1304 oprl->prefix[i].prefixlen = pr->ndpr_plen;
1305 oprl->prefix[i].vltime = pr->ndpr_vltime;
1306 oprl->prefix[i].pltime = pr->ndpr_pltime;
1307 oprl->prefix[i].if_index = pr->ndpr_ifp->if_index;
1308 oprl->prefix[i].expire = pr->ndpr_expire;
1309
1310 pfr = LIST_FIRST(&pr->ndpr_advrtrs);
1311 j = 0;
1312 while(pfr) {
1313 if (j < DRLSTSIZ) {
1314 #define RTRADDR oprl->prefix[i].advrtr[j]
1315 RTRADDR = pfr->router->rtaddr;
1316 if (IN6_IS_ADDR_LINKLOCAL(&RTRADDR)) {
1317
1318 RTRADDR.s6_addr16[1] = 0;
1319 } else
1320 log(LOG_ERR,
1321 "a router(%s) advertises "
1322 "a prefix with "
1323 "non-link local address\n",
1324 ip6_sprintf(&RTRADDR));
1325 #undef RTRADDR
1326 }
1327 j++;
1328 pfr = LIST_NEXT(pfr, pfr_entry);
1329 }
1330 oprl->prefix[i].advrtrs = j;
1331 oprl->prefix[i].origin = PR_ORIG_RA;
1332
1333 i++;
1334 pr = LIST_NEXT(pr, ndpr_entry);
1335 }
1336 splx(s);
1337
1338 break;
1339 case OSIOCGIFINFO_IN6:
1340
1341 bzero(&ndi->ndi, sizeof(ndi->ndi));
1342 ndi->ndi.linkmtu = IN6_LINKMTU(ifp);
1343 ndi->ndi.maxmtu = ND_IFINFO(ifp)->maxmtu;
1344 ndi->ndi.basereachable = ND_IFINFO(ifp)->basereachable;
1345 ndi->ndi.reachable = ND_IFINFO(ifp)->reachable;
1346 ndi->ndi.retrans = ND_IFINFO(ifp)->retrans;
1347 ndi->ndi.flags = ND_IFINFO(ifp)->flags;
1348 ndi->ndi.recalctm = ND_IFINFO(ifp)->recalctm;
1349 ndi->ndi.chlim = ND_IFINFO(ifp)->chlim;
1350 break;
1351 case SIOCGIFINFO_IN6:
1352 ndi->ndi = *ND_IFINFO(ifp);
1353 break;
1354 case SIOCSIFINFO_FLAGS:
1355 ND_IFINFO(ifp)->flags = ndi->ndi.flags;
1356 break;
1357 case SIOCSNDFLUSH_IN6:
1358
1359 defrouter_reset();
1360 defrouter_select();
1361 break;
1362 case SIOCSPFXFLUSH_IN6:
1363 {
1364
1365 struct nd_prefix *pr, *next;
1366
1367 s = splsoftnet();
1368 for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) {
1369 struct in6_ifaddr *ia, *ia_next;
1370
1371 next = LIST_NEXT(pr, ndpr_entry);
1372
1373 if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1374 continue;
1375
1376
1377 for (ia = in6_ifaddr; ia; ia = ia_next) {
1378
1379 ia_next = ia->ia_next;
1380
1381 if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
1382 continue;
1383
1384 if (ia->ia6_ndpr == pr)
1385 in6_purgeaddr(&ia->ia_ifa);
1386 }
1387 prelist_remove(pr);
1388 }
1389 splx(s);
1390 break;
1391 }
1392 case SIOCSRTRFLUSH_IN6:
1393 {
1394
1395 struct nd_defrouter *dr, *next;
1396
1397 s = splsoftnet();
1398 defrouter_reset();
1399 for (dr = TAILQ_FIRST(&nd_defrouter); dr; dr = next) {
1400 next = TAILQ_NEXT(dr, dr_entry);
1401 defrtrlist_del(dr);
1402 }
1403 defrouter_select();
1404 splx(s);
1405 break;
1406 }
1407 case SIOCGNBRINFO_IN6:
1408 {
1409 struct llinfo_nd6 *ln;
1410 struct in6_addr nb_addr = nbi->addr;
1411
1412
1413
1414
1415
1416 if (IN6_IS_ADDR_LINKLOCAL(&nbi->addr) ||
1417 IN6_IS_ADDR_MC_LINKLOCAL(&nbi->addr)) {
1418 u_int16_t *idp = (u_int16_t *)&nb_addr.s6_addr[2];
1419
1420 if (*idp == 0)
1421 *idp = htons(ifp->if_index);
1422 }
1423
1424 s = splsoftnet();
1425 if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL ||
1426 (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) {
1427 error = EINVAL;
1428 splx(s);
1429 break;
1430 }
1431 nbi->state = ln->ln_state;
1432 nbi->asked = ln->ln_asked;
1433 nbi->isrouter = ln->ln_router;
1434 nbi->expire = ln->ln_expire;
1435 splx(s);
1436
1437 break;
1438 }
1439 case SIOCGDEFIFACE_IN6:
1440 ndif->ifindex = nd6_defifindex;
1441 break;
1442 case SIOCSDEFIFACE_IN6:
1443 return (nd6_setdefaultiface(ndif->ifindex));
1444 break;
1445 }
1446 return (error);
1447 }
1448
1449
1450
1451
1452
1453 struct rtentry *
1454 nd6_cache_lladdr(ifp, from, lladdr, lladdrlen, type, code)
1455 struct ifnet *ifp;
1456 struct in6_addr *from;
1457 char *lladdr;
1458 int lladdrlen;
1459 int type;
1460 int code;
1461 {
1462 struct rtentry *rt = NULL;
1463 struct llinfo_nd6 *ln = NULL;
1464 int is_newentry;
1465 struct sockaddr_dl *sdl = NULL;
1466 int do_update;
1467 int olladdr;
1468 int llchange;
1469 int newstate = 0;
1470
1471 if (!ifp)
1472 panic("ifp == NULL in nd6_cache_lladdr");
1473 if (!from)
1474 panic("from == NULL in nd6_cache_lladdr");
1475
1476
1477 if (IN6_IS_ADDR_UNSPECIFIED(from))
1478 return NULL;
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490 rt = nd6_lookup(from, 0, ifp);
1491 if (!rt) {
1492 #if 0
1493
1494 if (!lladdr || !lladdrlen)
1495 return NULL;
1496 #endif
1497
1498 rt = nd6_lookup(from, 1, ifp);
1499 is_newentry = 1;
1500 } else {
1501
1502 if (rt->rt_flags & RTF_STATIC)
1503 return NULL;
1504 is_newentry = 0;
1505 }
1506
1507 if (!rt)
1508 return NULL;
1509 if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
1510 fail:
1511 (void)nd6_free(rt, 0);
1512 return NULL;
1513 }
1514 ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1515 if (!ln)
1516 goto fail;
1517 if (!rt->rt_gateway)
1518 goto fail;
1519 if (rt->rt_gateway->sa_family != AF_LINK)
1520 goto fail;
1521 sdl = SDL(rt->rt_gateway);
1522
1523 olladdr = (sdl->sdl_alen) ? 1 : 0;
1524 if (olladdr && lladdr) {
1525 if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
1526 llchange = 1;
1527 else
1528 llchange = 0;
1529 } else
1530 llchange = 0;
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 if (lladdr) {
1544
1545
1546
1547
1548 sdl->sdl_alen = ifp->if_addrlen;
1549 bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
1550 }
1551
1552 if (!is_newentry) {
1553 if ((!olladdr && lladdr) ||
1554 (olladdr && lladdr && llchange)) {
1555 do_update = 1;
1556 newstate = ND6_LLINFO_STALE;
1557 } else
1558 do_update = 0;
1559 } else {
1560 do_update = 1;
1561 if (!lladdr)
1562 newstate = ND6_LLINFO_NOSTATE;
1563 else
1564 newstate = ND6_LLINFO_STALE;
1565 }
1566
1567 if (do_update) {
1568
1569
1570
1571 ln->ln_state = newstate;
1572
1573 if (ln->ln_state == ND6_LLINFO_STALE) {
1574
1575
1576
1577
1578
1579
1580 nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1581
1582 if (ln->ln_hold) {
1583
1584
1585
1586
1587 nd6_output(ifp, ifp, ln->ln_hold,
1588 (struct sockaddr_in6 *)rt_key(rt), rt);
1589 ln->ln_hold = NULL;
1590 }
1591 } else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
1592
1593 nd6_llinfo_settimer((void *)ln, 0);
1594 }
1595 }
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626 switch (type & 0xff) {
1627 case ND_NEIGHBOR_SOLICIT:
1628
1629
1630
1631 if (is_newentry)
1632 ln->ln_router = 0;
1633 break;
1634 case ND_REDIRECT:
1635
1636
1637
1638
1639
1640 if (code == ND_REDIRECT_ROUTER)
1641 ln->ln_router = 1;
1642 else if (is_newentry)
1643 ln->ln_router = 0;
1644 break;
1645 case ND_ROUTER_SOLICIT:
1646
1647
1648
1649 ln->ln_router = 0;
1650 break;
1651 case ND_ROUTER_ADVERT:
1652
1653
1654
1655 if ((!is_newentry && (olladdr || lladdr)) ||
1656 (is_newentry && lladdr)) {
1657 ln->ln_router = 1;
1658 }
1659 break;
1660 }
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677 if (do_update && ln->ln_router && !ip6_forwarding && ip6_accept_rtadv)
1678 defrouter_select();
1679
1680 return rt;
1681 }
1682
1683 static void
1684 nd6_slowtimo(ignored_arg)
1685 void *ignored_arg;
1686 {
1687 int s = splsoftnet();
1688 struct nd_ifinfo *nd6if;
1689 struct ifnet *ifp;
1690
1691 timeout_set(&nd6_slowtimo_ch, nd6_slowtimo, NULL);
1692 timeout_add(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz);
1693 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
1694 {
1695 nd6if = ND_IFINFO(ifp);
1696 if (nd6if->basereachable &&
1697 (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
1698
1699
1700
1701
1702
1703
1704 nd6if->recalctm = nd6_recalc_reachtm_interval;
1705 nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable);
1706 }
1707 }
1708 splx(s);
1709 }
1710
1711 #define senderr(e) { error = (e); goto bad;}
1712 int
1713 nd6_output(ifp, origifp, m0, dst, rt0)
1714 struct ifnet *ifp;
1715 struct ifnet *origifp;
1716 struct mbuf *m0;
1717 struct sockaddr_in6 *dst;
1718 struct rtentry *rt0;
1719 {
1720 struct mbuf *m = m0;
1721 struct rtentry *rt = rt0;
1722 struct sockaddr_in6 *gw6 = NULL;
1723 struct llinfo_nd6 *ln = NULL;
1724 int error = 0;
1725 #ifdef IPSEC
1726 struct m_tag *mtag;
1727 #endif
1728
1729 if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
1730 goto sendpkt;
1731
1732 if (nd6_need_cache(ifp) == 0)
1733 goto sendpkt;
1734
1735
1736
1737
1738 if (rt) {
1739 if ((rt->rt_flags & RTF_UP) == 0) {
1740 if ((rt0 = rt = rtalloc1((struct sockaddr *)dst,
1741 1, 0)) != NULL)
1742 {
1743 rt->rt_refcnt--;
1744 if (rt->rt_ifp != ifp)
1745 senderr(EHOSTUNREACH);
1746 } else
1747 senderr(EHOSTUNREACH);
1748 }
1749
1750 if (rt->rt_flags & RTF_GATEWAY) {
1751 gw6 = (struct sockaddr_in6 *)rt->rt_gateway;
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761 if (!nd6_is_addr_neighbor(gw6, ifp) ||
1762 in6ifa_ifpwithaddr(ifp, &gw6->sin6_addr)) {
1763
1764
1765
1766
1767
1768 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
1769 senderr(EHOSTUNREACH);
1770
1771 goto sendpkt;
1772 }
1773
1774 if (rt->rt_gwroute == 0)
1775 goto lookup;
1776 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
1777 rtfree(rt); rt = rt0;
1778 lookup:
1779 rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0);
1780 if ((rt = rt->rt_gwroute) == 0)
1781 senderr(EHOSTUNREACH);
1782 }
1783 }
1784 }
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794 if (rt && (rt->rt_flags & RTF_LLINFO) != 0)
1795 ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1796 else {
1797
1798
1799
1800
1801
1802 if (nd6_is_addr_neighbor(dst, ifp) &&
1803 (rt = nd6_lookup(&dst->sin6_addr, 1, ifp)) != NULL)
1804 ln = (struct llinfo_nd6 *)rt->rt_llinfo;
1805 }
1806 if (!ln || !rt) {
1807 if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
1808 !(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
1809 log(LOG_DEBUG,
1810 "nd6_output: can't allocate llinfo for %s "
1811 "(ln=%p, rt=%p)\n",
1812 ip6_sprintf(&dst->sin6_addr), ln, rt);
1813 senderr(EIO);
1814 }
1815
1816 goto sendpkt;
1817 }
1818
1819
1820 if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
1821 ln->ln_state < ND6_LLINFO_REACHABLE) {
1822 ln->ln_state = ND6_LLINFO_STALE;
1823 nd6_llinfo_settimer(ln, (long)nd6_gctimer * hz);
1824 }
1825
1826
1827
1828
1829
1830
1831
1832
1833 if (ln->ln_state == ND6_LLINFO_STALE) {
1834 ln->ln_asked = 0;
1835 ln->ln_state = ND6_LLINFO_DELAY;
1836 nd6_llinfo_settimer(ln, nd6_delay * hz);
1837 }
1838
1839
1840
1841
1842
1843
1844 if (ln->ln_state > ND6_LLINFO_INCOMPLETE)
1845 goto sendpkt;
1846
1847
1848
1849
1850
1851
1852 if (ln->ln_state == ND6_LLINFO_NOSTATE)
1853 ln->ln_state = ND6_LLINFO_INCOMPLETE;
1854 if (ln->ln_hold)
1855 m_freem(ln->ln_hold);
1856 ln->ln_hold = m;
1857
1858
1859
1860
1861 if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
1862 ln->ln_asked++;
1863 nd6_llinfo_settimer(ln,
1864 (long)ND_IFINFO(ifp)->retrans * hz / 1000);
1865 nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
1866 }
1867 return (0);
1868
1869 sendpkt:
1870 #ifdef IPSEC
1871
1872
1873
1874
1875 mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL);
1876 #endif
1877
1878 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
1879 #ifdef IPSEC
1880 if (mtag != NULL &&
1881 (origifp->if_capabilities & IFCAP_IPSEC) == 0) {
1882
1883 ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
1884 error = EACCES;
1885 goto bad;
1886 }
1887 #endif
1888 return ((*ifp->if_output)(origifp, m, (struct sockaddr *)dst,
1889 rt));
1890 }
1891 #ifdef IPSEC
1892 if (mtag != NULL &&
1893 (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
1894
1895 ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
1896 error = EACCES;
1897 goto bad;
1898 }
1899 #endif
1900 return ((*ifp->if_output)(ifp, m, (struct sockaddr *)dst, rt));
1901
1902 bad:
1903 if (m)
1904 m_freem(m);
1905 return (error);
1906 }
1907 #undef senderr
1908
1909 int
1910 nd6_need_cache(ifp)
1911 struct ifnet *ifp;
1912 {
1913
1914
1915
1916
1917
1918
1919
1920 switch (ifp->if_type) {
1921 case IFT_ETHER:
1922 case IFT_FDDI:
1923 case IFT_IEEE1394:
1924 case IFT_PROPVIRTUAL:
1925 case IFT_L2VLAN:
1926 case IFT_IEEE80211:
1927 case IFT_CARP:
1928 case IFT_GIF:
1929 return (1);
1930 default:
1931 return (0);
1932 }
1933 }
1934
1935 int
1936 nd6_storelladdr(ifp, rt, m, dst, desten)
1937 struct ifnet *ifp;
1938 struct rtentry *rt;
1939 struct mbuf *m;
1940 struct sockaddr *dst;
1941 u_char *desten;
1942 {
1943 struct sockaddr_dl *sdl;
1944
1945 if (m->m_flags & M_MCAST) {
1946 switch (ifp->if_type) {
1947 case IFT_ETHER:
1948 case IFT_FDDI:
1949 ETHER_MAP_IPV6_MULTICAST(&SIN6(dst)->sin6_addr,
1950 desten);
1951 return (1);
1952 break;
1953 default:
1954 m_freem(m);
1955 return (0);
1956 }
1957 }
1958
1959 if (rt == NULL) {
1960
1961 m_freem(m);
1962 return (0);
1963 }
1964 if (rt->rt_gateway->sa_family != AF_LINK) {
1965 printf("nd6_storelladdr: something odd happens\n");
1966 m_freem(m);
1967 return (0);
1968 }
1969 sdl = SDL(rt->rt_gateway);
1970 if (sdl->sdl_alen == 0) {
1971
1972 printf("nd6_storelladdr: sdl_alen == 0, dst=%s, if=%s\n",
1973 ip6_sprintf(&SIN6(dst)->sin6_addr), ifp->if_xname);
1974 m_freem(m);
1975 return (0);
1976 }
1977
1978 bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
1979 return (1);
1980 }
1981
1982 int
1983 nd6_sysctl(name, oldp, oldlenp, newp, newlen)
1984 int name;
1985 void *oldp;
1986 size_t *oldlenp;
1987 void *newp;
1988 size_t newlen;
1989 {
1990 void *p;
1991 size_t ol, l;
1992 int error;
1993
1994 error = 0;
1995 l = 0;
1996
1997 if (newp)
1998 return EPERM;
1999 if (oldp && !oldlenp)
2000 return EINVAL;
2001 ol = oldlenp ? *oldlenp : 0;
2002
2003 if (oldp) {
2004 p = malloc(*oldlenp, M_TEMP, M_WAITOK);
2005 if (!p)
2006 return ENOMEM;
2007 } else
2008 p = NULL;
2009 switch (name) {
2010 case ICMPV6CTL_ND6_DRLIST:
2011 error = fill_drlist(p, oldlenp, ol);
2012 if (!error && p && oldp)
2013 error = copyout(p, oldp, *oldlenp);
2014 break;
2015
2016 case ICMPV6CTL_ND6_PRLIST:
2017 error = fill_prlist(p, oldlenp, ol);
2018 if (!error && p && oldp)
2019 error = copyout(p, oldp, *oldlenp);
2020 break;
2021
2022 default:
2023 error = ENOPROTOOPT;
2024 break;
2025 }
2026 if (p)
2027 free(p, M_TEMP);
2028
2029 return (error);
2030 }
2031
2032 static int
2033 fill_drlist(oldp, oldlenp, ol)
2034 void *oldp;
2035 size_t *oldlenp, ol;
2036 {
2037 int error = 0, s;
2038 struct in6_defrouter *d = NULL, *de = NULL;
2039 struct nd_defrouter *dr;
2040 size_t l;
2041
2042 s = splsoftnet();
2043
2044 if (oldp) {
2045 d = (struct in6_defrouter *)oldp;
2046 de = (struct in6_defrouter *)((caddr_t)oldp + *oldlenp);
2047 }
2048 l = 0;
2049
2050 for (dr = TAILQ_FIRST(&nd_defrouter); dr;
2051 dr = TAILQ_NEXT(dr, dr_entry)) {
2052
2053 if (oldp && d + 1 <= de) {
2054 bzero(d, sizeof(*d));
2055 d->rtaddr.sin6_family = AF_INET6;
2056 d->rtaddr.sin6_len = sizeof(struct sockaddr_in6);
2057 d->rtaddr.sin6_addr = dr->rtaddr;
2058 in6_recoverscope(&d->rtaddr, &d->rtaddr.sin6_addr,
2059 dr->ifp);
2060 d->flags = dr->flags;
2061 d->rtlifetime = dr->rtlifetime;
2062 d->expire = dr->expire;
2063 d->if_index = dr->ifp->if_index;
2064 }
2065
2066 l += sizeof(*d);
2067 if (d)
2068 d++;
2069 }
2070
2071 if (oldp) {
2072 *oldlenp = l;
2073 if (l > ol)
2074 error = ENOMEM;
2075 } else
2076 *oldlenp = l;
2077
2078 splx(s);
2079
2080 return (error);
2081 }
2082
2083 static int
2084 fill_prlist(oldp, oldlenp, ol)
2085 void *oldp;
2086 size_t *oldlenp, ol;
2087 {
2088 int error = 0, s;
2089 struct nd_prefix *pr;
2090 struct in6_prefix *p = NULL;
2091 struct in6_prefix *pe = NULL;
2092 size_t l;
2093
2094 s = splsoftnet();
2095
2096 if (oldp) {
2097 p = (struct in6_prefix *)oldp;
2098 pe = (struct in6_prefix *)((caddr_t)oldp + *oldlenp);
2099 }
2100 l = 0;
2101
2102 LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
2103 u_short advrtrs;
2104 size_t advance;
2105 struct sockaddr_in6 *sin6;
2106 struct sockaddr_in6 *s6;
2107 struct nd_pfxrouter *pfr;
2108
2109 if (oldp && p + 1 <= pe)
2110 {
2111 bzero(p, sizeof(*p));
2112 sin6 = (struct sockaddr_in6 *)(p + 1);
2113
2114 p->prefix = pr->ndpr_prefix;
2115 if (in6_recoverscope(&p->prefix,
2116 &p->prefix.sin6_addr, pr->ndpr_ifp) != 0)
2117 log(LOG_ERR,
2118 "scope error in prefix list (%s)\n",
2119 ip6_sprintf(&p->prefix.sin6_addr));
2120 p->raflags = pr->ndpr_raf;
2121 p->prefixlen = pr->ndpr_plen;
2122 p->vltime = pr->ndpr_vltime;
2123 p->pltime = pr->ndpr_pltime;
2124 p->if_index = pr->ndpr_ifp->if_index;
2125 if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
2126 p->expire = 0;
2127 else {
2128 time_t maxexpire;
2129
2130
2131 maxexpire = (-1) &
2132 ~(1 << ((sizeof(maxexpire) * 8) - 1));
2133 if (pr->ndpr_vltime <
2134 maxexpire - pr->ndpr_lastupdate) {
2135 p->expire = pr->ndpr_lastupdate +
2136 pr->ndpr_vltime;
2137 } else
2138 p->expire = maxexpire;
2139 }
2140 p->refcnt = pr->ndpr_refcnt;
2141 p->flags = pr->ndpr_stateflags;
2142 p->origin = PR_ORIG_RA;
2143 advrtrs = 0;
2144 LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
2145 if ((void *)&sin6[advrtrs + 1] > (void *)pe) {
2146 advrtrs++;
2147 continue;
2148 }
2149 s6 = &sin6[advrtrs];
2150 s6->sin6_family = AF_INET6;
2151 s6->sin6_len = sizeof(struct sockaddr_in6);
2152 s6->sin6_addr = pfr->router->rtaddr;
2153 in6_recoverscope(s6, &pfr->router->rtaddr,
2154 pfr->router->ifp);
2155 advrtrs++;
2156 }
2157 p->advrtrs = advrtrs;
2158 }
2159 else {
2160 advrtrs = 0;
2161 LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
2162 advrtrs++;
2163 }
2164
2165 advance = sizeof(*p) + sizeof(*sin6) * advrtrs;
2166 l += advance;
2167 if (p)
2168 p = (struct in6_prefix *)((caddr_t)p + advance);
2169 }
2170
2171 if (oldp) {
2172 *oldlenp = l;
2173 if (l > ol)
2174 error = ENOMEM;
2175 } else
2176 *oldlenp = l;
2177
2178 splx(s);
2179
2180 return (error);
2181 }