in6_ifattach.c (37f878f56c07f3c298351acae5fe0c9afe936d79) in6_ifattach.c (1272577e22d8f1c1c5b5e88f2624836e93aecb17)
1/* $FreeBSD$ */
2/* $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $ */
3
4/*-
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 81 unchanged lines hidden (view full) ---

90#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
91
92/*
93 * Generate a last-resort interface identifier, when the machine has no
94 * IEEE802/EUI64 address sources.
95 * The goal here is to get an interface identifier that is
96 * (1) random enough and (2) does not change across reboot.
97 * We currently use MD5(hostname) for it.
1/* $FreeBSD$ */
2/* $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $ */
3
4/*-
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 81 unchanged lines hidden (view full) ---

90#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
91
92/*
93 * Generate a last-resort interface identifier, when the machine has no
94 * IEEE802/EUI64 address sources.
95 * The goal here is to get an interface identifier that is
96 * (1) random enough and (2) does not change across reboot.
97 * We currently use MD5(hostname) for it.
98 *
99 * in6 - upper 64bits are preserved
98 */
99static int
100 */
101static int
100get_rand_ifid(ifp, in6)
101 struct ifnet *ifp;
102 struct in6_addr *in6; /* upper 64bits are preserved */
102get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
103{
104 MD5_CTX ctxt;
105 u_int8_t digest[16];
106 int hostnamelen = strlen(hostname);
107
108#if 0
109 /* we need at least several letters as seed for ifid */
110 if (hostnamelen < 3)

--- 15 unchanged lines hidden (view full) ---

126
127 /* convert EUI64 into IPv6 interface identifier */
128 EUI64_TO_IFID(in6);
129
130 return 0;
131}
132
133static int
103{
104 MD5_CTX ctxt;
105 u_int8_t digest[16];
106 int hostnamelen = strlen(hostname);
107
108#if 0
109 /* we need at least several letters as seed for ifid */
110 if (hostnamelen < 3)

--- 15 unchanged lines hidden (view full) ---

126
127 /* convert EUI64 into IPv6 interface identifier */
128 EUI64_TO_IFID(in6);
129
130 return 0;
131}
132
133static int
134generate_tmp_ifid(seed0, seed1, ret)
135 u_int8_t *seed0, *ret;
136 const u_int8_t *seed1;
134generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
137{
138 MD5_CTX ctxt;
139 u_int8_t seed[16], digest[16], nullbuf[8];
140 u_int32_t val32;
141
135{
136 MD5_CTX ctxt;
137 u_int8_t seed[16], digest[16], nullbuf[8];
138 u_int32_t val32;
139
142 /* If there's no hisotry, start with a random seed. */
140 /* If there's no history, start with a random seed. */
143 bzero(nullbuf, sizeof(nullbuf));
144 if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
145 int i;
146
147 for (i = 0; i < 2; i++) {
148 val32 = arc4random();
149 bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
150 }

--- 58 unchanged lines hidden (view full) ---

209 }
210
211 return 0;
212}
213
214/*
215 * Get interface identifier for the specified interface.
216 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
141 bzero(nullbuf, sizeof(nullbuf));
142 if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
143 int i;
144
145 for (i = 0; i < 2; i++) {
146 val32 = arc4random();
147 bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
148 }

--- 58 unchanged lines hidden (view full) ---

207 }
208
209 return 0;
210}
211
212/*
213 * Get interface identifier for the specified interface.
214 * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
215 *
216 * in6 - upper 64bits are preserved
217 */
218int
217 */
218int
219in6_get_hw_ifid(ifp, in6)
220 struct ifnet *ifp;
221 struct in6_addr *in6; /* upper 64bits are preserved */
219in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
222{
223 struct ifaddr *ifa;
224 struct sockaddr_dl *sdl;
225 u_int8_t *addr;
226 size_t addrlen;
227 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
228 static u_int8_t allone[8] =
229 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

--- 112 unchanged lines hidden (view full) ---

342
343 return 0;
344}
345
346/*
347 * Get interface identifier for the specified interface. If it is not
348 * available on ifp0, borrow interface identifier from other information
349 * sources.
220{
221 struct ifaddr *ifa;
222 struct sockaddr_dl *sdl;
223 u_int8_t *addr;
224 size_t addrlen;
225 static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
226 static u_int8_t allone[8] =
227 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

--- 112 unchanged lines hidden (view full) ---

340
341 return 0;
342}
343
344/*
345 * Get interface identifier for the specified interface. If it is not
346 * available on ifp0, borrow interface identifier from other information
347 * sources.
348 *
349 * altifp - secondary EUI64 source
350 */
351static int
350 */
351static int
352get_ifid(ifp0, altifp, in6)
353 struct ifnet *ifp0;
354 struct ifnet *altifp; /* secondary EUI64 source */
355 struct in6_addr *in6;
352get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
353 struct in6_addr *in6)
356{
357 struct ifnet *ifp;
358
359 /* first, try to get it from the interface itself */
360 if (in6_get_hw_ifid(ifp0, in6) == 0) {
361 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
362 if_name(ifp0)));
363 goto success;

