This source file includes following definitions.
- LIST_HEAD
- in6_ifloop_request
- in6_ifaddloop
- in6_ifremloop
- in6_mask2len
- in6_control
- in6_update_ifa
- in6_purgeaddr
- in6_unlink_ifa
- in6_purgeif
- in6_lifaddr_ioctl
- in6_ifinit
- in6_savemkludge
- in6_restoremkludge
- in6_createmkludge
- in6_purgemkludge
- in6_addmulti
- in6_delmulti
- in6_joingroup
- in6_leavegroup
- in6ifa_ifpforlinklocal
- in6ifa_ifpwithaddr
- ip6_sprintf
- in6_addrscope
- in6_addr2scopeid
- in6_is_addr_deprecated
- in6_matchlen
- in6_are_prefix_equal
- in6_prefixlen2mask
- in6_ifawithscope
- in6_ifawithifp
- in6_if_up
- in6if_do_dad
- in6_setmaxmtu
- in6_domifattach
- in6_domifdetach
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 #include <sys/param.h>
65 #include <sys/ioctl.h>
66 #include <sys/errno.h>
67 #include <sys/malloc.h>
68 #include <sys/socket.h>
69 #include <sys/socketvar.h>
70 #include <sys/sockio.h>
71 #include <sys/systm.h>
72 #include <sys/proc.h>
73 #include <sys/time.h>
74 #include <sys/kernel.h>
75 #include <sys/syslog.h>
76
77 #include <net/if.h>
78 #include <net/if_types.h>
79 #include <net/route.h>
80 #include <net/if_dl.h>
81
82 #include <netinet/in.h>
83 #include <netinet/in_var.h>
84 #include <netinet/if_ether.h>
85
86 #include <netinet/ip6.h>
87 #include <netinet6/ip6_var.h>
88 #include <netinet6/nd6.h>
89 #include <netinet6/mld6_var.h>
90 #ifdef MROUTING
91 #include <netinet6/ip6_mroute.h>
92 #endif
93 #include <netinet6/in6_ifattach.h>
94
95
96 #define COMPAT_IN6IFIOCTL
97
98
99
100
101 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
102 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
103 const struct in6_addr in6addr_intfacelocal_allnodes =
104 IN6ADDR_INTFACELOCAL_ALLNODES_INIT;
105 const struct in6_addr in6addr_linklocal_allnodes =
106 IN6ADDR_LINKLOCAL_ALLNODES_INIT;
107 const struct in6_addr in6addr_linklocal_allrouters =
108 IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
109
110 const struct in6_addr in6mask0 = IN6MASK0;
111 const struct in6_addr in6mask32 = IN6MASK32;
112 const struct in6_addr in6mask64 = IN6MASK64;
113 const struct in6_addr in6mask96 = IN6MASK96;
114 const struct in6_addr in6mask128 = IN6MASK128;
115
116 static int in6_lifaddr_ioctl(struct socket *, u_long, caddr_t,
117 struct ifnet *, struct proc *);
118 static int in6_ifinit(struct ifnet *, struct in6_ifaddr *,
119 struct sockaddr_in6 *, int);
120 static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
121
122 const struct sockaddr_in6 sa6_any = {sizeof(sa6_any), AF_INET6,
123 0, 0, IN6ADDR_ANY_INIT, 0};
124
125
126
127
128
129 static LIST_HEAD(, multi6_kludge) in6_mk;
130
131 struct multi6_kludge {
132 LIST_ENTRY(multi6_kludge) mk_entry;
133 struct ifnet *mk_ifp;
134 struct in6_multihead mk_head;
135 };
136
137
138
139
140
141 static void
142 in6_ifloop_request(int cmd, struct ifaddr *ifa)
143 {
144 struct sockaddr_in6 lo_sa;
145 struct sockaddr_in6 all1_sa;
146 struct rtentry *nrt = NULL;
147 int e;
148
149 bzero(&lo_sa, sizeof(lo_sa));
150 bzero(&all1_sa, sizeof(all1_sa));
151 lo_sa.sin6_family = all1_sa.sin6_family = AF_INET6;
152 lo_sa.sin6_len = all1_sa.sin6_len = sizeof(struct sockaddr_in6);
153 lo_sa.sin6_addr = in6addr_loopback;
154 all1_sa.sin6_addr = in6mask128;
155
156
157
158
159
160
161
162
163
164
165 e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
166 (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt, 0);
167 if (e != 0) {
168 log(LOG_ERR, "in6_ifloop_request: "
169 "%s operation failed for %s (errno=%d)\n",
170 cmd == RTM_ADD ? "ADD" : "DELETE",
171 ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr),
172 e);
173 }
174
175
176
177
178
179
180
181
182 if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
183 IFAFREE(nrt->rt_ifa);
184 ifa->ifa_refcnt++;
185 nrt->rt_ifa = ifa;
186 }
187
188
189
190
191
192
193
194 if (nrt) {
195 rt_newaddrmsg(cmd, ifa, e, nrt);
196 if (cmd == RTM_DELETE) {
197 if (nrt->rt_refcnt <= 0) {
198
199 nrt->rt_refcnt++;
200 rtfree(nrt);
201 }
202 } else {
203
204 nrt->rt_refcnt--;
205 }
206 }
207 }
208
209
210
211
212
213
214
215
216 void
217 in6_ifaddloop(struct ifaddr *ifa)
218 {
219 struct rtentry *rt;
220
221
222 rt = rtalloc1(ifa->ifa_addr, 0, 0);
223 if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
224 (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
225 in6_ifloop_request(RTM_ADD, ifa);
226 if (rt)
227 rt->rt_refcnt--;
228 }
229
230
231
232
233
234 void
235 in6_ifremloop(struct ifaddr *ifa)
236 {
237 struct in6_ifaddr *ia;
238 struct rtentry *rt;
239 int ia_count = 0;
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
257 if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
258 ia_count++;
259 if (ia_count > 1)
260 break;
261 }
262 }
263
264 if (ia_count == 1) {
265
266
267
268
269
270
271
272
273 rt = rtalloc1(ifa->ifa_addr, 0, 0);
274 if (rt != NULL && (rt->rt_flags & RTF_HOST) != 0 &&
275 (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
276 rt->rt_refcnt--;
277 in6_ifloop_request(RTM_DELETE, ifa);
278 }
279 }
280 }
281
282 int
283 in6_mask2len(mask, lim0)
284 struct in6_addr *mask;
285 u_char *lim0;
286 {
287 int x = 0, y;
288 u_char *lim = lim0, *p;
289
290
291 if (lim0 == NULL || lim0 - (u_char *)mask > sizeof(*mask))
292 lim = (u_char *)mask + sizeof(*mask);
293 for (p = (u_char *)mask; p < lim; x++, p++) {
294 if (*p != 0xff)
295 break;
296 }
297 y = 0;
298 if (p < lim) {
299 for (y = 0; y < 8; y++) {
300 if ((*p & (0x80 >> y)) == 0)
301 break;
302 }
303 }
304
305
306
307
308
309 if (p < lim) {
310 if (y != 0 && (*p & (0x00ff >> y)) != 0)
311 return (-1);
312 for (p = p + 1; p < lim; p++)
313 if (*p != 0)
314 return (-1);
315 }
316
317 return x * 8 + y;
318 }
319
320 #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
321 #define ia62ifa(ia6) (&((ia6)->ia_ifa))
322
323 int
324 in6_control(so, cmd, data, ifp, p)
325 struct socket *so;
326 u_long cmd;
327 caddr_t data;
328 struct ifnet *ifp;
329 struct proc *p;
330 {
331 struct in6_ifreq *ifr = (struct in6_ifreq *)data;
332 struct in6_ifaddr *ia = NULL;
333 struct in6_aliasreq *ifra = (struct in6_aliasreq *)data;
334 struct sockaddr_in6 *sa6;
335 int privileged;
336
337 privileged = 0;
338 if ((so->so_state & SS_PRIV) != 0)
339 privileged++;
340
341 #ifdef MROUTING
342 switch (cmd) {
343 case SIOCGETSGCNT_IN6:
344 case SIOCGETMIFCNT_IN6:
345 return (mrt6_ioctl(cmd, data));
346 }
347 #endif
348
349 if (ifp == NULL)
350 return (EOPNOTSUPP);
351
352 switch (cmd) {
353 case SIOCSNDFLUSH_IN6:
354 case SIOCSPFXFLUSH_IN6:
355 case SIOCSRTRFLUSH_IN6:
356 case SIOCSDEFIFACE_IN6:
357 case SIOCSIFINFO_FLAGS:
358 if (!privileged)
359 return (EPERM);
360
361 case OSIOCGIFINFO_IN6:
362 case SIOCGIFINFO_IN6:
363 case SIOCGDRLST_IN6:
364 case SIOCGPRLST_IN6:
365 case SIOCGNBRINFO_IN6:
366 case SIOCGDEFIFACE_IN6:
367 return (nd6_ioctl(cmd, data, ifp));
368 }
369
370 switch (cmd) {
371 case SIOCSIFPREFIX_IN6:
372 case SIOCDIFPREFIX_IN6:
373 case SIOCAIFPREFIX_IN6:
374 case SIOCCIFPREFIX_IN6:
375 case SIOCSGIFPREFIX_IN6:
376 case SIOCGIFPREFIX_IN6:
377 log(LOG_NOTICE,
378 "prefix ioctls are now invalidated. "
379 "please use ifconfig.\n");
380 return (EOPNOTSUPP);
381 }
382
383 switch (cmd) {
384 case SIOCALIFADDR:
385 case SIOCDLIFADDR:
386 if (!privileged)
387 return (EPERM);
388
389 case SIOCGLIFADDR:
390 return in6_lifaddr_ioctl(so, cmd, data, ifp, p);
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404
405 switch (cmd) {
406 case SIOCAIFADDR_IN6:
407 case SIOCSIFPHYADDR_IN6:
408 sa6 = &ifra->ifra_addr;
409 break;
410 case SIOCSIFADDR_IN6:
411 case SIOCGIFADDR_IN6:
412 case SIOCSIFDSTADDR_IN6:
413 case SIOCSIFNETMASK_IN6:
414 case SIOCGIFDSTADDR_IN6:
415 case SIOCGIFNETMASK_IN6:
416 case SIOCDIFADDR_IN6:
417 case SIOCGIFPSRCADDR_IN6:
418 case SIOCGIFPDSTADDR_IN6:
419 case SIOCGIFAFLAG_IN6:
420 case SIOCSNDFLUSH_IN6:
421 case SIOCSPFXFLUSH_IN6:
422 case SIOCSRTRFLUSH_IN6:
423 case SIOCGIFALIFETIME_IN6:
424 case SIOCSIFALIFETIME_IN6:
425 case SIOCGIFSTAT_IN6:
426 case SIOCGIFSTAT_ICMP6:
427 sa6 = &ifr->ifr_addr;
428 break;
429 default:
430 sa6 = NULL;
431 break;
432 }
433 if (sa6 && sa6->sin6_family == AF_INET6) {
434 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
435 if (sa6->sin6_addr.s6_addr16[1] == 0) {
436
437 sa6->sin6_addr.s6_addr16[1] =
438 htons(ifp->if_index);
439 } else if (sa6->sin6_addr.s6_addr16[1] !=
440 htons(ifp->if_index)) {
441 return (EINVAL);
442 }
443 if (sa6->sin6_scope_id) {
444 if (sa6->sin6_scope_id !=
445 (u_int32_t)ifp->if_index)
446 return (EINVAL);
447 sa6->sin6_scope_id = 0;
448 }
449 }
450 ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
451 } else
452 ia = NULL;
453
454 switch (cmd) {
455 case SIOCSIFADDR_IN6:
456 case SIOCSIFDSTADDR_IN6:
457 case SIOCSIFNETMASK_IN6:
458
459
460
461
462 return (EINVAL);
463
464 case SIOCDIFADDR_IN6:
465
466
467
468
469
470
471
472 if (ia == NULL)
473 return (EADDRNOTAVAIL);
474
475 case SIOCAIFADDR_IN6:
476
477
478
479
480 if (ifra->ifra_addr.sin6_family != AF_INET6 ||
481 ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
482 return (EAFNOSUPPORT);
483 if (!privileged)
484 return (EPERM);
485
486 break;
487
488 case SIOCGIFADDR_IN6:
489
490
491 case SIOCGIFAFLAG_IN6:
492 case SIOCGIFNETMASK_IN6:
493 case SIOCGIFDSTADDR_IN6:
494 case SIOCGIFALIFETIME_IN6:
495
496 if (ia == NULL)
497 return (EADDRNOTAVAIL);
498 break;
499 case SIOCSIFALIFETIME_IN6:
500 {
501 struct in6_addrlifetime *lt;
502
503 if (!privileged)
504 return (EPERM);
505 if (ia == NULL)
506 return (EADDRNOTAVAIL);
507
508 lt = &ifr->ifr_ifru.ifru_lifetime;
509 if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
510 && lt->ia6t_vltime + time_second < time_second) {
511 return EINVAL;
512 }
513 if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
514 && lt->ia6t_pltime + time_second < time_second) {
515 return EINVAL;
516 }
517 break;
518 }
519 }
520
521 switch (cmd) {
522
523 case SIOCGIFADDR_IN6:
524 ifr->ifr_addr = ia->ia_addr;
525 break;
526
527 case SIOCGIFDSTADDR_IN6:
528 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
529 return (EINVAL);
530
531
532
533
534 ifr->ifr_dstaddr = ia->ia_dstaddr;
535 break;
536
537 case SIOCGIFNETMASK_IN6:
538 ifr->ifr_addr = ia->ia_prefixmask;
539 break;
540
541 case SIOCGIFAFLAG_IN6:
542 ifr->ifr_ifru.ifru_flags6 = ia->ia6_flags;
543 break;
544
545 case SIOCGIFSTAT_IN6:
546 if (ifp == NULL)
547 return EINVAL;
548 bzero(&ifr->ifr_ifru.ifru_stat,
549 sizeof(ifr->ifr_ifru.ifru_stat));
550 ifr->ifr_ifru.ifru_stat =
551 *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
552 break;
553
554 case SIOCGIFSTAT_ICMP6:
555 if (ifp == NULL)
556 return EINVAL;
557 bzero(&ifr->ifr_ifru.ifru_icmp6stat,
558 sizeof(ifr->ifr_ifru.ifru_icmp6stat));
559 ifr->ifr_ifru.ifru_icmp6stat =
560 *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
561 break;
562
563 case SIOCGIFALIFETIME_IN6:
564 ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime;
565 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
566 time_t maxexpire;
567 struct in6_addrlifetime *retlt =
568 &ifr->ifr_ifru.ifru_lifetime;
569
570
571
572
573
574 maxexpire = (-1) &
575 ~(1 << ((sizeof(maxexpire) * 8) - 1));
576 if (ia->ia6_lifetime.ia6t_vltime <
577 maxexpire - ia->ia6_updatetime) {
578 retlt->ia6t_expire = ia->ia6_updatetime +
579 ia->ia6_lifetime.ia6t_vltime;
580 } else
581 retlt->ia6t_expire = maxexpire;
582 }
583 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
584 time_t maxexpire;
585 struct in6_addrlifetime *retlt =
586 &ifr->ifr_ifru.ifru_lifetime;
587
588
589
590
591
592 maxexpire = (-1) &
593 ~(1 << ((sizeof(maxexpire) * 8) - 1));
594 if (ia->ia6_lifetime.ia6t_pltime <
595 maxexpire - ia->ia6_updatetime) {
596 retlt->ia6t_preferred = ia->ia6_updatetime +
597 ia->ia6_lifetime.ia6t_pltime;
598 } else
599 retlt->ia6t_preferred = maxexpire;
600 }
601 break;
602
603 case SIOCSIFALIFETIME_IN6:
604 ia->ia6_lifetime = ifr->ifr_ifru.ifru_lifetime;
605
606 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
607 ia->ia6_lifetime.ia6t_expire =
608 time_second + ia->ia6_lifetime.ia6t_vltime;
609 } else
610 ia->ia6_lifetime.ia6t_expire = 0;
611 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
612 ia->ia6_lifetime.ia6t_preferred =
613 time_second + ia->ia6_lifetime.ia6t_pltime;
614 } else
615 ia->ia6_lifetime.ia6t_preferred = 0;
616 break;
617
618 case SIOCAIFADDR_IN6:
619 {
620 int i, error = 0;
621 struct nd_prefix pr0, *pr;
622
623
624 if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
625 (ifra->ifra_flags & IN6_IFF_DETACHED) != 0 ||
626 (ifra->ifra_flags & IN6_IFF_NODAD) != 0 ||
627 (ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0) {
628 return (EINVAL);
629 }
630
631
632
633
634 if ((error = in6_update_ifa(ifp, ifra, ia)) != 0)
635 return (error);
636 if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
637 == NULL) {
638
639
640
641
642 break;
643 }
644
645
646
647
648
649
650
651
652
653
654
655
656 bzero(&pr0, sizeof(pr0));
657 pr0.ndpr_ifp = ifp;
658 pr0.ndpr_plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
659 NULL);
660 if (pr0.ndpr_plen == 128) {
661 break;
662 }
663 pr0.ndpr_prefix = ifra->ifra_addr;
664 pr0.ndpr_mask = ifra->ifra_prefixmask.sin6_addr;
665
666 for (i = 0; i < 4; i++) {
667 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
668 ifra->ifra_prefixmask.sin6_addr.s6_addr32[i];
669 }
670
671
672
673
674
675
676
677 pr0.ndpr_raf_onlink = 1;
678 pr0.ndpr_raf_auto =
679 ((ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0);
680 pr0.ndpr_vltime = ifra->ifra_lifetime.ia6t_vltime;
681 pr0.ndpr_pltime = ifra->ifra_lifetime.ia6t_pltime;
682
683
684 if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
685
686
687
688
689 if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
690 return (error);
691 if (pr == NULL) {
692 log(LOG_ERR, "nd6_prelist_add succeeded but "
693 "no prefix\n");
694 return (EINVAL);
695 }
696 }
697
698
699 if (ia->ia6_ndpr == NULL) {
700 ia->ia6_ndpr = pr;
701 pr->ndpr_refcnt++;
702 }
703
704
705
706
707
708 pfxlist_onlink_check();
709
710 dohooks(ifp->if_addrhooks, 0);
711 break;
712 }
713
714 case SIOCDIFADDR_IN6:
715 {
716 int i = 0, purgeprefix = 0;
717 struct nd_prefix pr0, *pr = NULL;
718
719
720
721
722
723
724
725
726
727
728 bzero(&pr0, sizeof(pr0));
729 pr0.ndpr_ifp = ifp;
730 pr0.ndpr_plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr,
731 NULL);
732 if (pr0.ndpr_plen == 128)
733 goto purgeaddr;
734 pr0.ndpr_prefix = ia->ia_addr;
735 pr0.ndpr_mask = ia->ia_prefixmask.sin6_addr;
736 for (i = 0; i < 4; i++) {
737 pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
738 ia->ia_prefixmask.sin6_addr.s6_addr32[i];
739 }
740 if ((pr = nd6_prefix_lookup(&pr0)) != NULL &&
741 pr == ia->ia6_ndpr) {
742 pr->ndpr_refcnt--;
743 if (pr->ndpr_refcnt == 0)
744 purgeprefix = 1;
745 }
746
747 purgeaddr:
748 in6_purgeaddr(&ia->ia_ifa);
749 if (pr && purgeprefix)
750 prelist_remove(pr);
751 dohooks(ifp->if_addrhooks, 0);
752 break;
753 }
754
755 default:
756 if (ifp == NULL || ifp->if_ioctl == 0)
757 return (EOPNOTSUPP);
758 return ((*ifp->if_ioctl)(ifp, cmd, data));
759 }
760
761 return (0);
762 }
763
764
765
766
767
768
769
770 int
771 in6_update_ifa(ifp, ifra, ia)
772 struct ifnet *ifp;
773 struct in6_aliasreq *ifra;
774 struct in6_ifaddr *ia;
775 {
776 int error = 0, hostIsNew = 0, plen = -1;
777 struct in6_ifaddr *oia;
778 struct sockaddr_in6 dst6;
779 struct in6_addrlifetime *lt;
780 struct in6_multi_mship *imm;
781 struct rtentry *rt;
782
783
784 if (ifp == NULL || ifra == NULL)
785 return (EINVAL);
786
787
788
789
790
791 if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
792 ifra->ifra_dstaddr.sin6_family != AF_INET6 &&
793 ifra->ifra_dstaddr.sin6_family != AF_UNSPEC)
794 return (EAFNOSUPPORT);
795
796
797
798
799 if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6))
800 return (EINVAL);
801
802
803
804
805
806
807 if (ia == NULL && ifra->ifra_prefixmask.sin6_len == 0)
808 return (EINVAL);
809 if (ifra->ifra_prefixmask.sin6_len != 0) {
810 plen = in6_mask2len(&ifra->ifra_prefixmask.sin6_addr,
811 (u_char *)&ifra->ifra_prefixmask +
812 ifra->ifra_prefixmask.sin6_len);
813 if (plen <= 0)
814 return (EINVAL);
815 } else {
816
817
818
819
820 plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
821 }
822
823
824
825
826
827 dst6 = ifra->ifra_dstaddr;
828 if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) != 0 &&
829 (dst6.sin6_family == AF_INET6)) {
830
831 if (IN6_IS_ADDR_LINKLOCAL(&dst6.sin6_addr)) {
832 if (dst6.sin6_addr.s6_addr16[1] == 0) {
833
834
835
836
837 dst6.sin6_addr.s6_addr16[1] =
838 htons(ifp->if_index);
839 } else if (dst6.sin6_addr.s6_addr16[1] !=
840 htons(ifp->if_index)) {
841 return (EINVAL);
842 }
843 }
844 }
845
846
847
848
849
850 if (ifra->ifra_dstaddr.sin6_family == AF_INET6) {
851 #ifdef FORCE_P2PPLEN
852 int i;
853 #endif
854
855 if ((ifp->if_flags & (IFF_POINTOPOINT|IFF_LOOPBACK)) == 0) {
856
857 nd6log((LOG_INFO, "in6_update_ifa: a destination can "
858 "be specified for a p2p or a loopback IF only\n"));
859 return (EINVAL);
860 }
861 if (plen != 128) {
862 nd6log((LOG_INFO, "in6_update_ifa: prefixlen should "
863 "be 128 when dstaddr is specified\n"));
864 #ifdef FORCE_P2PPLEN
865
866
867
868
869
870
871 ifra->ifra_prefixmask.sin6_len =
872 sizeof(struct sockaddr_in6);
873 for (i = 0; i < 4; i++)
874 ifra->ifra_prefixmask.sin6_addr.s6_addr32[i] =
875 0xffffffff;
876 plen = 128;
877 #else
878 return (EINVAL);
879 #endif
880 }
881 }
882
883 lt = &ifra->ifra_lifetime;
884 if (lt->ia6t_pltime > lt->ia6t_vltime)
885 return (EINVAL);
886 if (lt->ia6t_vltime == 0) {
887
888
889
890
891 nd6log((LOG_INFO,
892 "in6_update_ifa: valid lifetime is 0 for %s\n",
893 ip6_sprintf(&ifra->ifra_addr.sin6_addr)));
894
895 if (ia == NULL)
896 return (0);
897 }
898
899
900
901
902
903 if (ia == NULL) {
904 hostIsNew = 1;
905
906
907
908
909
910 ia = (struct in6_ifaddr *) malloc(sizeof(*ia), M_IFADDR,
911 M_NOWAIT);
912 if (ia == NULL)
913 return (ENOBUFS);
914 bzero((caddr_t)ia, sizeof(*ia));
915 LIST_INIT(&ia->ia6_memberships);
916
917 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
918 ia->ia_addr.sin6_family = AF_INET6;
919 ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
920 ia->ia6_createtime = ia->ia6_updatetime = time_second;
921 if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
922
923
924
925
926 ia->ia_ifa.ifa_dstaddr =
927 (struct sockaddr *)&ia->ia_dstaddr;
928 } else {
929 ia->ia_ifa.ifa_dstaddr = NULL;
930 }
931 ia->ia_ifa.ifa_netmask =
932 (struct sockaddr *)&ia->ia_prefixmask;
933
934 ia->ia_ifp = ifp;
935 if ((oia = in6_ifaddr) != NULL) {
936 for ( ; oia->ia_next; oia = oia->ia_next)
937 continue;
938 oia->ia_next = ia;
939 } else
940 in6_ifaddr = ia;
941 TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
942 ifa_list);
943 }
944
945
946 if (ifra->ifra_prefixmask.sin6_len) {
947
948
949
950
951
952
953 if (ia->ia_prefixmask.sin6_len &&
954 in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) {
955 nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an"
956 " existing (%s) address should not be changed\n",
957 ip6_sprintf(&ia->ia_addr.sin6_addr)));
958 error = EINVAL;
959 goto unlink;
960 }
961 ia->ia_prefixmask = ifra->ifra_prefixmask;
962 }
963
964
965
966
967
968
969 if (dst6.sin6_family == AF_INET6 &&
970 !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) {
971 int e;
972
973 if ((ia->ia_flags & IFA_ROUTE) != 0 &&
974 (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) {
975 nd6log((LOG_ERR, "in6_update_ifa: failed to remove "
976 "a route to the old destination: %s\n",
977 ip6_sprintf(&ia->ia_addr.sin6_addr)));
978
979 } else
980 ia->ia_flags &= ~IFA_ROUTE;
981 ia->ia_dstaddr = dst6;
982 }
983
984
985
986
987
988
989 ia->ia6_lifetime = ifra->ifra_lifetime;
990 if (ia->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME) {
991 ia->ia6_lifetime.ia6t_expire =
992 time_second + ia->ia6_lifetime.ia6t_vltime;
993 } else
994 ia->ia6_lifetime.ia6t_expire = 0;
995 if (ia->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME) {
996 ia->ia6_lifetime.ia6t_preferred =
997 time_second + ia->ia6_lifetime.ia6t_pltime;
998 } else
999 ia->ia6_lifetime.ia6t_preferred = 0;
1000
1001
1002 if ((error = in6_ifinit(ifp, ia, &ifra->ifra_addr, hostIsNew)) != 0)
1003 goto unlink;
1004
1005
1006
1007
1008 ia->ia6_flags = ifra->ifra_flags;
1009
1010
1011
1012
1013 if ((ifra->ifra_flags & IN6_IFF_DEPRECATED) != 0) {
1014 ia->ia6_lifetime.ia6t_pltime = 0;
1015 ia->ia6_lifetime.ia6t_preferred = time_second;
1016 }
1017
1018
1019
1020
1021
1022 ia->ia6_flags &= ~IN6_IFF_DUPLICATED;
1023 if (hostIsNew && in6if_do_dad(ifp))
1024 ia->ia6_flags |= IN6_IFF_TENTATIVE;
1025
1026
1027
1028
1029 if (!hostIsNew)
1030 return (error);
1031
1032
1033
1034
1035
1036
1037
1038 if ((ifp->if_flags & IFF_MULTICAST) != 0) {
1039 struct sockaddr_in6 mltaddr, mltmask;
1040
1041
1042 struct sockaddr_in6 llsol;
1043
1044 bzero(&llsol, sizeof(llsol));
1045 llsol.sin6_family = AF_INET6;
1046 llsol.sin6_len = sizeof(llsol);
1047 llsol.sin6_addr.s6_addr16[0] = htons(0xff02);
1048 llsol.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1049 llsol.sin6_addr.s6_addr32[1] = 0;
1050 llsol.sin6_addr.s6_addr32[2] = htonl(1);
1051 llsol.sin6_addr.s6_addr32[3] =
1052 ifra->ifra_addr.sin6_addr.s6_addr32[3];
1053 llsol.sin6_addr.s6_addr8[12] = 0xff;
1054 imm = in6_joingroup(ifp, &llsol.sin6_addr, &error);
1055 if (!imm) {
1056 nd6log((LOG_ERR, "in6_update_ifa: "
1057 "addmulti failed for %s on %s (errno=%d)\n",
1058 ip6_sprintf(&llsol.sin6_addr),
1059 ifp->if_xname, error));
1060 goto cleanup;
1061 }
1062 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
1063
1064 bzero(&mltmask, sizeof(mltmask));
1065 mltmask.sin6_len = sizeof(struct sockaddr_in6);
1066 mltmask.sin6_family = AF_INET6;
1067 mltmask.sin6_addr = in6mask32;
1068
1069
1070
1071
1072 bzero(&mltaddr, sizeof(mltaddr));
1073 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
1074 mltaddr.sin6_family = AF_INET6;
1075 mltaddr.sin6_addr = in6addr_linklocal_allnodes;
1076 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1077 mltaddr.sin6_scope_id = 0;
1078
1079
1080
1081
1082
1083
1084
1085 rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0);
1086 if (rt) {
1087
1088
1089
1090 if (memcmp(&mltaddr.sin6_addr,
1091 &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1092 32 / 8)) {
1093 RTFREE(rt);
1094 rt = NULL;
1095 }
1096 }
1097 if (!rt) {
1098 struct rt_addrinfo info;
1099
1100 bzero(&info, sizeof(info));
1101 info.rti_info[RTAX_DST] = (struct sockaddr *)&mltaddr;
1102 info.rti_info[RTAX_GATEWAY] =
1103 (struct sockaddr *)&ia->ia_addr;
1104 info.rti_info[RTAX_NETMASK] =
1105 (struct sockaddr *)&mltmask;
1106 info.rti_info[RTAX_IFA] =
1107 (struct sockaddr *)&ia->ia_addr;
1108
1109 info.rti_flags = RTF_UP | RTF_CLONING;
1110 error = rtrequest1(RTM_ADD, &info, NULL, 0);
1111 if (error)
1112 goto cleanup;
1113 } else {
1114 RTFREE(rt);
1115 }
1116 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
1117 if (!imm) {
1118 nd6log((LOG_WARNING,
1119 "in6_update_ifa: addmulti failed for "
1120 "%s on %s (errno=%d)\n",
1121 ip6_sprintf(&mltaddr.sin6_addr),
1122 ifp->if_xname, error));
1123 goto cleanup;
1124 }
1125 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
1126
1127
1128
1129
1130 if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) == 0) {
1131 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
1132 if (!imm) {
1133 nd6log((LOG_WARNING, "in6_update_ifa: "
1134 "addmulti failed for %s on %s (errno=%d)\n",
1135 ip6_sprintf(&mltaddr.sin6_addr),
1136 ifp->if_xname, error));
1137
1138 } else {
1139 LIST_INSERT_HEAD(&ia->ia6_memberships,
1140 imm, i6mm_chain);
1141 }
1142 }
1143
1144
1145
1146
1147
1148 bzero(&mltaddr.sin6_addr, sizeof(mltaddr.sin6_addr));
1149 mltaddr.sin6_len = sizeof(struct sockaddr_in6);
1150 mltaddr.sin6_family = AF_INET6;
1151 mltaddr.sin6_addr = in6addr_intfacelocal_allnodes;
1152 mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1153 mltaddr.sin6_scope_id = 0;
1154
1155
1156 rt = rtalloc1((struct sockaddr *)&mltaddr, 0, 0);
1157 if (rt) {
1158
1159 if (memcmp(&mltaddr.sin6_addr,
1160 &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
1161 32 / 8)) {
1162 RTFREE(rt);
1163 rt = NULL;
1164 }
1165 }
1166 if (!rt) {
1167 struct rt_addrinfo info;
1168
1169 bzero(&info, sizeof(info));
1170 info.rti_info[RTAX_DST] = (struct sockaddr *)&mltaddr;
1171 info.rti_info[RTAX_GATEWAY] =
1172 (struct sockaddr *)&ia->ia_addr;
1173 info.rti_info[RTAX_NETMASK] =
1174 (struct sockaddr *)&mltmask;
1175 info.rti_info[RTAX_IFA] =
1176 (struct sockaddr *)&ia->ia_addr;
1177 info.rti_flags = RTF_UP | RTF_CLONING;
1178 error = rtrequest1(RTM_ADD, &info, NULL, 0);
1179 if (error)
1180 goto cleanup;
1181 } else {
1182 RTFREE(rt);
1183 }
1184 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
1185 if (!imm) {
1186 nd6log((LOG_WARNING, "in6_update_ifa: "
1187 "addmulti failed for %s on %s (errno=%d)\n",
1188 ip6_sprintf(&mltaddr.sin6_addr),
1189 ifp->if_xname, error));
1190 goto cleanup;
1191 }
1192 LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
1193 }
1194
1195
1196
1197
1198
1199
1200 if (hostIsNew && in6if_do_dad(ifp) &&
1201 (ifra->ifra_flags & IN6_IFF_NODAD) == 0)
1202 {
1203 nd6_dad_start((struct ifaddr *)ia, NULL);
1204 }
1205
1206 return (error);
1207
1208 unlink:
1209
1210
1211
1212
1213 if (hostIsNew)
1214 in6_unlink_ifa(ia, ifp);
1215 return (error);
1216
1217 cleanup:
1218 in6_purgeaddr(&ia->ia_ifa);
1219 return error;
1220 }
1221
1222 void
1223 in6_purgeaddr(ifa)
1224 struct ifaddr *ifa;
1225 {
1226 struct ifnet *ifp = ifa->ifa_ifp;
1227 struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
1228 struct in6_multi_mship *imm;
1229
1230
1231 nd6_dad_stop(ifa);
1232
1233
1234
1235
1236
1237 if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
1238 int e;
1239
1240 if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
1241 != 0) {
1242 log(LOG_ERR, "in6_purgeaddr: failed to remove "
1243 "a route to the p2p destination: %s on %s, "
1244 "errno=%d\n",
1245 ip6_sprintf(&ia->ia_addr.sin6_addr), ifp->if_xname,
1246 e);
1247
1248 } else
1249 ia->ia_flags &= ~IFA_ROUTE;
1250 }
1251
1252
1253 in6_ifremloop(&(ia->ia_ifa));
1254
1255
1256
1257
1258 while (!LIST_EMPTY(&ia->ia6_memberships)) {
1259 imm = LIST_FIRST(&ia->ia6_memberships);
1260 LIST_REMOVE(imm, i6mm_chain);
1261 in6_leavegroup(imm);
1262 }
1263
1264 in6_unlink_ifa(ia, ifp);
1265 }
1266
1267 static void
1268 in6_unlink_ifa(ia, ifp)
1269 struct in6_ifaddr *ia;
1270 struct ifnet *ifp;
1271 {
1272 struct in6_ifaddr *oia;
1273 int s = splnet();
1274
1275 TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
1276
1277 oia = ia;
1278 if (oia == (ia = in6_ifaddr))
1279 in6_ifaddr = ia->ia_next;
1280 else {
1281 while (ia->ia_next && (ia->ia_next != oia))
1282 ia = ia->ia_next;
1283 if (ia->ia_next)
1284 ia->ia_next = oia->ia_next;
1285 else {
1286
1287 printf("Couldn't unlink in6_ifaddr from in6_ifaddr\n");
1288 }
1289 }
1290
1291 if (!LIST_EMPTY(&oia->ia6_multiaddrs)) {
1292 in6_savemkludge(oia);
1293 }
1294
1295
1296
1297
1298
1299
1300
1301 if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
1302 if (oia->ia6_ndpr == NULL) {
1303 log(LOG_NOTICE, "in6_unlink_ifa: autoconf'ed address "
1304 "%p has no prefix\n", oia);
1305 } else {
1306 oia->ia6_ndpr->ndpr_refcnt--;
1307 oia->ia6_flags &= ~IN6_IFF_AUTOCONF;
1308 oia->ia6_ndpr = NULL;
1309 }
1310
1311 pfxlist_onlink_check();
1312 }
1313
1314
1315
1316
1317
1318 IFAFREE(&oia->ia_ifa);
1319
1320 splx(s);
1321 }
1322
1323 void
1324 in6_purgeif(ifp)
1325 struct ifnet *ifp;
1326 {
1327 struct ifaddr *ifa, *nifa;
1328
1329 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa)
1330 {
1331 nifa = TAILQ_NEXT(ifa, ifa_list);
1332 if (ifa->ifa_addr->sa_family != AF_INET6)
1333 continue;
1334 in6_purgeaddr(ifa);
1335 }
1336
1337 in6_ifdetach(ifp);
1338 }
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363 static int
1364 in6_lifaddr_ioctl(so, cmd, data, ifp, p)
1365 struct socket *so;
1366 u_long cmd;
1367 caddr_t data;
1368 struct ifnet *ifp;
1369 struct proc *p;
1370 {
1371 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
1372 struct ifaddr *ifa;
1373 struct sockaddr *sa;
1374
1375
1376 if (!data || !ifp) {
1377 panic("invalid argument to in6_lifaddr_ioctl");
1378
1379 }
1380
1381 switch (cmd) {
1382 case SIOCGLIFADDR:
1383
1384 if ((iflr->flags & IFLR_PREFIX) == 0)
1385 break;
1386
1387 case SIOCALIFADDR:
1388 case SIOCDLIFADDR:
1389
1390 sa = (struct sockaddr *)&iflr->addr;
1391 if (sa->sa_family != AF_INET6)
1392 return EINVAL;
1393 if (sa->sa_len != sizeof(struct sockaddr_in6))
1394 return EINVAL;
1395
1396 sa = (struct sockaddr *)&iflr->dstaddr;
1397 if (sa->sa_family && sa->sa_family != AF_INET6)
1398 return EINVAL;
1399 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in6))
1400 return EINVAL;
1401 break;
1402 default:
1403 #if 0
1404 panic("invalid cmd to in6_lifaddr_ioctl");
1405
1406 #else
1407 return EOPNOTSUPP;
1408 #endif
1409 }
1410 if (sizeof(struct in6_addr) * 8 < iflr->prefixlen)
1411 return EINVAL;
1412
1413 switch (cmd) {
1414 case SIOCALIFADDR:
1415 {
1416 struct in6_aliasreq ifra;
1417 struct in6_addr *hostid = NULL;
1418 int prefixlen;
1419
1420 if ((iflr->flags & IFLR_PREFIX) != 0) {
1421 struct sockaddr_in6 *sin6;
1422
1423
1424
1425
1426
1427
1428 ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0);
1429 if (!ifa)
1430 return EADDRNOTAVAIL;
1431 hostid = IFA_IN6(ifa);
1432
1433
1434 if (64 < iflr->prefixlen)
1435 return EINVAL;
1436 prefixlen = iflr->prefixlen;
1437
1438
1439 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1440 if (sin6->sin6_addr.s6_addr32[2] != 0
1441 || sin6->sin6_addr.s6_addr32[3] != 0) {
1442 return EINVAL;
1443 }
1444 } else
1445 prefixlen = iflr->prefixlen;
1446
1447
1448 bzero(&ifra, sizeof(ifra));
1449 bcopy(iflr->iflr_name, ifra.ifra_name, sizeof(ifra.ifra_name));
1450
1451 bcopy(&iflr->addr, &ifra.ifra_addr,
1452 ((struct sockaddr *)&iflr->addr)->sa_len);
1453 if (hostid) {
1454
1455 ifra.ifra_addr.sin6_addr.s6_addr32[2] =
1456 hostid->s6_addr32[2];
1457 ifra.ifra_addr.sin6_addr.s6_addr32[3] =
1458 hostid->s6_addr32[3];
1459 }
1460
1461 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {
1462 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1463 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
1464 if (hostid) {
1465 ifra.ifra_dstaddr.sin6_addr.s6_addr32[2] =
1466 hostid->s6_addr32[2];
1467 ifra.ifra_dstaddr.sin6_addr.s6_addr32[3] =
1468 hostid->s6_addr32[3];
1469 }
1470 }
1471
1472 ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
1473 in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
1474
1475 ifra.ifra_flags = iflr->flags & ~IFLR_PREFIX;
1476 return in6_control(so, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, p);
1477 }
1478 case SIOCGLIFADDR:
1479 case SIOCDLIFADDR:
1480 {
1481 struct in6_ifaddr *ia;
1482 struct in6_addr mask, candidate, match;
1483 struct sockaddr_in6 *sin6;
1484 int cmp;
1485
1486 bzero(&mask, sizeof(mask));
1487 if (iflr->flags & IFLR_PREFIX) {
1488
1489 in6_prefixlen2mask(&mask, iflr->prefixlen);
1490
1491 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1492 bcopy(&sin6->sin6_addr, &match, sizeof(match));
1493 match.s6_addr32[0] &= mask.s6_addr32[0];
1494 match.s6_addr32[1] &= mask.s6_addr32[1];
1495 match.s6_addr32[2] &= mask.s6_addr32[2];
1496 match.s6_addr32[3] &= mask.s6_addr32[3];
1497
1498
1499 if (bcmp(&match, &sin6->sin6_addr, sizeof(match)))
1500 return EINVAL;
1501
1502 cmp = 1;
1503 } else {
1504 if (cmd == SIOCGLIFADDR) {
1505
1506 cmp = 0;
1507 } else {
1508
1509 in6_prefixlen2mask(&mask, 128);
1510 sin6 = (struct sockaddr_in6 *)&iflr->addr;
1511 bcopy(&sin6->sin6_addr, &match, sizeof(match));
1512
1513 cmp = 1;
1514 }
1515 }
1516
1517 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1518 if (ifa->ifa_addr->sa_family != AF_INET6)
1519 continue;
1520 if (!cmp)
1521 break;
1522
1523 bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate));
1524 candidate.s6_addr32[0] &= mask.s6_addr32[0];
1525 candidate.s6_addr32[1] &= mask.s6_addr32[1];
1526 candidate.s6_addr32[2] &= mask.s6_addr32[2];
1527 candidate.s6_addr32[3] &= mask.s6_addr32[3];
1528 if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
1529 break;
1530 }
1531 if (!ifa)
1532 return EADDRNOTAVAIL;
1533 ia = ifa2ia6(ifa);
1534
1535 if (cmd == SIOCGLIFADDR) {
1536
1537 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len);
1538 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1539 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1540 ia->ia_dstaddr.sin6_len);
1541 } else
1542 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
1543
1544 iflr->prefixlen =
1545 in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
1546
1547 iflr->flags = ia->ia6_flags;
1548
1549 return 0;
1550 } else {
1551 struct in6_aliasreq ifra;
1552
1553
1554 bzero(&ifra, sizeof(ifra));
1555 bcopy(iflr->iflr_name, ifra.ifra_name,
1556 sizeof(ifra.ifra_name));
1557
1558 bcopy(&ia->ia_addr, &ifra.ifra_addr,
1559 ia->ia_addr.sin6_len);
1560 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1561 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1562 ia->ia_dstaddr.sin6_len);
1563 } else {
1564 bzero(&ifra.ifra_dstaddr,
1565 sizeof(ifra.ifra_dstaddr));
1566 }
1567 bcopy(&ia->ia_prefixmask, &ifra.ifra_dstaddr,
1568 ia->ia_prefixmask.sin6_len);
1569
1570 ifra.ifra_flags = ia->ia6_flags;
1571 return in6_control(so, SIOCDIFADDR_IN6, (caddr_t)&ifra,
1572 ifp, p);
1573 }
1574 }
1575 }
1576
1577 return EOPNOTSUPP;
1578 }
1579
1580
1581
1582
1583
1584 static int
1585 in6_ifinit(ifp, ia, sin6, newhost)
1586 struct ifnet *ifp;
1587 struct in6_ifaddr *ia;
1588 struct sockaddr_in6 *sin6;
1589 int newhost;
1590 {
1591 int error = 0, plen, ifacount = 0;
1592 int s = splnet();
1593 struct ifaddr *ifa;
1594
1595
1596
1597
1598
1599
1600 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1601 if (ifa->ifa_addr == NULL)
1602 continue;
1603 if (ifa->ifa_addr->sa_family != AF_INET6)
1604 continue;
1605 ifacount++;
1606 }
1607
1608 ia->ia_addr = *sin6;
1609
1610 if ((ifacount <= 1 || ifp->if_type == IFT_CARP) && ifp->if_ioctl &&
1611 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
1612 splx(s);
1613 return (error);
1614 }
1615 splx(s);
1616
1617 ia->ia_ifa.ifa_metric = ifp->if_metric;
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627 plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL);
1628 if (plen == 128 && ia->ia_dstaddr.sin6_family == AF_INET6) {
1629 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
1630 RTF_UP | RTF_HOST)) != 0)
1631 return (error);
1632 ia->ia_flags |= IFA_ROUTE;
1633 }
1634
1635
1636 if (newhost) {
1637
1638 ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
1639 in6_ifaddloop(&(ia->ia_ifa));
1640 }
1641
1642 if (ifp->if_flags & IFF_MULTICAST)
1643 in6_restoremkludge(ia, ifp);
1644
1645 return (error);
1646 }
1647
1648
1649
1650
1651
1652
1653
1654 void
1655 in6_savemkludge(oia)
1656 struct in6_ifaddr *oia;
1657 {
1658 struct in6_ifaddr *ia;
1659 struct in6_multi *in6m, *next;
1660
1661 IFP_TO_IA6(oia->ia_ifp, ia);
1662 if (ia) {
1663 for (in6m = LIST_FIRST(&oia->ia6_multiaddrs);
1664 in6m != LIST_END(&oia->ia6_multiaddrs); in6m = next) {
1665 next = LIST_NEXT(in6m, in6m_entry);
1666 IFAFREE(&in6m->in6m_ia->ia_ifa);
1667 ia->ia_ifa.ifa_refcnt++;
1668 in6m->in6m_ia = ia;
1669 LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
1670 }
1671 } else {
1672 struct multi6_kludge *mk;
1673
1674 LIST_FOREACH(mk, &in6_mk, mk_entry) {
1675 if (mk->mk_ifp == oia->ia_ifp)
1676 break;
1677 }
1678 if (mk == NULL)
1679 panic("in6_savemkludge: no kludge space");
1680
1681 for (in6m = LIST_FIRST(&oia->ia6_multiaddrs);
1682 in6m != LIST_END(&oia->ia6_multiaddrs); in6m = next) {
1683 next = LIST_NEXT(in6m, in6m_entry);
1684 IFAFREE(&in6m->in6m_ia->ia_ifa);
1685 in6m->in6m_ia = NULL;
1686 LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
1687 }
1688 }
1689 }
1690
1691
1692
1693
1694
1695
1696 void
1697 in6_restoremkludge(ia, ifp)
1698 struct in6_ifaddr *ia;
1699 struct ifnet *ifp;
1700 {
1701 struct multi6_kludge *mk;
1702
1703 LIST_FOREACH(mk, &in6_mk, mk_entry) {
1704 if (mk->mk_ifp == ifp) {
1705 struct in6_multi *in6m, *next;
1706
1707 for (in6m = LIST_FIRST(&mk->mk_head);
1708 in6m != LIST_END(&mk->mk_head);
1709 in6m = next) {
1710 next = LIST_NEXT(in6m, in6m_entry);
1711 in6m->in6m_ia = ia;
1712 ia->ia_ifa.ifa_refcnt++;
1713 LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
1714 in6m, in6m_entry);
1715 }
1716 LIST_INIT(&mk->mk_head);
1717 break;
1718 }
1719 }
1720 }
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733 void
1734 in6_createmkludge(ifp)
1735 struct ifnet *ifp;
1736 {
1737 struct multi6_kludge *mk;
1738
1739 LIST_FOREACH(mk, &in6_mk, mk_entry) {
1740
1741 if (mk->mk_ifp == ifp)
1742 return;
1743 }
1744
1745 mk = malloc(sizeof(*mk), M_IPMADDR, M_WAITOK);
1746
1747 bzero(mk, sizeof(*mk));
1748 LIST_INIT(&mk->mk_head);
1749 mk->mk_ifp = ifp;
1750 LIST_INSERT_HEAD(&in6_mk, mk, mk_entry);
1751 }
1752
1753 void
1754 in6_purgemkludge(ifp)
1755 struct ifnet *ifp;
1756 {
1757 struct multi6_kludge *mk;
1758 struct in6_multi *in6m;
1759
1760 LIST_FOREACH(mk, &in6_mk, mk_entry) {
1761 if (mk->mk_ifp != ifp)
1762 continue;
1763
1764
1765 while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL)
1766 in6_delmulti(in6m);
1767 LIST_REMOVE(mk, mk_entry);
1768 free(mk, M_IPMADDR);
1769 break;
1770 }
1771 }
1772
1773
1774
1775
1776
1777 struct in6_multi *
1778 in6_addmulti(maddr6, ifp, errorp)
1779 struct in6_addr *maddr6;
1780 struct ifnet *ifp;
1781 int *errorp;
1782 {
1783 struct in6_ifaddr *ia;
1784 struct in6_ifreq ifr;
1785 struct in6_multi *in6m;
1786 int s = splsoftnet();
1787
1788 *errorp = 0;
1789
1790
1791
1792 IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
1793 if (in6m != NULL) {
1794
1795
1796
1797 in6m->in6m_refcount++;
1798 } else {
1799
1800
1801
1802
1803 in6m = (struct in6_multi *)
1804 malloc(sizeof(*in6m), M_IPMADDR, M_NOWAIT);
1805 if (in6m == NULL) {
1806 splx(s);
1807 *errorp = ENOBUFS;
1808 return (NULL);
1809 }
1810 in6m->in6m_addr = *maddr6;
1811 in6m->in6m_ifp = ifp;
1812 in6m->in6m_refcount = 1;
1813 IFP_TO_IA6(ifp, ia);
1814 if (ia == NULL) {
1815 free(in6m, M_IPMADDR);
1816 splx(s);
1817 *errorp = EADDRNOTAVAIL;
1818 return (NULL);
1819 }
1820 in6m->in6m_ia = ia;
1821 ia->ia_ifa.ifa_refcnt++;
1822 LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
1823
1824
1825
1826
1827
1828 bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
1829 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
1830 ifr.ifr_addr.sin6_family = AF_INET6;
1831 ifr.ifr_addr.sin6_addr = *maddr6;
1832 if (ifp->if_ioctl == NULL)
1833 *errorp = ENXIO;
1834 else
1835 *errorp = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,
1836 (caddr_t)&ifr);
1837 if (*errorp) {
1838 LIST_REMOVE(in6m, in6m_entry);
1839 free(in6m, M_IPMADDR);
1840 IFAFREE(&ia->ia_ifa);
1841 splx(s);
1842 return (NULL);
1843 }
1844
1845
1846
1847
1848 mld6_start_listening(in6m);
1849 }
1850 splx(s);
1851 return (in6m);
1852 }
1853
1854
1855
1856
1857 void
1858 in6_delmulti(in6m)
1859 struct in6_multi *in6m;
1860 {
1861 struct in6_ifreq ifr;
1862 int s = splsoftnet();
1863
1864 if (--in6m->in6m_refcount == 0) {
1865
1866
1867
1868
1869 mld6_stop_listening(in6m);
1870
1871
1872
1873
1874 LIST_REMOVE(in6m, in6m_entry);
1875 if (in6m->in6m_ia) {
1876 IFAFREE(&in6m->in6m_ia->ia_ifa);
1877 }
1878
1879
1880
1881
1882
1883 bzero(&ifr.ifr_addr, sizeof(struct sockaddr_in6));
1884 ifr.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
1885 ifr.ifr_addr.sin6_family = AF_INET6;
1886 ifr.ifr_addr.sin6_addr = in6m->in6m_addr;
1887 (*in6m->in6m_ifp->if_ioctl)(in6m->in6m_ifp,
1888 SIOCDELMULTI, (caddr_t)&ifr);
1889 free(in6m, M_IPMADDR);
1890 }
1891 splx(s);
1892 }
1893
1894 struct in6_multi_mship *
1895 in6_joingroup(ifp, addr, errorp)
1896 struct ifnet *ifp;
1897 struct in6_addr *addr;
1898 int *errorp;
1899 {
1900 struct in6_multi_mship *imm;
1901
1902 imm = malloc(sizeof(*imm), M_IPMADDR, M_NOWAIT);
1903 if (!imm) {
1904 *errorp = ENOBUFS;
1905 return NULL;
1906 }
1907 imm->i6mm_maddr = in6_addmulti(addr, ifp, errorp);
1908 if (!imm->i6mm_maddr) {
1909
1910 free(imm, M_IPMADDR);
1911 return NULL;
1912 }
1913 return imm;
1914 }
1915
1916 int
1917 in6_leavegroup(imm)
1918 struct in6_multi_mship *imm;
1919 {
1920
1921 if (imm->i6mm_maddr)
1922 in6_delmulti(imm->i6mm_maddr);
1923 free(imm, M_IPMADDR);
1924 return 0;
1925 }
1926
1927
1928
1929
1930 struct in6_ifaddr *
1931 in6ifa_ifpforlinklocal(ifp, ignoreflags)
1932 struct ifnet *ifp;
1933 int ignoreflags;
1934 {
1935 struct ifaddr *ifa;
1936
1937 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1938 if (ifa->ifa_addr == NULL)
1939 continue;
1940 if (ifa->ifa_addr->sa_family != AF_INET6)
1941 continue;
1942 if (IN6_IS_ADDR_LINKLOCAL(IFA_IN6(ifa))) {
1943 if ((((struct in6_ifaddr *)ifa)->ia6_flags &
1944 ignoreflags) != 0)
1945 continue;
1946 break;
1947 }
1948 }
1949
1950 return ((struct in6_ifaddr *)ifa);
1951 }
1952
1953
1954
1955
1956
1957 struct in6_ifaddr *
1958 in6ifa_ifpwithaddr(ifp, addr)
1959 struct ifnet *ifp;
1960 struct in6_addr *addr;
1961 {
1962 struct ifaddr *ifa;
1963
1964 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1965 if (ifa->ifa_addr == NULL)
1966 continue;
1967 if (ifa->ifa_addr->sa_family != AF_INET6)
1968 continue;
1969 if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa)))
1970 break;
1971 }
1972
1973 return ((struct in6_ifaddr *)ifa);
1974 }
1975
1976
1977
1978
1979 static char digits[] = "0123456789abcdef";
1980 static int ip6round = 0;
1981 char *
1982 ip6_sprintf(addr)
1983 struct in6_addr *addr;
1984 {
1985 static char ip6buf[8][48];
1986 int i;
1987 char *cp;
1988 u_short *a = (u_short *)addr;
1989 u_char *d;
1990 int dcolon = 0;
1991
1992 ip6round = (ip6round + 1) & 7;
1993 cp = ip6buf[ip6round];
1994
1995 for (i = 0; i < 8; i++) {
1996 if (dcolon == 1) {
1997 if (*a == 0) {
1998 if (i == 7)
1999 *cp++ = ':';
2000 a++;
2001 continue;
2002 } else
2003 dcolon = 2;
2004 }
2005 if (*a == 0) {
2006 if (dcolon == 0 && *(a + 1) == 0) {
2007 if (i == 0)
2008 *cp++ = ':';
2009 *cp++ = ':';
2010 dcolon = 1;
2011 } else {
2012 *cp++ = '0';
2013 *cp++ = ':';
2014 }
2015 a++;
2016 continue;
2017 }
2018 d = (u_char *)a;
2019 *cp++ = digits[*d >> 4];
2020 *cp++ = digits[*d++ & 0xf];
2021 *cp++ = digits[*d >> 4];
2022 *cp++ = digits[*d & 0xf];
2023 *cp++ = ':';
2024 a++;
2025 }
2026 *--cp = 0;
2027 return (ip6buf[ip6round]);
2028 }
2029
2030
2031
2032
2033 int
2034 in6_addrscope (addr)
2035 struct in6_addr *addr;
2036 {
2037 int scope;
2038
2039 if (addr->s6_addr8[0] == 0xfe) {
2040 scope = addr->s6_addr8[1] & 0xc0;
2041
2042 switch (scope) {
2043 case 0x80:
2044 return IPV6_ADDR_SCOPE_LINKLOCAL;
2045 break;
2046 case 0xc0:
2047 return IPV6_ADDR_SCOPE_SITELOCAL;
2048 break;
2049 default:
2050 return IPV6_ADDR_SCOPE_GLOBAL;
2051 break;
2052 }
2053 }
2054
2055
2056 if (addr->s6_addr8[0] == 0xff) {
2057 scope = addr->s6_addr8[1] & 0x0f;
2058
2059
2060
2061
2062
2063 switch (scope) {
2064 case IPV6_ADDR_SCOPE_INTFACELOCAL:
2065 return IPV6_ADDR_SCOPE_INTFACELOCAL;
2066 break;
2067 case IPV6_ADDR_SCOPE_LINKLOCAL:
2068 return IPV6_ADDR_SCOPE_LINKLOCAL;
2069 break;
2070 case IPV6_ADDR_SCOPE_SITELOCAL:
2071 return IPV6_ADDR_SCOPE_SITELOCAL;
2072 break;
2073 default:
2074 return IPV6_ADDR_SCOPE_GLOBAL;
2075 break;
2076 }
2077 }
2078
2079 if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
2080 if (addr->s6_addr8[15] == 1)
2081 return IPV6_ADDR_SCOPE_INTFACELOCAL;
2082 if (addr->s6_addr8[15] == 0)
2083 return IPV6_ADDR_SCOPE_LINKLOCAL;
2084 }
2085
2086 return IPV6_ADDR_SCOPE_GLOBAL;
2087 }
2088
2089 int
2090 in6_addr2scopeid(ifp, addr)
2091 struct ifnet *ifp;
2092 struct in6_addr *addr;
2093 {
2094 int scope = in6_addrscope(addr);
2095
2096 switch(scope) {
2097 case IPV6_ADDR_SCOPE_INTFACELOCAL:
2098 case IPV6_ADDR_SCOPE_LINKLOCAL:
2099
2100 return (ifp->if_index);
2101
2102 case IPV6_ADDR_SCOPE_SITELOCAL:
2103 return (0);
2104
2105 default:
2106 return (0);
2107 }
2108 }
2109
2110 int
2111 in6_is_addr_deprecated(sa6)
2112 struct sockaddr_in6 *sa6;
2113 {
2114 struct in6_ifaddr *ia;
2115
2116 for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
2117 if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
2118 &sa6->sin6_addr) &&
2119 (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0)
2120 return (1);
2121
2122
2123 }
2124
2125 return (0);
2126 }
2127
2128
2129
2130
2131
2132 int
2133 in6_matchlen(src, dst)
2134 struct in6_addr *src, *dst;
2135 {
2136 int match = 0;
2137 u_char *s = (u_char *)src, *d = (u_char *)dst;
2138 u_char *lim = s + 16, r;
2139
2140 while (s < lim)
2141 if ((r = (*d++ ^ *s++)) != 0) {
2142 while (r < 128) {
2143 match++;
2144 r <<= 1;
2145 }
2146 break;
2147 } else
2148 match += 8;
2149 return match;
2150 }
2151
2152 int
2153 in6_are_prefix_equal(p1, p2, len)
2154 struct in6_addr *p1, *p2;
2155 int len;
2156 {
2157 int bytelen, bitlen;
2158
2159
2160 if (0 > len || len > 128) {
2161 log(LOG_ERR, "in6_are_prefix_equal: invalid prefix length(%d)\n",
2162 len);
2163 return (0);
2164 }
2165
2166 bytelen = len / 8;
2167 bitlen = len % 8;
2168
2169 if (bcmp(&p1->s6_addr, &p2->s6_addr, bytelen))
2170 return (0);
2171
2172 if (bitlen != 0 &&
2173 p1->s6_addr[bytelen] >> (8 - bitlen) !=
2174 p2->s6_addr[bytelen] >> (8 - bitlen))
2175 return (0);
2176
2177 return (1);
2178 }
2179
2180 void
2181 in6_prefixlen2mask(maskp, len)
2182 struct in6_addr *maskp;
2183 int len;
2184 {
2185 u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
2186 int bytelen, bitlen, i;
2187
2188
2189 if (0 > len || len > 128) {
2190 log(LOG_ERR, "in6_prefixlen2mask: invalid prefix length(%d)\n",
2191 len);
2192 return;
2193 }
2194
2195 bzero(maskp, sizeof(*maskp));
2196 bytelen = len / 8;
2197 bitlen = len % 8;
2198 for (i = 0; i < bytelen; i++)
2199 maskp->s6_addr[i] = 0xff;
2200
2201 if (bitlen)
2202 maskp->s6_addr[bytelen] = maskarray[bitlen - 1];
2203 }
2204
2205
2206
2207
2208 struct in6_ifaddr *
2209 in6_ifawithscope(oifp, dst)
2210 struct ifnet *oifp;
2211 struct in6_addr *dst;
2212 {
2213 int dst_scope = in6_addrscope(dst), src_scope, best_scope = 0;
2214 int blen = -1;
2215 struct ifaddr *ifa;
2216 struct ifnet *ifp;
2217 struct in6_ifaddr *ifa_best = NULL;
2218
2219 if (oifp == NULL) {
2220 printf("in6_ifawithscope: output interface is not specified\n");
2221 return (NULL);
2222 }
2223
2224
2225
2226
2227
2228
2229 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
2230 {
2231
2232
2233
2234
2235 if (in6_addr2scopeid(ifp, dst) != in6_addr2scopeid(oifp, dst))
2236 continue;
2237
2238 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2239 int tlen = -1, dscopecmp, bscopecmp, matchcmp;
2240
2241 if (ifa->ifa_addr->sa_family != AF_INET6)
2242 continue;
2243
2244 src_scope = in6_addrscope(IFA_IN6(ifa));
2245
2246 #ifdef ADDRSELECT_DEBUG
2247 dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
2248 printf("in6_ifawithscope: dst=%s bestaddr=%s, "
2249 "newaddr=%s, scope=%x, dcmp=%d, bcmp=%d, "
2250 "matchlen=%d, flgs=%x\n",
2251 ip6_sprintf(dst),
2252 ifa_best ? ip6_sprintf(&ifa_best->ia_addr.sin6_addr) : "none",
2253 ip6_sprintf(IFA_IN6(ifa)), src_scope,
2254 dscopecmp,
2255 ifa_best ? IN6_ARE_SCOPE_CMP(src_scope, best_scope) : -1,
2256 in6_matchlen(IFA_IN6(ifa), dst),
2257 ((struct in6_ifaddr *)ifa)->ia6_flags);
2258 #endif
2259
2260
2261
2262
2263
2264 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2265 IN6_IFF_NOTREADY)
2266 continue;
2267
2268
2269 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2270 IN6_IFF_ANYCAST)
2271 continue;
2272
2273 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2274 IN6_IFF_DETACHED)
2275 continue;
2276
2277
2278
2279
2280
2281 if (ifa_best == NULL)
2282 goto replace;
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297 if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0 &&
2298 IN6_ARE_SCOPE_CMP(src_scope, dst_scope) >= 0)
2299 goto replace;
2300 if (IN6_ARE_SCOPE_CMP(src_scope, dst_scope) < 0 &&
2301 IN6_ARE_SCOPE_CMP(best_scope, dst_scope) >= 0)
2302 continue;
2303
2304
2305
2306
2307
2308
2309
2310 if (((struct in6_ifaddr *)ifa)->ia6_flags &
2311 IN6_IFF_DEPRECATED) {
2312
2313
2314
2315
2316 if (!ip6_use_deprecated)
2317 continue;
2318
2319
2320
2321
2322
2323 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED)
2324 == 0)
2325 continue;
2326 }
2327
2328
2329
2330
2331
2332
2333 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) &&
2334 (((struct in6_ifaddr *)ifa)->ia6_flags &
2335 IN6_IFF_DEPRECATED) == 0)
2336 goto replace;
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385 dscopecmp = IN6_ARE_SCOPE_CMP(src_scope, dst_scope);
2386 bscopecmp = IN6_ARE_SCOPE_CMP(src_scope, best_scope);
2387
2388 if (dscopecmp && bscopecmp == 0) {
2389 if (oifp == ifp)
2390 goto replace;
2391 continue;
2392 }
2393 if (dscopecmp > 0) {
2394 if (bscopecmp > 0)
2395 continue;
2396 goto replace;
2397 }
2398 if (dscopecmp < 0) {
2399 if (bscopecmp > 0)
2400 goto replace;
2401 continue;
2402 }
2403
2404
2405 if (bscopecmp < 0)
2406 goto replace;
2407
2408
2409
2410
2411
2412
2413 tlen = in6_matchlen(IFA_IN6(ifa), dst);
2414 matchcmp = tlen - blen;
2415 if (matchcmp > 0)
2416 goto replace;
2417 if (matchcmp < 0)
2418 continue;
2419 if (oifp == ifp)
2420 goto replace;
2421 continue;
2422
2423 replace:
2424 ifa_best = (struct in6_ifaddr *)ifa;
2425 blen = tlen >= 0 ? tlen :
2426 in6_matchlen(IFA_IN6(ifa), dst);
2427 best_scope = in6_addrscope(&ifa_best->ia_addr.sin6_addr);
2428 }
2429 }
2430
2431
2432 if (ifa_best == NULL)
2433 ip6stat.ip6s_sources_none++;
2434 else {
2435 if (oifp == ifa_best->ia_ifp)
2436 ip6stat.ip6s_sources_sameif[best_scope]++;
2437 else
2438 ip6stat.ip6s_sources_otherif[best_scope]++;
2439
2440 if (best_scope == dst_scope)
2441 ip6stat.ip6s_sources_samescope[best_scope]++;
2442 else
2443 ip6stat.ip6s_sources_otherscope[best_scope]++;
2444
2445 if ((ifa_best->ia6_flags & IN6_IFF_DEPRECATED) != 0)
2446 ip6stat.ip6s_sources_deprecated[best_scope]++;
2447 }
2448
2449 return (ifa_best);
2450 }
2451
2452
2453
2454
2455
2456 struct in6_ifaddr *
2457 in6_ifawithifp(ifp, dst)
2458 struct ifnet *ifp;
2459 struct in6_addr *dst;
2460 {
2461 int dst_scope = in6_addrscope(dst), blen = -1, tlen;
2462 struct ifaddr *ifa;
2463 struct in6_ifaddr *besta = 0;
2464 struct in6_ifaddr *dep[2];
2465
2466 dep[0] = dep[1] = NULL;
2467
2468
2469
2470
2471
2472
2473
2474 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2475 if (ifa->ifa_addr->sa_family != AF_INET6)
2476 continue;
2477 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
2478 continue;
2479 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
2480 continue;
2481 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
2482 continue;
2483 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2484 if (ip6_use_deprecated)
2485 dep[0] = (struct in6_ifaddr *)ifa;
2486 continue;
2487 }
2488
2489 if (dst_scope == in6_addrscope(IFA_IN6(ifa))) {
2490
2491
2492
2493 if (besta) {
2494 if (blen == -1)
2495 blen = in6_matchlen(&besta->ia_addr.sin6_addr, dst);
2496 tlen = in6_matchlen(IFA_IN6(ifa), dst);
2497 if (tlen > blen) {
2498 blen = tlen;
2499 besta = (struct in6_ifaddr *)ifa;
2500 }
2501 } else
2502 besta = (struct in6_ifaddr *)ifa;
2503 }
2504 }
2505 if (besta)
2506 return (besta);
2507
2508 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2509 if (ifa->ifa_addr->sa_family != AF_INET6)
2510 continue;
2511 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_ANYCAST)
2512 continue;
2513 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_NOTREADY)
2514 continue;
2515 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DETACHED)
2516 continue;
2517 if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DEPRECATED) {
2518 if (ip6_use_deprecated)
2519 dep[1] = (struct in6_ifaddr *)ifa;
2520 continue;
2521 }
2522
2523 return (struct in6_ifaddr *)ifa;
2524 }
2525
2526
2527 if (dep[0])
2528 return dep[0];
2529 if (dep[1])
2530 return dep[1];
2531
2532 return NULL;
2533 }
2534
2535
2536
2537
2538 void
2539 in6_if_up(ifp)
2540 struct ifnet *ifp;
2541 {
2542 struct ifaddr *ifa;
2543 struct in6_ifaddr *ia;
2544 int dad_delay;
2545
2546
2547
2548
2549 in6_ifattach(ifp, NULL);
2550
2551 dad_delay = 0;
2552 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
2553 if (ifa->ifa_addr->sa_family != AF_INET6)
2554 continue;
2555 ia = (struct in6_ifaddr *)ifa;
2556 if (ia->ia6_flags & IN6_IFF_TENTATIVE)
2557 nd6_dad_start(ifa, &dad_delay);
2558 }
2559 }
2560
2561 int
2562 in6if_do_dad(ifp)
2563 struct ifnet *ifp;
2564 {
2565 if ((ifp->if_flags & IFF_LOOPBACK) != 0)
2566 return (0);
2567
2568 switch (ifp->if_type) {
2569 case IFT_FAITH:
2570
2571
2572
2573
2574
2575
2576 return (0);
2577 default:
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) !=
2588 (IFF_UP|IFF_RUNNING))
2589 return (0);
2590
2591 return (1);
2592 }
2593 }
2594
2595
2596
2597
2598
2599 void
2600 in6_setmaxmtu()
2601 {
2602 unsigned long maxmtu = 0;
2603 struct ifnet *ifp;
2604
2605 for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
2606 {
2607
2608 if (!ifp->if_afdata[AF_INET6])
2609 continue;
2610 if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
2611 IN6_LINKMTU(ifp) > maxmtu)
2612 maxmtu = IN6_LINKMTU(ifp);
2613 }
2614 if (maxmtu)
2615 in6_maxmtu = maxmtu;
2616 }
2617
2618 void *
2619 in6_domifattach(ifp)
2620 struct ifnet *ifp;
2621 {
2622 struct in6_ifextra *ext;
2623
2624 ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
2625 bzero(ext, sizeof(*ext));
2626
2627 ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
2628 M_IFADDR, M_WAITOK);
2629 bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
2630
2631 ext->icmp6_ifstat =
2632 (struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
2633 M_IFADDR, M_WAITOK);
2634 bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
2635
2636 ext->nd_ifinfo = nd6_ifattach(ifp);
2637 return ext;
2638 }
2639
2640 void
2641 in6_domifdetach(ifp, aux)
2642 struct ifnet *ifp;
2643 void *aux;
2644 {
2645 struct in6_ifextra *ext = (struct in6_ifextra *)aux;
2646
2647 nd6_ifdetach(ext->nd_ifinfo);
2648 free(ext->in6_ifstat, M_IFADDR);
2649 free(ext->icmp6_ifstat, M_IFADDR);
2650 free(ext, M_IFADDR);
2651 }