--- 42 unchanged lines hidden (view full) ---

406success:
407 nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
408 if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
409 in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
410 in6->s6_addr[14], in6->s6_addr[15]));
411 return 0;
412}
413
354{
355 struct ifnet *ifp;
356
357 /* first, try to get it from the interface itself */
358 if (in6_get_hw_ifid(ifp0, in6) == 0) {
359 nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
360 if_name(ifp0)));
361 goto success;

--- 42 unchanged lines hidden (view full) ---

404success:
405 nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
406 if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
407 in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
408 in6->s6_addr[14], in6->s6_addr[15]));
409 return 0;
410}
411
412/*
413 * altifp - secondary EUI64 source
414 */
414static int
415static int
415in6_ifattach_linklocal(ifp, altifp)
416 struct ifnet *ifp;
417 struct ifnet *altifp; /* secondary EUI64 source */
416in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
418{
419 struct in6_ifaddr *ia;
420 struct in6_aliasreq ifra;
421 struct nd_prefixctl pr0;
422 int i, error;
423
424 /*
425 * configure link-local address.

--- 95 unchanged lines hidden (view full) ---

521 if (nd6_prefix_lookup(&pr0) == NULL) {
522 if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
523 return (error);
524 }
525
526 return 0;
527}
528
417{
418 struct in6_ifaddr *ia;
419 struct in6_aliasreq ifra;
420 struct nd_prefixctl pr0;
421 int i, error;
422
423 /*
424 * configure link-local address.

--- 95 unchanged lines hidden (view full) ---

520 if (nd6_prefix_lookup(&pr0) == NULL) {
521 if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
522 return (error);
523 }
524
525 return 0;
526}
527
528/*
529 * ifp - must be IFT_LOOP
530 */
529static int
531static int
530in6_ifattach_loopback(ifp)
531 struct ifnet *ifp; /* must be IFT_LOOP */
532in6_ifattach_loopback(struct ifnet *ifp)
532{
533 struct in6_aliasreq ifra;
534 int error;
535
536 bzero(&ifra, sizeof(ifra));
537
538 /*
539 * in6_update_ifa() does not use ifra_name, but we accurately set it

--- 43 unchanged lines hidden (view full) ---

583
584/*
585 * compute NI group address, based on the current hostname setting.
586 * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
587 *
588 * when ifp == NULL, the caller is responsible for filling scopeid.
589 */
590int
533{
534 struct in6_aliasreq ifra;
535 int error;
536
537 bzero(&ifra, sizeof(ifra));
538
539 /*
540 * in6_update_ifa() does not use ifra_name, but we accurately set it

--- 43 unchanged lines hidden (view full) ---

584
585/*
586 * compute NI group address, based on the current hostname setting.
587 * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
588 *
589 * when ifp == NULL, the caller is responsible for filling scopeid.
590 */
591int
591in6_nigroup(ifp, name, namelen, in6)
592 struct ifnet *ifp;
593 const char *name;
594 int namelen;
595 struct in6_addr *in6;
592in6_nigroup(struct ifnet *ifp, const char *name, int namelen,
593 struct in6_addr *in6)
596{
597 const char *p;
598 u_char *q;
599 MD5_CTX ctxt;
600 u_int8_t digest[16];
601 char l;
602 char n[64]; /* a single label must not exceed 63 chars */
603

--- 29 unchanged lines hidden (view full) ---

633
634 return 0;
635}
636
637/*
638 * XXX multiple loopback interface needs more care. for instance,
639 * nodelocal address needs to be configured onto only one of them.
640 * XXX multiple link-local address case
594{
595 const char *p;
596 u_char *q;
597 MD5_CTX ctxt;
598 u_int8_t digest[16];
599 char l;
600 char n[64]; /* a single label must not exceed 63 chars */
601

--- 29 unchanged lines hidden (view full) ---

631
632 return 0;
633}
634
635/*
636 * XXX multiple loopback interface needs more care. for instance,
637 * nodelocal address needs to be configured onto only one of them.
638 * XXX multiple link-local address case
639 *
640 * altifp - secondary EUI64 source
641 */
642void
641 */
642void
643in6_ifattach(ifp, altifp)
644 struct ifnet *ifp;
645 struct ifnet *altifp; /* secondary EUI64 source */
643in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
646{
647 struct in6_ifaddr *ia;
648 struct in6_addr in6;
649
650 /* some of the interfaces are inherently not IPv6 capable */
651 switch (ifp->if_type) {
652 case IFT_PFLOG:
653 case IFT_PFSYNC:

--- 65 unchanged lines hidden (view full) ---

719}
720
721/*
722 * NOTE: in6_ifdetach() does not support loopback if at this moment.
723 * We don't need this function in bsdi, because interfaces are never removed
724 * from the ifnet list in bsdi.
725 */
726void
644{
645 struct in6_ifaddr *ia;
646 struct in6_addr in6;
647
648 /* some of the interfaces are inherently not IPv6 capable */
649 switch (ifp->if_type) {
650 case IFT_PFLOG:
651 case IFT_PFSYNC:

--- 65 unchanged lines hidden (view full) ---

717}
718
719/*
720 * NOTE: in6_ifdetach() does not support loopback if at this moment.
721 * We don't need this function in bsdi, because interfaces are never removed
722 * from the ifnet list in bsdi.
723 */
724void
727in6_ifdetach(ifp)
728 struct ifnet *ifp;
725in6_ifdetach(struct ifnet *ifp)
729{
730 struct in6_ifaddr *ia, *oia;
731 struct ifaddr *ifa, *next;
732 struct rtentry *rt;
733 short rtflags;
734 struct sockaddr_in6 sin6;
735 struct in6_multi_mship *imm;
736

--- 93 unchanged lines hidden (view full) ---

830 rtexpunge(rt);
831 RTFREE_LOCKED(rt);
832 }
833 RADIX_NODE_HEAD_UNLOCK(rt_tables[AF_INET6]);
834 }
835}
836
837int
726{
727 struct in6_ifaddr *ia, *oia;
728 struct ifaddr *ifa, *next;
729 struct rtentry *rt;
730 short rtflags;
731 struct sockaddr_in6 sin6;
732 struct in6_multi_mship *imm;
733

--- 93 unchanged lines hidden (view full) ---

827 rtexpunge(rt);
828 RTFREE_LOCKED(rt);
829 }
830 RADIX_NODE_HEAD_UNLOCK(rt_tables[AF_INET6]);
831 }
832}
833
834int
838in6_get_tmpifid(ifp, retbuf, baseid, generate)
839 struct ifnet *ifp;
840 u_int8_t *retbuf;
841 const u_int8_t *baseid;
842 int generate;
835in6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
836 const u_int8_t *baseid, int generate)
843{
844 u_int8_t nullbuf[8];
845 struct nd_ifinfo *ndi = ND_IFINFO(ifp);
846
847 bzero(nullbuf, sizeof(nullbuf));
848 if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
849 /* we've never created a random ID. Create a new one. */
850 generate = 1;

--- 7 unchanged lines hidden (view full) ---

858 ndi->randomid);
859 }
860 bcopy(ndi->randomid, retbuf, 8);
861
862 return (0);
863}
864
865void
837{
838 u_int8_t nullbuf[8];
839 struct nd_ifinfo *ndi = ND_IFINFO(ifp);
840
841 bzero(nullbuf, sizeof(nullbuf));
842 if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
843 /* we've never created a random ID. Create a new one. */
844 generate = 1;

--- 7 unchanged lines hidden (view full) ---

852 ndi->randomid);
853 }
854 bcopy(ndi->randomid, retbuf, 8);
855
856 return (0);
857}
858
859void
866in6_tmpaddrtimer(ignored_arg)
867 void *ignored_arg;
860in6_tmpaddrtimer(void *ignored_arg)
868{
869 struct nd_ifinfo *ndi;
870 u_int8_t nullbuf[8];
871 struct ifnet *ifp;
872 int s = splnet();
873
874 callout_reset(&in6_tmpaddrtimer_ch,
875 (ip6_temp_preferred_lifetime - ip6_desync_factor -

--- 11 unchanged lines hidden (view full) ---

887 ndi->randomseed1, ndi->randomid);
888 }
889 }
890
891 splx(s);
892}
893
894static void
861{
862 struct nd_ifinfo *ndi;
863 u_int8_t nullbuf[8];
864 struct ifnet *ifp;
865 int s = splnet();
866
867 callout_reset(&in6_tmpaddrtimer_ch,
868 (ip6_temp_preferred_lifetime - ip6_desync_factor -

--- 11 unchanged lines hidden (view full) ---

880 ndi->randomseed1, ndi->randomid);
881 }
882 }
883
884 splx(s);
885}
886
887static void
895in6_purgemaddrs(ifp)
896 struct ifnet *ifp;
888in6_purgemaddrs(struct ifnet *ifp)
897{
898 struct in6_multi *in6m;
899 struct in6_multi *oin6m;
900
901#ifdef DIAGNOSTIC
902 printf("%s: purging ifp %p\n", __func__, ifp);
903#endif
904
905 IFF_LOCKGIANT(ifp);
906 LIST_FOREACH_SAFE(in6m, &in6_multihead, in6m_entry, oin6m) {
907 if (in6m->in6m_ifp == ifp)
908 in6_delmulti(in6m);
909 }
910 IFF_UNLOCKGIANT(ifp);
911}
889{
890 struct in6_multi *in6m;
891 struct in6_multi *oin6m;
892
893#ifdef DIAGNOSTIC
894 printf("%s: purging ifp %p\n", __func__, ifp);
895#endif
896
897 IFF_LOCKGIANT(ifp);
898 LIST_FOREACH_SAFE(in6m, &in6_multihead, in6m_entry, oin6m) {
899 if (in6m->in6m_ifp == ifp)
900 in6_delmulti(in6m);
901 }
902 IFF_UNLOCKGIANT(ifp);
903}