1caf43b02SWarner Losh /*-
251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni *
482cd038dSYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
582cd038dSYoshinobu Inoue * All rights reserved.
682cd038dSYoshinobu Inoue *
782cd038dSYoshinobu Inoue * Redistribution and use in source and binary forms, with or without
882cd038dSYoshinobu Inoue * modification, are permitted provided that the following conditions
982cd038dSYoshinobu Inoue * are met:
1082cd038dSYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright
1182cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer.
1282cd038dSYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright
1382cd038dSYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the
1482cd038dSYoshinobu Inoue * documentation and/or other materials provided with the distribution.
1582cd038dSYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors
1682cd038dSYoshinobu Inoue * may be used to endorse or promote products derived from this software
1782cd038dSYoshinobu Inoue * without specific prior written permission.
1882cd038dSYoshinobu Inoue *
1982cd038dSYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2082cd038dSYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2182cd038dSYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2282cd038dSYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2382cd038dSYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2482cd038dSYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2582cd038dSYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2682cd038dSYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2782cd038dSYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2882cd038dSYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2982cd038dSYoshinobu Inoue * SUCH DAMAGE.
30b48287a3SDavid E. O'Brien *
31b48287a3SDavid E. O'Brien * $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $
3282cd038dSYoshinobu Inoue */
3382cd038dSYoshinobu Inoue
3482cd038dSYoshinobu Inoue #include <sys/param.h>
3582cd038dSYoshinobu Inoue #include <sys/systm.h>
3682cd038dSYoshinobu Inoue #include <sys/malloc.h>
3782cd038dSYoshinobu Inoue #include <sys/socket.h>
3882cd038dSYoshinobu Inoue #include <sys/sockio.h>
3976ca6f88SJamie Gritton #include <sys/jail.h>
4082cd038dSYoshinobu Inoue #include <sys/kernel.h>
41cc0a3c8cSAndrey V. Elsukov #include <sys/lock.h>
42530c0060SRobert Watson #include <sys/proc.h>
43cc0a3c8cSAndrey V. Elsukov #include <sys/rmlock.h>
4433841545SHajimu UMEMOTO #include <sys/syslog.h>
4582cd038dSYoshinobu Inoue #include <sys/md5.h>
4682cd038dSYoshinobu Inoue
4782cd038dSYoshinobu Inoue #include <net/if.h>
4876039bc8SGleb Smirnoff #include <net/if_var.h>
4982cd038dSYoshinobu Inoue #include <net/if_dl.h>
50*3d0d5b21SJustin Hibbits #include <net/if_private.h>
5182cd038dSYoshinobu Inoue #include <net/if_types.h>
5282cd038dSYoshinobu Inoue #include <net/route.h>
534b79449eSBjoern A. Zeeb #include <net/vnet.h>
5482cd038dSYoshinobu Inoue
5582cd038dSYoshinobu Inoue #include <netinet/in.h>
5682cd038dSYoshinobu Inoue #include <netinet/in_var.h>
5782cd038dSYoshinobu Inoue #include <netinet/if_ether.h>
58e43cc4aeSHajimu UMEMOTO #include <netinet/in_pcb.h>
59eddfbb76SRobert Watson #include <netinet/ip_var.h>
60eddfbb76SRobert Watson #include <netinet/udp.h>
61eddfbb76SRobert Watson #include <netinet/udp_var.h>
6282cd038dSYoshinobu Inoue
63686cdd19SJun-ichiro itojun Hagino #include <netinet/ip6.h>
6482cd038dSYoshinobu Inoue #include <netinet6/ip6_var.h>
6533841545SHajimu UMEMOTO #include <netinet6/in6_var.h>
66e43cc4aeSHajimu UMEMOTO #include <netinet6/in6_pcb.h>
6782cd038dSYoshinobu Inoue #include <netinet6/in6_ifattach.h>
6882cd038dSYoshinobu Inoue #include <netinet6/ip6_var.h>
6982cd038dSYoshinobu Inoue #include <netinet6/nd6.h>
7033cde130SBruce M Simpson #include <netinet6/mld6_var.h>
71686cdd19SJun-ichiro itojun Hagino #include <netinet6/scope6_var.h>
7282cd038dSYoshinobu Inoue
7382cea7e6SBjoern A. Zeeb VNET_DEFINE(unsigned long, in6_maxmtu) = 0;
74eddfbb76SRobert Watson
7582cea7e6SBjoern A. Zeeb #ifdef IP6_AUTO_LINKLOCAL
7682cea7e6SBjoern A. Zeeb VNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL;
7782cea7e6SBjoern A. Zeeb #else
7882cea7e6SBjoern A. Zeeb VNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */
7982cea7e6SBjoern A. Zeeb #endif
8082cea7e6SBjoern A. Zeeb
8182cea7e6SBjoern A. Zeeb VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch);
821e77c105SRobert Watson #define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
83eddfbb76SRobert Watson
84eddfbb76SRobert Watson VNET_DECLARE(struct inpcbinfo, ripcbinfo);
851e77c105SRobert Watson #define V_ripcbinfo VNET(ripcbinfo)
86e43cc4aeSHajimu UMEMOTO
879233d8f3SDavid E. O'Brien static int get_rand_ifid(struct ifnet *, struct in6_addr *);
889233d8f3SDavid E. O'Brien static int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
899233d8f3SDavid E. O'Brien static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
909233d8f3SDavid E. O'Brien static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
919233d8f3SDavid E. O'Brien static int in6_ifattach_loopback(struct ifnet *);
929233d8f3SDavid E. O'Brien static void in6_purgemaddrs(struct ifnet *);
9382cd038dSYoshinobu Inoue
94686cdd19SJun-ichiro itojun Hagino #define EUI64_GBIT 0x01
95686cdd19SJun-ichiro itojun Hagino #define EUI64_UBIT 0x02
96686cdd19SJun-ichiro itojun Hagino #define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
97686cdd19SJun-ichiro itojun Hagino #define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT)
98686cdd19SJun-ichiro itojun Hagino #define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6))
99686cdd19SJun-ichiro itojun Hagino #define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT)
100686cdd19SJun-ichiro itojun Hagino #define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6))
10182cd038dSYoshinobu Inoue
102686cdd19SJun-ichiro itojun Hagino #define IFID_LOCAL(in6) (!EUI64_LOCAL(in6))
103686cdd19SJun-ichiro itojun Hagino #define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
10482cd038dSYoshinobu Inoue
10582cd038dSYoshinobu Inoue /*
10682cd038dSYoshinobu Inoue * Generate a last-resort interface identifier, when the machine has no
10782cd038dSYoshinobu Inoue * IEEE802/EUI64 address sources.
108686cdd19SJun-ichiro itojun Hagino * The goal here is to get an interface identifier that is
109686cdd19SJun-ichiro itojun Hagino * (1) random enough and (2) does not change across reboot.
110686cdd19SJun-ichiro itojun Hagino * We currently use MD5(hostname) for it.
1111272577eSXin LI *
1121272577eSXin LI * in6 - upper 64bits are preserved
11382cd038dSYoshinobu Inoue */
11482cd038dSYoshinobu Inoue static int
get_rand_ifid(struct ifnet * ifp,struct in6_addr * in6)1151272577eSXin LI get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
11682cd038dSYoshinobu Inoue {
11782cd038dSYoshinobu Inoue MD5_CTX ctxt;
11876ca6f88SJamie Gritton struct prison *pr;
11982cd038dSYoshinobu Inoue u_int8_t digest[16];
1204f7d1876SRobert Watson int hostnamelen;
12182cd038dSYoshinobu Inoue
12276ca6f88SJamie Gritton pr = curthread->td_ucred->cr_prison;
12376ca6f88SJamie Gritton mtx_lock(&pr->pr_mtx);
124c1f19219SJamie Gritton hostnamelen = strlen(pr->pr_hostname);
125686cdd19SJun-ichiro itojun Hagino #if 0
126686cdd19SJun-ichiro itojun Hagino /* we need at least several letters as seed for ifid */
12776ca6f88SJamie Gritton if (hostnamelen < 3) {
12876ca6f88SJamie Gritton mtx_unlock(&pr->pr_mtx);
129686cdd19SJun-ichiro itojun Hagino return -1;
13076ca6f88SJamie Gritton }
131686cdd19SJun-ichiro itojun Hagino #endif
132686cdd19SJun-ichiro itojun Hagino
13382cd038dSYoshinobu Inoue /* generate 8 bytes of pseudo-random value. */
13482cd038dSYoshinobu Inoue bzero(&ctxt, sizeof(ctxt));
13582cd038dSYoshinobu Inoue MD5Init(&ctxt);
136c1f19219SJamie Gritton MD5Update(&ctxt, pr->pr_hostname, hostnamelen);
13776ca6f88SJamie Gritton mtx_unlock(&pr->pr_mtx);
13882cd038dSYoshinobu Inoue MD5Final(digest, &ctxt);
13982cd038dSYoshinobu Inoue
140686cdd19SJun-ichiro itojun Hagino /* assumes sizeof(digest) > sizeof(ifid) */
141686cdd19SJun-ichiro itojun Hagino bcopy(digest, &in6->s6_addr[8], 8);
14282cd038dSYoshinobu Inoue
14382cd038dSYoshinobu Inoue /* make sure to set "u" bit to local, and "g" bit to individual. */
144686cdd19SJun-ichiro itojun Hagino in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
145686cdd19SJun-ichiro itojun Hagino in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
146686cdd19SJun-ichiro itojun Hagino
147686cdd19SJun-ichiro itojun Hagino /* convert EUI64 into IPv6 interface identifier */
148686cdd19SJun-ichiro itojun Hagino EUI64_TO_IFID(in6);
14982cd038dSYoshinobu Inoue
15082cd038dSYoshinobu Inoue return 0;
15182cd038dSYoshinobu Inoue }
15282cd038dSYoshinobu Inoue
15333841545SHajimu UMEMOTO static int
generate_tmp_ifid(u_int8_t * seed0,const u_int8_t * seed1,u_int8_t * ret)1541272577eSXin LI generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
15533841545SHajimu UMEMOTO {
15633841545SHajimu UMEMOTO MD5_CTX ctxt;
15733841545SHajimu UMEMOTO u_int8_t seed[16], digest[16], nullbuf[8];
15833841545SHajimu UMEMOTO u_int32_t val32;
15933841545SHajimu UMEMOTO
1601272577eSXin LI /* If there's no history, start with a random seed. */
16133841545SHajimu UMEMOTO bzero(nullbuf, sizeof(nullbuf));
16233841545SHajimu UMEMOTO if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
16333841545SHajimu UMEMOTO int i;
16433841545SHajimu UMEMOTO
16533841545SHajimu UMEMOTO for (i = 0; i < 2; i++) {
166a02e1e2bSHajimu UMEMOTO val32 = arc4random();
16733841545SHajimu UMEMOTO bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
16833841545SHajimu UMEMOTO }
1697efe5d92SHajimu UMEMOTO } else
17033841545SHajimu UMEMOTO bcopy(seed0, seed, 8);
17133841545SHajimu UMEMOTO
17233841545SHajimu UMEMOTO /* copy the right-most 64-bits of the given address */
17333841545SHajimu UMEMOTO /* XXX assumption on the size of IFID */
17433841545SHajimu UMEMOTO bcopy(seed1, &seed[8], 8);
17533841545SHajimu UMEMOTO
17633841545SHajimu UMEMOTO if (0) { /* for debugging purposes only */
17733841545SHajimu UMEMOTO int i;
17833841545SHajimu UMEMOTO
17933841545SHajimu UMEMOTO printf("generate_tmp_ifid: new randomized ID from: ");
18033841545SHajimu UMEMOTO for (i = 0; i < 16; i++)
18133841545SHajimu UMEMOTO printf("%02x", seed[i]);
18233841545SHajimu UMEMOTO printf(" ");
18333841545SHajimu UMEMOTO }
18433841545SHajimu UMEMOTO
18533841545SHajimu UMEMOTO /* generate 16 bytes of pseudo-random value. */
18633841545SHajimu UMEMOTO bzero(&ctxt, sizeof(ctxt));
18733841545SHajimu UMEMOTO MD5Init(&ctxt);
18833841545SHajimu UMEMOTO MD5Update(&ctxt, seed, sizeof(seed));
18933841545SHajimu UMEMOTO MD5Final(digest, &ctxt);
19033841545SHajimu UMEMOTO
19133841545SHajimu UMEMOTO /*
19233841545SHajimu UMEMOTO * RFC 3041 3.2.1. (3)
19333841545SHajimu UMEMOTO * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
19433841545SHajimu UMEMOTO * left-most bit is numbered 0) to zero.
19533841545SHajimu UMEMOTO */
19633841545SHajimu UMEMOTO bcopy(digest, ret, 8);
19733841545SHajimu UMEMOTO ret[0] &= ~EUI64_UBIT;
19833841545SHajimu UMEMOTO
19933841545SHajimu UMEMOTO /*
20033841545SHajimu UMEMOTO * XXX: we'd like to ensure that the generated value is not zero
20133841545SHajimu UMEMOTO * for simplicity. If the caclculated digest happens to be zero,
20233841545SHajimu UMEMOTO * use a random non-zero value as the last resort.
20333841545SHajimu UMEMOTO */
20433841545SHajimu UMEMOTO if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
2052ce62dceSSUZUKI Shinsuke nd6log((LOG_INFO,
2062ce62dceSSUZUKI Shinsuke "generate_tmp_ifid: computed MD5 value is zero.\n"));
20733841545SHajimu UMEMOTO
208a02e1e2bSHajimu UMEMOTO val32 = arc4random();
20933841545SHajimu UMEMOTO val32 = 1 + (val32 % (0xffffffff - 1));
21033841545SHajimu UMEMOTO }
21133841545SHajimu UMEMOTO
21233841545SHajimu UMEMOTO /*
21333841545SHajimu UMEMOTO * RFC 3041 3.2.1. (4)
21433841545SHajimu UMEMOTO * Take the rightmost 64-bits of the MD5 digest and save them in
21533841545SHajimu UMEMOTO * stable storage as the history value to be used in the next
21633841545SHajimu UMEMOTO * iteration of the algorithm.
21733841545SHajimu UMEMOTO */
21833841545SHajimu UMEMOTO bcopy(&digest[8], seed0, 8);
21933841545SHajimu UMEMOTO
22033841545SHajimu UMEMOTO if (0) { /* for debugging purposes only */
22133841545SHajimu UMEMOTO int i;
22233841545SHajimu UMEMOTO
22333841545SHajimu UMEMOTO printf("to: ");
22433841545SHajimu UMEMOTO for (i = 0; i < 16; i++)
22533841545SHajimu UMEMOTO printf("%02x", digest[i]);
22633841545SHajimu UMEMOTO printf("\n");
22733841545SHajimu UMEMOTO }
22833841545SHajimu UMEMOTO
22933841545SHajimu UMEMOTO return 0;
23033841545SHajimu UMEMOTO }
23133841545SHajimu UMEMOTO
23282cd038dSYoshinobu Inoue /*
233686cdd19SJun-ichiro itojun Hagino * Get interface identifier for the specified interface.
234686cdd19SJun-ichiro itojun Hagino * XXX assumes single sockaddr_dl (AF_LINK address) per an interface
2351272577eSXin LI *
2361272577eSXin LI * in6 - upper 64bits are preserved
23782cd038dSYoshinobu Inoue */
238d28bde66SSUZUKI Shinsuke int
in6_get_hw_ifid(struct ifnet * ifp,struct in6_addr * in6)2391272577eSXin LI in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
24082cd038dSYoshinobu Inoue {
241686cdd19SJun-ichiro itojun Hagino struct ifaddr *ifa;
242686cdd19SJun-ichiro itojun Hagino struct sockaddr_dl *sdl;
243686cdd19SJun-ichiro itojun Hagino u_int8_t *addr;
244686cdd19SJun-ichiro itojun Hagino size_t addrlen;
245686cdd19SJun-ichiro itojun Hagino static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
246686cdd19SJun-ichiro itojun Hagino static u_int8_t allone[8] =
247686cdd19SJun-ichiro itojun Hagino { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
248686cdd19SJun-ichiro itojun Hagino
249b8a6e03fSGleb Smirnoff NET_EPOCH_ASSERT();
250b8a6e03fSGleb Smirnoff
251d7c5a620SMatt Macy CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
25282cd038dSYoshinobu Inoue if (ifa->ifa_addr->sa_family != AF_LINK)
25382cd038dSYoshinobu Inoue continue;
25482cd038dSYoshinobu Inoue sdl = (struct sockaddr_dl *)ifa->ifa_addr;
25582cd038dSYoshinobu Inoue if (sdl == NULL)
25682cd038dSYoshinobu Inoue continue;
25782cd038dSYoshinobu Inoue if (sdl->sdl_alen == 0)
25882cd038dSYoshinobu Inoue continue;
259686cdd19SJun-ichiro itojun Hagino
260686cdd19SJun-ichiro itojun Hagino goto found;
261686cdd19SJun-ichiro itojun Hagino }
262686cdd19SJun-ichiro itojun Hagino
263686cdd19SJun-ichiro itojun Hagino return -1;
264686cdd19SJun-ichiro itojun Hagino
265686cdd19SJun-ichiro itojun Hagino found:
266686cdd19SJun-ichiro itojun Hagino addr = LLADDR(sdl);
267686cdd19SJun-ichiro itojun Hagino addrlen = sdl->sdl_alen;
268686cdd19SJun-ichiro itojun Hagino
269686cdd19SJun-ichiro itojun Hagino /* get EUI64 */
27082cd038dSYoshinobu Inoue switch (ifp->if_type) {
271af805644SHiroki Sato case IFT_BRIDGE:
27282cd038dSYoshinobu Inoue case IFT_ETHER:
273e9a23b55SJohn Hay case IFT_L2VLAN:
27482cd038dSYoshinobu Inoue case IFT_ATM:
27533841545SHajimu UMEMOTO case IFT_IEEE1394:
27682cd038dSYoshinobu Inoue /* IEEE802/EUI64 cases - what others? */
27733841545SHajimu UMEMOTO /* IEEE1394 uses 16byte length address starting with EUI64 */
27833841545SHajimu UMEMOTO if (addrlen > 8)
27933841545SHajimu UMEMOTO addrlen = 8;
280686cdd19SJun-ichiro itojun Hagino
281686cdd19SJun-ichiro itojun Hagino /* look at IEEE802/EUI64 only */
282b8a6e03fSGleb Smirnoff if (addrlen != 8 && addrlen != 6)
283686cdd19SJun-ichiro itojun Hagino return -1;
284686cdd19SJun-ichiro itojun Hagino
28582cd038dSYoshinobu Inoue /*
286686cdd19SJun-ichiro itojun Hagino * check for invalid MAC address - on bsdi, we see it a lot
287686cdd19SJun-ichiro itojun Hagino * since wildboar configures all-zero MAC on pccard before
288686cdd19SJun-ichiro itojun Hagino * card insertion.
28982cd038dSYoshinobu Inoue */
290b8a6e03fSGleb Smirnoff if (bcmp(addr, allzero, addrlen) == 0)
291686cdd19SJun-ichiro itojun Hagino return -1;
292b8a6e03fSGleb Smirnoff if (bcmp(addr, allone, addrlen) == 0)
293686cdd19SJun-ichiro itojun Hagino return -1;
294686cdd19SJun-ichiro itojun Hagino
295686cdd19SJun-ichiro itojun Hagino /* make EUI64 address */
296686cdd19SJun-ichiro itojun Hagino if (addrlen == 8)
297686cdd19SJun-ichiro itojun Hagino bcopy(addr, &in6->s6_addr[8], 8);
298686cdd19SJun-ichiro itojun Hagino else if (addrlen == 6) {
299686cdd19SJun-ichiro itojun Hagino in6->s6_addr[8] = addr[0];
300686cdd19SJun-ichiro itojun Hagino in6->s6_addr[9] = addr[1];
301686cdd19SJun-ichiro itojun Hagino in6->s6_addr[10] = addr[2];
302686cdd19SJun-ichiro itojun Hagino in6->s6_addr[11] = 0xff;
303686cdd19SJun-ichiro itojun Hagino in6->s6_addr[12] = 0xfe;
304686cdd19SJun-ichiro itojun Hagino in6->s6_addr[13] = addr[3];
305686cdd19SJun-ichiro itojun Hagino in6->s6_addr[14] = addr[4];
306686cdd19SJun-ichiro itojun Hagino in6->s6_addr[15] = addr[5];
307686cdd19SJun-ichiro itojun Hagino }
30882cd038dSYoshinobu Inoue break;
309686cdd19SJun-ichiro itojun Hagino
310686cdd19SJun-ichiro itojun Hagino case IFT_GIF:
311686cdd19SJun-ichiro itojun Hagino case IFT_STF:
312686cdd19SJun-ichiro itojun Hagino /*
31333841545SHajimu UMEMOTO * RFC2893 says: "SHOULD use IPv4 address as ifid source".
314686cdd19SJun-ichiro itojun Hagino * however, IPv4 address is not very suitable as unique
315686cdd19SJun-ichiro itojun Hagino * identifier source (can be renumbered).
316686cdd19SJun-ichiro itojun Hagino * we don't do this.
317686cdd19SJun-ichiro itojun Hagino */
318686cdd19SJun-ichiro itojun Hagino return -1;
31982cd038dSYoshinobu Inoue
320c4cc6097SKonstantin Belousov case IFT_INFINIBAND:
321b8a6e03fSGleb Smirnoff if (addrlen != 20)
322c4cc6097SKonstantin Belousov return -1;
323c4cc6097SKonstantin Belousov bcopy(addr + 12, &in6->s6_addr[8], 8);
324c4cc6097SKonstantin Belousov break;
325c4cc6097SKonstantin Belousov
326686cdd19SJun-ichiro itojun Hagino default:
327686cdd19SJun-ichiro itojun Hagino return -1;
328686cdd19SJun-ichiro itojun Hagino }
32982cd038dSYoshinobu Inoue
330686cdd19SJun-ichiro itojun Hagino /* sanity check: g bit must not indicate "group" */
331b8a6e03fSGleb Smirnoff if (EUI64_GROUP(in6))
332686cdd19SJun-ichiro itojun Hagino return -1;
33382cd038dSYoshinobu Inoue
334686cdd19SJun-ichiro itojun Hagino /* convert EUI64 into IPv6 interface identifier */
335686cdd19SJun-ichiro itojun Hagino EUI64_TO_IFID(in6);
336686cdd19SJun-ichiro itojun Hagino
337686cdd19SJun-ichiro itojun Hagino /*
338686cdd19SJun-ichiro itojun Hagino * sanity check: ifid must not be all zero, avoid conflict with
339686cdd19SJun-ichiro itojun Hagino * subnet router anycast
340686cdd19SJun-ichiro itojun Hagino */
341686cdd19SJun-ichiro itojun Hagino if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
342b8a6e03fSGleb Smirnoff bcmp(&in6->s6_addr[9], allzero, 7) == 0)
343686cdd19SJun-ichiro itojun Hagino return -1;
34482cd038dSYoshinobu Inoue
34582cd038dSYoshinobu Inoue return 0;
346686cdd19SJun-ichiro itojun Hagino }
347686cdd19SJun-ichiro itojun Hagino
348686cdd19SJun-ichiro itojun Hagino /*
349686cdd19SJun-ichiro itojun Hagino * Get interface identifier for the specified interface. If it is not
350686cdd19SJun-ichiro itojun Hagino * available on ifp0, borrow interface identifier from other information
351686cdd19SJun-ichiro itojun Hagino * sources.
3521272577eSXin LI *
3531272577eSXin LI * altifp - secondary EUI64 source
354686cdd19SJun-ichiro itojun Hagino */
355686cdd19SJun-ichiro itojun Hagino static int
get_ifid(struct ifnet * ifp0,struct ifnet * altifp,struct in6_addr * in6)3561272577eSXin LI get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
3571272577eSXin LI struct in6_addr *in6)
358686cdd19SJun-ichiro itojun Hagino {
359686cdd19SJun-ichiro itojun Hagino struct ifnet *ifp;
360686cdd19SJun-ichiro itojun Hagino
361b8a6e03fSGleb Smirnoff NET_EPOCH_ASSERT();
362b8a6e03fSGleb Smirnoff
363686cdd19SJun-ichiro itojun Hagino /* first, try to get it from the interface itself */
364d28bde66SSUZUKI Shinsuke if (in6_get_hw_ifid(ifp0, in6) == 0) {
36533841545SHajimu UMEMOTO nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
36633841545SHajimu UMEMOTO if_name(ifp0)));
367686cdd19SJun-ichiro itojun Hagino goto success;
368686cdd19SJun-ichiro itojun Hagino }
369686cdd19SJun-ichiro itojun Hagino
370686cdd19SJun-ichiro itojun Hagino /* try secondary EUI64 source. this basically is for ATM PVC */
371d28bde66SSUZUKI Shinsuke if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
37233841545SHajimu UMEMOTO nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
37333841545SHajimu UMEMOTO if_name(ifp0), if_name(altifp)));
374686cdd19SJun-ichiro itojun Hagino goto success;
375686cdd19SJun-ichiro itojun Hagino }
376686cdd19SJun-ichiro itojun Hagino
377686cdd19SJun-ichiro itojun Hagino /* next, try to get it from some other hardware interface */
3784f6c66ccSMatt Macy CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
379686cdd19SJun-ichiro itojun Hagino if (ifp == ifp0)
380686cdd19SJun-ichiro itojun Hagino continue;
381d28bde66SSUZUKI Shinsuke if (in6_get_hw_ifid(ifp, in6) != 0)
382686cdd19SJun-ichiro itojun Hagino continue;
383686cdd19SJun-ichiro itojun Hagino
384686cdd19SJun-ichiro itojun Hagino /*
385686cdd19SJun-ichiro itojun Hagino * to borrow ifid from other interface, ifid needs to be
386686cdd19SJun-ichiro itojun Hagino * globally unique
387686cdd19SJun-ichiro itojun Hagino */
388686cdd19SJun-ichiro itojun Hagino if (IFID_UNIVERSAL(in6)) {
38933841545SHajimu UMEMOTO nd6log((LOG_DEBUG,
39033841545SHajimu UMEMOTO "%s: borrow interface identifier from %s\n",
39133841545SHajimu UMEMOTO if_name(ifp0), if_name(ifp)));
392686cdd19SJun-ichiro itojun Hagino goto success;
393686cdd19SJun-ichiro itojun Hagino }
394686cdd19SJun-ichiro itojun Hagino }
395686cdd19SJun-ichiro itojun Hagino
396686cdd19SJun-ichiro itojun Hagino /* last resort: get from random number source */
397686cdd19SJun-ichiro itojun Hagino if (get_rand_ifid(ifp, in6) == 0) {
39833841545SHajimu UMEMOTO nd6log((LOG_DEBUG,
39933841545SHajimu UMEMOTO "%s: interface identifier generated by random number\n",
40033841545SHajimu UMEMOTO if_name(ifp0)));
401686cdd19SJun-ichiro itojun Hagino goto success;
402686cdd19SJun-ichiro itojun Hagino }
403686cdd19SJun-ichiro itojun Hagino
404de9c893eSJun-ichiro itojun Hagino printf("%s: failed to get interface identifier\n", if_name(ifp0));
405686cdd19SJun-ichiro itojun Hagino return -1;
406686cdd19SJun-ichiro itojun Hagino
407686cdd19SJun-ichiro itojun Hagino success:
4087efe5d92SHajimu UMEMOTO nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
4097efe5d92SHajimu UMEMOTO if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
4107efe5d92SHajimu UMEMOTO in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
41133841545SHajimu UMEMOTO in6->s6_addr[14], in6->s6_addr[15]));
412686cdd19SJun-ichiro itojun Hagino return 0;
413686cdd19SJun-ichiro itojun Hagino }
414686cdd19SJun-ichiro itojun Hagino
4151272577eSXin LI /*
4161272577eSXin LI * altifp - secondary EUI64 source
4171272577eSXin LI */
418686cdd19SJun-ichiro itojun Hagino static int
in6_ifattach_linklocal(struct ifnet * ifp,struct ifnet * altifp)4191272577eSXin LI in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
420686cdd19SJun-ichiro itojun Hagino {
421686cdd19SJun-ichiro itojun Hagino struct in6_ifaddr *ia;
42233841545SHajimu UMEMOTO struct in6_aliasreq ifra;
423743eee66SSUZUKI Shinsuke struct nd_prefixctl pr0;
424ef2e580eSGleb Smirnoff struct epoch_tracker et;
425d748f7efSMark Johnston struct nd_prefix *pr;
4261dc8f6a8SAlexander V. Chernikov int error;
427686cdd19SJun-ichiro itojun Hagino
428686cdd19SJun-ichiro itojun Hagino /*
42933841545SHajimu UMEMOTO * configure link-local address.
430686cdd19SJun-ichiro itojun Hagino */
4319080e7d0SAlexander V. Chernikov in6_prepare_ifra(&ifra, NULL, &in6mask64);
432686cdd19SJun-ichiro itojun Hagino
433a1f7e5f8SHajimu UMEMOTO ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
43433841545SHajimu UMEMOTO ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
43533841545SHajimu UMEMOTO if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
43633841545SHajimu UMEMOTO ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
43733841545SHajimu UMEMOTO ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
43833841545SHajimu UMEMOTO } else {
439ef2e580eSGleb Smirnoff NET_EPOCH_ENTER(et);
440ef2e580eSGleb Smirnoff error = get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr);
441ef2e580eSGleb Smirnoff NET_EPOCH_EXIT(et);
442ef2e580eSGleb Smirnoff if (error != 0) {
44333841545SHajimu UMEMOTO nd6log((LOG_ERR,
44433841545SHajimu UMEMOTO "%s: no ifid available\n", if_name(ifp)));
4457efe5d92SHajimu UMEMOTO return (-1);
44633841545SHajimu UMEMOTO }
44733841545SHajimu UMEMOTO }
448a1f7e5f8SHajimu UMEMOTO if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
449a1f7e5f8SHajimu UMEMOTO return (-1);
45033841545SHajimu UMEMOTO
45133841545SHajimu UMEMOTO /* link-local addresses should NEVER expire. */
45233841545SHajimu UMEMOTO ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
45333841545SHajimu UMEMOTO ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
454686cdd19SJun-ichiro itojun Hagino
45533841545SHajimu UMEMOTO /*
45633841545SHajimu UMEMOTO * Now call in6_update_ifa() to do a bunch of procedures to configure
4572ce62dceSSUZUKI Shinsuke * a link-local address. We can set the 3rd argument to NULL, because
45888ff5695SSUZUKI Shinsuke * we know there's no other link-local address on the interface
45988ff5695SSUZUKI Shinsuke * and therefore we are adding one (instead of updating one).
46033841545SHajimu UMEMOTO */
461743eee66SSUZUKI Shinsuke if ((error = in6_update_ifa(ifp, &ifra, NULL,
462743eee66SSUZUKI Shinsuke IN6_IFAUPDATE_DADDELAY)) != 0) {
46333841545SHajimu UMEMOTO /*
46433841545SHajimu UMEMOTO * XXX: When the interface does not support IPv6, this call
46533841545SHajimu UMEMOTO * would fail in the SIOCSIFADDR ioctl. I believe the
46633841545SHajimu UMEMOTO * notification is rather confusing in this case, so just
4677efe5d92SHajimu UMEMOTO * suppress it. (jinmei@kame.net 20010130)
46833841545SHajimu UMEMOTO */
46933841545SHajimu UMEMOTO if (error != EAFNOSUPPORT)
4702ce62dceSSUZUKI Shinsuke nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
47133841545SHajimu UMEMOTO "configure a link-local address on %s "
47233841545SHajimu UMEMOTO "(errno=%d)\n",
4732ce62dceSSUZUKI Shinsuke if_name(ifp), error));
47433841545SHajimu UMEMOTO return (-1);
475686cdd19SJun-ichiro itojun Hagino }
47633841545SHajimu UMEMOTO
477ef2e580eSGleb Smirnoff NET_EPOCH_ENTER(et);
47868b84087SEric van Gyzen ia = in6ifa_ifpforlinklocal(ifp, 0);
479ef2e580eSGleb Smirnoff NET_EPOCH_EXIT(et);
48068b84087SEric van Gyzen if (ia == NULL) {
48168b84087SEric van Gyzen /*
48268b84087SEric van Gyzen * Another thread removed the address that we just added.
48368b84087SEric van Gyzen * This should be rare, but it happens.
48468b84087SEric van Gyzen */
48568b84087SEric van Gyzen nd6log((LOG_NOTICE, "%s: %s: new link-local address "
48668b84087SEric van Gyzen "disappeared\n", __func__, if_name(ifp)));
48768b84087SEric van Gyzen return (-1);
48868b84087SEric van Gyzen }
4898c0fec80SRobert Watson ifa_free(&ia->ia_ifa);
490686cdd19SJun-ichiro itojun Hagino
49133841545SHajimu UMEMOTO /*
4927efe5d92SHajimu UMEMOTO * Make the link-local prefix (fe80::%link/64) as on-link.
49333841545SHajimu UMEMOTO * Since we'd like to manage prefixes separately from addresses,
49433841545SHajimu UMEMOTO * we make an ND6 prefix structure for the link-local prefix,
49533841545SHajimu UMEMOTO * and add it to the prefix list as a never-expire prefix.
49633841545SHajimu UMEMOTO * XXX: this change might affect some existing code base...
49733841545SHajimu UMEMOTO */
49833841545SHajimu UMEMOTO bzero(&pr0, sizeof(pr0));
49933841545SHajimu UMEMOTO pr0.ndpr_ifp = ifp;
50033841545SHajimu UMEMOTO /* this should be 64 at this moment. */
50133841545SHajimu UMEMOTO pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
50233841545SHajimu UMEMOTO pr0.ndpr_prefix = ifra.ifra_addr;
50333841545SHajimu UMEMOTO /* apply the mask for safety. (nd6_prelist_add will apply it again) */
5041dc8f6a8SAlexander V. Chernikov IN6_MASK_ADDR(&pr0.ndpr_prefix.sin6_addr, &in6mask64);
50533841545SHajimu UMEMOTO /*
50633841545SHajimu UMEMOTO * Initialize parameters. The link-local prefix must always be
50733841545SHajimu UMEMOTO * on-link, and its lifetimes never expire.
50833841545SHajimu UMEMOTO */
50933841545SHajimu UMEMOTO pr0.ndpr_raf_onlink = 1;
51033841545SHajimu UMEMOTO pr0.ndpr_raf_auto = 1; /* probably meaningless */
51133841545SHajimu UMEMOTO pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
51233841545SHajimu UMEMOTO pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
51333841545SHajimu UMEMOTO /*
51433841545SHajimu UMEMOTO * Since there is no other link-local addresses, nd6_prefix_lookup()
51533841545SHajimu UMEMOTO * probably returns NULL. However, we cannot always expect the result.
51633841545SHajimu UMEMOTO * For example, if we first remove the (only) existing link-local
51733841545SHajimu UMEMOTO * address, and then reconfigure another one, the prefix is still
51833841545SHajimu UMEMOTO * valid with referring to the old link-local address.
51933841545SHajimu UMEMOTO */
520d748f7efSMark Johnston if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
521e58c8da0SAlexander V. Chernikov if ((error = nd6_prelist_add(&pr0, NULL, &pr)) != 0)
52233841545SHajimu UMEMOTO return (error);
523e58c8da0SAlexander V. Chernikov /* Reference prefix */
524e58c8da0SAlexander V. Chernikov ia->ia6_ndpr = pr;
525e58c8da0SAlexander V. Chernikov pr->ndpr_addrcnt++;
526d748f7efSMark Johnston } else
527d748f7efSMark Johnston nd6_prefix_rele(pr);
528686cdd19SJun-ichiro itojun Hagino
529686cdd19SJun-ichiro itojun Hagino return 0;
530686cdd19SJun-ichiro itojun Hagino }
531686cdd19SJun-ichiro itojun Hagino
5321272577eSXin LI /*
5331272577eSXin LI * ifp - must be IFT_LOOP
5341272577eSXin LI */
535686cdd19SJun-ichiro itojun Hagino static int
in6_ifattach_loopback(struct ifnet * ifp)5361272577eSXin LI in6_ifattach_loopback(struct ifnet *ifp)
537686cdd19SJun-ichiro itojun Hagino {
53833841545SHajimu UMEMOTO struct in6_aliasreq ifra;
53933841545SHajimu UMEMOTO int error;
54033841545SHajimu UMEMOTO
5419080e7d0SAlexander V. Chernikov in6_prepare_ifra(&ifra, &in6addr_loopback, &in6mask128);
542686cdd19SJun-ichiro itojun Hagino
543686cdd19SJun-ichiro itojun Hagino /*
544686cdd19SJun-ichiro itojun Hagino * Always initialize ia_dstaddr (= broadcast address) to loopback
54533841545SHajimu UMEMOTO * address. Follows IPv4 practice - see in_ifinit().
546686cdd19SJun-ichiro itojun Hagino */
54733841545SHajimu UMEMOTO ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
54833841545SHajimu UMEMOTO ifra.ifra_dstaddr.sin6_family = AF_INET6;
54933841545SHajimu UMEMOTO ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
550686cdd19SJun-ichiro itojun Hagino
55133841545SHajimu UMEMOTO /* the loopback address should NEVER expire. */
55233841545SHajimu UMEMOTO ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
55333841545SHajimu UMEMOTO ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
554686cdd19SJun-ichiro itojun Hagino
55533841545SHajimu UMEMOTO /*
55688ff5695SSUZUKI Shinsuke * We are sure that this is a newly assigned address, so we can set
55788ff5695SSUZUKI Shinsuke * NULL to the 3rd arg.
55833841545SHajimu UMEMOTO */
559743eee66SSUZUKI Shinsuke if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
5602ce62dceSSUZUKI Shinsuke nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
56133841545SHajimu UMEMOTO "the loopback address on %s (errno=%d)\n",
5622ce62dceSSUZUKI Shinsuke if_name(ifp), error));
56333841545SHajimu UMEMOTO return (-1);
564686cdd19SJun-ichiro itojun Hagino }
565686cdd19SJun-ichiro itojun Hagino
566686cdd19SJun-ichiro itojun Hagino return 0;
567686cdd19SJun-ichiro itojun Hagino }
568686cdd19SJun-ichiro itojun Hagino
569686cdd19SJun-ichiro itojun Hagino /*
570686cdd19SJun-ichiro itojun Hagino * compute NI group address, based on the current hostname setting.
5715df1b6b5SHiroki Sato * see RFC 4620.
572686cdd19SJun-ichiro itojun Hagino *
573686cdd19SJun-ichiro itojun Hagino * when ifp == NULL, the caller is responsible for filling scopeid.
5745df1b6b5SHiroki Sato *
5755df1b6b5SHiroki Sato * If oldmcprefix == 1, FF02:0:0:0:0:2::/96 is used for NI group address
5765df1b6b5SHiroki Sato * while it is FF02:0:0:0:0:2:FF00::/104 in RFC 4620.
577686cdd19SJun-ichiro itojun Hagino */
5785df1b6b5SHiroki Sato static int
in6_nigroup0(struct ifnet * ifp,const char * name,int namelen,struct in6_addr * in6,int oldmcprefix)5795df1b6b5SHiroki Sato in6_nigroup0(struct ifnet *ifp, const char *name, int namelen,
5805df1b6b5SHiroki Sato struct in6_addr *in6, int oldmcprefix)
581686cdd19SJun-ichiro itojun Hagino {
58276ca6f88SJamie Gritton struct prison *pr;
583686cdd19SJun-ichiro itojun Hagino const char *p;
58433841545SHajimu UMEMOTO u_char *q;
585686cdd19SJun-ichiro itojun Hagino MD5_CTX ctxt;
586686cdd19SJun-ichiro itojun Hagino u_int8_t digest[16];
587686cdd19SJun-ichiro itojun Hagino char l;
58833841545SHajimu UMEMOTO char n[64]; /* a single label must not exceed 63 chars */
589686cdd19SJun-ichiro itojun Hagino
5900304c731SJamie Gritton /*
5910304c731SJamie Gritton * If no name is given and namelen is -1,
5920304c731SJamie Gritton * we try to do the hostname lookup ourselves.
5930304c731SJamie Gritton */
5940304c731SJamie Gritton if (!name && namelen == -1) {
59576ca6f88SJamie Gritton pr = curthread->td_ucred->cr_prison;
59676ca6f88SJamie Gritton mtx_lock(&pr->pr_mtx);
597c1f19219SJamie Gritton name = pr->pr_hostname;
5980304c731SJamie Gritton namelen = strlen(name);
5990304c731SJamie Gritton } else
60076ca6f88SJamie Gritton pr = NULL;
6010304c731SJamie Gritton if (!name || !namelen) {
60276ca6f88SJamie Gritton if (pr != NULL)
60376ca6f88SJamie Gritton mtx_unlock(&pr->pr_mtx);
604686cdd19SJun-ichiro itojun Hagino return -1;
6050304c731SJamie Gritton }
606686cdd19SJun-ichiro itojun Hagino
607686cdd19SJun-ichiro itojun Hagino p = name;
608686cdd19SJun-ichiro itojun Hagino while (p && *p && *p != '.' && p - name < namelen)
609686cdd19SJun-ichiro itojun Hagino p++;
6100304c731SJamie Gritton if (p == name || p - name > sizeof(n) - 1) {
61176ca6f88SJamie Gritton if (pr != NULL)
61276ca6f88SJamie Gritton mtx_unlock(&pr->pr_mtx);
613686cdd19SJun-ichiro itojun Hagino return -1; /* label too long */
6140304c731SJamie Gritton }
615686cdd19SJun-ichiro itojun Hagino l = p - name;
61633841545SHajimu UMEMOTO strncpy(n, name, l);
61776ca6f88SJamie Gritton if (pr != NULL)
61876ca6f88SJamie Gritton mtx_unlock(&pr->pr_mtx);
61933841545SHajimu UMEMOTO n[(int)l] = '\0';
62033841545SHajimu UMEMOTO for (q = n; *q; q++) {
62133841545SHajimu UMEMOTO if ('A' <= *q && *q <= 'Z')
62233841545SHajimu UMEMOTO *q = *q - 'A' + 'a';
62333841545SHajimu UMEMOTO }
624686cdd19SJun-ichiro itojun Hagino
6255df1b6b5SHiroki Sato /* generate 16 bytes of pseudo-random value. */
626686cdd19SJun-ichiro itojun Hagino bzero(&ctxt, sizeof(ctxt));
627686cdd19SJun-ichiro itojun Hagino MD5Init(&ctxt);
628686cdd19SJun-ichiro itojun Hagino MD5Update(&ctxt, &l, sizeof(l));
62933841545SHajimu UMEMOTO MD5Update(&ctxt, n, l);
630686cdd19SJun-ichiro itojun Hagino MD5Final(digest, &ctxt);
631686cdd19SJun-ichiro itojun Hagino
632686cdd19SJun-ichiro itojun Hagino bzero(in6, sizeof(*in6));
6332ce62dceSSUZUKI Shinsuke in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
634686cdd19SJun-ichiro itojun Hagino in6->s6_addr8[11] = 2;
6355df1b6b5SHiroki Sato if (oldmcprefix == 0) {
6365df1b6b5SHiroki Sato in6->s6_addr8[12] = 0xff;
6375df1b6b5SHiroki Sato /* Copy the first 24 bits of 128-bit hash into the address. */
6385df1b6b5SHiroki Sato bcopy(digest, &in6->s6_addr8[13], 3);
6395df1b6b5SHiroki Sato } else {
6405df1b6b5SHiroki Sato /* Copy the first 32 bits of 128-bit hash into the address. */
641686cdd19SJun-ichiro itojun Hagino bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
6425df1b6b5SHiroki Sato }
643a1f7e5f8SHajimu UMEMOTO if (in6_setscope(in6, ifp, NULL))
644a1f7e5f8SHajimu UMEMOTO return (-1); /* XXX: should not fail */
645686cdd19SJun-ichiro itojun Hagino
646686cdd19SJun-ichiro itojun Hagino return 0;
647686cdd19SJun-ichiro itojun Hagino }
648686cdd19SJun-ichiro itojun Hagino
6495df1b6b5SHiroki Sato int
in6_nigroup(struct ifnet * ifp,const char * name,int namelen,struct in6_addr * in6)6505df1b6b5SHiroki Sato in6_nigroup(struct ifnet *ifp, const char *name, int namelen,
6515df1b6b5SHiroki Sato struct in6_addr *in6)
6525df1b6b5SHiroki Sato {
6535df1b6b5SHiroki Sato
6545df1b6b5SHiroki Sato return (in6_nigroup0(ifp, name, namelen, in6, 0));
6555df1b6b5SHiroki Sato }
6565df1b6b5SHiroki Sato
6575df1b6b5SHiroki Sato int
in6_nigroup_oldmcprefix(struct ifnet * ifp,const char * name,int namelen,struct in6_addr * in6)6585df1b6b5SHiroki Sato in6_nigroup_oldmcprefix(struct ifnet *ifp, const char *name, int namelen,
6595df1b6b5SHiroki Sato struct in6_addr *in6)
6605df1b6b5SHiroki Sato {
6615df1b6b5SHiroki Sato
6625df1b6b5SHiroki Sato return (in6_nigroup0(ifp, name, namelen, in6, 1));
6635df1b6b5SHiroki Sato }
6645df1b6b5SHiroki Sato
66582cd038dSYoshinobu Inoue /*
666686cdd19SJun-ichiro itojun Hagino * XXX multiple loopback interface needs more care. for instance,
667686cdd19SJun-ichiro itojun Hagino * nodelocal address needs to be configured onto only one of them.
668686cdd19SJun-ichiro itojun Hagino * XXX multiple link-local address case
6691272577eSXin LI *
6701272577eSXin LI * altifp - secondary EUI64 source
67182cd038dSYoshinobu Inoue */
67282cd038dSYoshinobu Inoue void
in6_ifattach(struct ifnet * ifp,struct ifnet * altifp)6731272577eSXin LI in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
67482cd038dSYoshinobu Inoue {
675686cdd19SJun-ichiro itojun Hagino struct in6_ifaddr *ia;
67633841545SHajimu UMEMOTO
6770de0dd9bSHiroki Sato if (ifp->if_afdata[AF_INET6] == NULL)
678cc5934f5SMax Laier return;
67982cd038dSYoshinobu Inoue /*
680686cdd19SJun-ichiro itojun Hagino * quirks based on interface type
68182cd038dSYoshinobu Inoue */
682686cdd19SJun-ichiro itojun Hagino switch (ifp->if_type) {
683686cdd19SJun-ichiro itojun Hagino case IFT_STF:
68482cd038dSYoshinobu Inoue /*
68588ff5695SSUZUKI Shinsuke * 6to4 interface is a very special kind of beast.
68688ff5695SSUZUKI Shinsuke * no multicast, no linklocal. RFC2529 specifies how to make
68788ff5695SSUZUKI Shinsuke * linklocals for 6to4 interface, but there's no use and
68888ff5695SSUZUKI Shinsuke * it is rather harmful to have one.
68982cd038dSYoshinobu Inoue */
690af805644SHiroki Sato ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL;
691ca1163bdSMark Johnston ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD;
692af805644SHiroki Sato break;
69382cd038dSYoshinobu Inoue default:
69482cd038dSYoshinobu Inoue break;
69582cd038dSYoshinobu Inoue }
69682cd038dSYoshinobu Inoue
697686cdd19SJun-ichiro itojun Hagino /*
698686cdd19SJun-ichiro itojun Hagino * usually, we require multicast capability to the interface
699686cdd19SJun-ichiro itojun Hagino */
700686cdd19SJun-ichiro itojun Hagino if ((ifp->if_flags & IFF_MULTICAST) == 0) {
7012ce62dceSSUZUKI Shinsuke nd6log((LOG_INFO, "in6_ifattach: "
70233841545SHajimu UMEMOTO "%s is not multicast capable, IPv6 not enabled\n",
7032ce62dceSSUZUKI Shinsuke if_name(ifp)));
70482cd038dSYoshinobu Inoue return;
70582cd038dSYoshinobu Inoue }
706686cdd19SJun-ichiro itojun Hagino
707686cdd19SJun-ichiro itojun Hagino /*
70833841545SHajimu UMEMOTO * assign loopback address for loopback interface.
709686cdd19SJun-ichiro itojun Hagino */
71033841545SHajimu UMEMOTO if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
711efc284cbSAndrey V. Elsukov /*
712efc284cbSAndrey V. Elsukov * check that loopback address doesn't exist yet.
713efc284cbSAndrey V. Elsukov */
7148268d82cSAlexander V. Chernikov ia = in6ifa_ifwithaddr(&in6addr_loopback, 0, false);
715efc284cbSAndrey V. Elsukov if (ia == NULL)
716efc284cbSAndrey V. Elsukov in6_ifattach_loopback(ifp);
717686cdd19SJun-ichiro itojun Hagino }
718686cdd19SJun-ichiro itojun Hagino
71933841545SHajimu UMEMOTO /*
72033841545SHajimu UMEMOTO * assign a link-local address, if there's none.
72133841545SHajimu UMEMOTO */
722af805644SHiroki Sato if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
723a283298cSHiroki Sato ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) {
724ef2e580eSGleb Smirnoff struct epoch_tracker et;
725ef2e580eSGleb Smirnoff
726ef2e580eSGleb Smirnoff NET_EPOCH_ENTER(et);
72733841545SHajimu UMEMOTO ia = in6ifa_ifpforlinklocal(ifp, 0);
728ef2e580eSGleb Smirnoff NET_EPOCH_EXIT(et);
729efc284cbSAndrey V. Elsukov if (ia == NULL)
730efc284cbSAndrey V. Elsukov in6_ifattach_linklocal(ifp, altifp);
731efc284cbSAndrey V. Elsukov else
7328c0fec80SRobert Watson ifa_free(&ia->ia_ifa);
73333841545SHajimu UMEMOTO }
73433841545SHajimu UMEMOTO
73582cd038dSYoshinobu Inoue /* update dynamically. */
736603724d3SBjoern A. Zeeb if (V_in6_maxmtu < ifp->if_mtu)
737603724d3SBjoern A. Zeeb V_in6_maxmtu = ifp->if_mtu;
73882cd038dSYoshinobu Inoue }
73982cd038dSYoshinobu Inoue
740686cdd19SJun-ichiro itojun Hagino /*
741686cdd19SJun-ichiro itojun Hagino * NOTE: in6_ifdetach() does not support loopback if at this moment.
74289856f7eSBjoern A. Zeeb *
74389856f7eSBjoern A. Zeeb * When shutting down a VNET we clean up layers top-down. In that case
74489856f7eSBjoern A. Zeeb * upper layer protocols (ulp) are cleaned up already and locks are destroyed
74589856f7eSBjoern A. Zeeb * and we must not call into these cleanup functions anymore, thus purgeulp
74689856f7eSBjoern A. Zeeb * is set to 0 in that case by in6_ifdetach_destroy().
74789856f7eSBjoern A. Zeeb * The normal case of destroying a (cloned) interface still needs to cleanup
74889856f7eSBjoern A. Zeeb * everything related to the interface and will have purgeulp set to 1.
749686cdd19SJun-ichiro itojun Hagino */
75089856f7eSBjoern A. Zeeb static void
_in6_ifdetach(struct ifnet * ifp,int purgeulp)75189856f7eSBjoern A. Zeeb _in6_ifdetach(struct ifnet *ifp, int purgeulp)
75282cd038dSYoshinobu Inoue {
753686cdd19SJun-ichiro itojun Hagino struct ifaddr *ifa, *next;
75482cd038dSYoshinobu Inoue
7556378e1f3SHiroki Sato if (ifp->if_afdata[AF_INET6] == NULL)
7566378e1f3SHiroki Sato return;
7576378e1f3SHiroki Sato
75889856f7eSBjoern A. Zeeb /*
75994a43496SAndrey V. Elsukov * nuke any of IPv6 addresses we have
76094a43496SAndrey V. Elsukov */
761d7c5a620SMatt Macy CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
762686cdd19SJun-ichiro itojun Hagino if (ifa->ifa_addr->sa_family != AF_INET6)
763686cdd19SJun-ichiro itojun Hagino continue;
76433841545SHajimu UMEMOTO in6_purgeaddr(ifa);
765686cdd19SJun-ichiro itojun Hagino }
76689856f7eSBjoern A. Zeeb if (purgeulp) {
76759854ecfSHans Petter Selasky IN6_MULTI_LOCK();
768603724d3SBjoern A. Zeeb in6_pcbpurgeif0(&V_udbinfo, ifp);
769e06e816fSKevin Lo in6_pcbpurgeif0(&V_ulitecbinfo, ifp);
770603724d3SBjoern A. Zeeb in6_pcbpurgeif0(&V_ripcbinfo, ifp);
77159854ecfSHans Petter Selasky IN6_MULTI_UNLOCK();
77289856f7eSBjoern A. Zeeb }
77371498f30SBruce M Simpson /* leave from all multicast groups joined */
77471498f30SBruce M Simpson in6_purgemaddrs(ifp);
775686cdd19SJun-ichiro itojun Hagino
77633841545SHajimu UMEMOTO /*
777d748f7efSMark Johnston * Remove neighbor management table.
778d748f7efSMark Johnston * Enabling the nd6_purge will panic on vmove for interfaces on VNET
779d748f7efSMark Johnston * teardown as the IPv6 layer is cleaned up already and the locks
780d748f7efSMark Johnston * are destroyed.
78133841545SHajimu UMEMOTO */
78289856f7eSBjoern A. Zeeb if (purgeulp)
783686cdd19SJun-ichiro itojun Hagino nd6_purge(ifp);
7843f02eaf3SDon Lewis }
78533841545SHajimu UMEMOTO
78689856f7eSBjoern A. Zeeb void
in6_ifdetach(struct ifnet * ifp)78789856f7eSBjoern A. Zeeb in6_ifdetach(struct ifnet *ifp)
78889856f7eSBjoern A. Zeeb {
78989856f7eSBjoern A. Zeeb
79089856f7eSBjoern A. Zeeb _in6_ifdetach(ifp, 1);
79189856f7eSBjoern A. Zeeb }
79289856f7eSBjoern A. Zeeb
79389856f7eSBjoern A. Zeeb void
in6_ifdetach_destroy(struct ifnet * ifp)79489856f7eSBjoern A. Zeeb in6_ifdetach_destroy(struct ifnet *ifp)
79589856f7eSBjoern A. Zeeb {
79689856f7eSBjoern A. Zeeb
79789856f7eSBjoern A. Zeeb _in6_ifdetach(ifp, 0);
79889856f7eSBjoern A. Zeeb }
79989856f7eSBjoern A. Zeeb
800743eee66SSUZUKI Shinsuke int
in6_get_tmpifid(struct ifnet * ifp,u_int8_t * retbuf,const u_int8_t * baseid,int generate)8011272577eSXin LI in6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
8021272577eSXin LI const u_int8_t *baseid, int generate)
80333841545SHajimu UMEMOTO {
80433841545SHajimu UMEMOTO u_int8_t nullbuf[8];
80531b1bfe1SHajimu UMEMOTO struct nd_ifinfo *ndi = ND_IFINFO(ifp);
80633841545SHajimu UMEMOTO
80733841545SHajimu UMEMOTO bzero(nullbuf, sizeof(nullbuf));
80833841545SHajimu UMEMOTO if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
80933841545SHajimu UMEMOTO /* we've never created a random ID. Create a new one. */
81033841545SHajimu UMEMOTO generate = 1;
81133841545SHajimu UMEMOTO }
81233841545SHajimu UMEMOTO
81333841545SHajimu UMEMOTO if (generate) {
81433841545SHajimu UMEMOTO bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
81533841545SHajimu UMEMOTO
81633841545SHajimu UMEMOTO /* generate_tmp_ifid will update seedn and buf */
81733841545SHajimu UMEMOTO (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
81833841545SHajimu UMEMOTO ndi->randomid);
81933841545SHajimu UMEMOTO }
82033841545SHajimu UMEMOTO bcopy(ndi->randomid, retbuf, 8);
821743eee66SSUZUKI Shinsuke
822743eee66SSUZUKI Shinsuke return (0);
82333841545SHajimu UMEMOTO }
82433841545SHajimu UMEMOTO
82533841545SHajimu UMEMOTO void
in6_tmpaddrtimer(void * arg)826f6dfe47aSMarko Zec in6_tmpaddrtimer(void *arg)
82733841545SHajimu UMEMOTO {
828f6dfe47aSMarko Zec CURVNET_SET((struct vnet *) arg);
8298ee0826fSMark Johnston struct epoch_tracker et;
83033841545SHajimu UMEMOTO struct nd_ifinfo *ndi;
83133841545SHajimu UMEMOTO u_int8_t nullbuf[8];
83231b1bfe1SHajimu UMEMOTO struct ifnet *ifp;
83333841545SHajimu UMEMOTO
834603724d3SBjoern A. Zeeb callout_reset(&V_in6_tmpaddrtimer_ch,
835603724d3SBjoern A. Zeeb (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
836f6dfe47aSMarko Zec V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet);
83733841545SHajimu UMEMOTO
83833841545SHajimu UMEMOTO bzero(nullbuf, sizeof(nullbuf));
8398ee0826fSMark Johnston NET_EPOCH_ENTER(et);
8404f6c66ccSMatt Macy CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
84141541ebfSHiroki Sato if (ifp->if_afdata[AF_INET6] == NULL)
84241541ebfSHiroki Sato continue;
84331b1bfe1SHajimu UMEMOTO ndi = ND_IFINFO(ifp);
84433841545SHajimu UMEMOTO if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
84533841545SHajimu UMEMOTO /*
84633841545SHajimu UMEMOTO * We've been generating a random ID on this interface.
84733841545SHajimu UMEMOTO * Create a new one.
84833841545SHajimu UMEMOTO */
84933841545SHajimu UMEMOTO (void)generate_tmp_ifid(ndi->randomseed0,
8507efe5d92SHajimu UMEMOTO ndi->randomseed1, ndi->randomid);
85133841545SHajimu UMEMOTO }
85233841545SHajimu UMEMOTO }
8538ee0826fSMark Johnston NET_EPOCH_EXIT(et);
854f6dfe47aSMarko Zec CURVNET_RESTORE();
85533841545SHajimu UMEMOTO }
85671498f30SBruce M Simpson
85771498f30SBruce M Simpson static void
in6_purgemaddrs(struct ifnet * ifp)8581272577eSXin LI in6_purgemaddrs(struct ifnet *ifp)
85971498f30SBruce M Simpson {
8602cd6ad76SHans Petter Selasky struct in6_multi_head inmh;
86171498f30SBruce M Simpson
8622cd6ad76SHans Petter Selasky SLIST_INIT(&inmh);
86333cde130SBruce M Simpson IN6_MULTI_LOCK();
864f3e1324bSStephen Hurd IN6_MULTI_LIST_LOCK();
8652cd6ad76SHans Petter Selasky mld_ifdetach(ifp, &inmh);
866f3e1324bSStephen Hurd IN6_MULTI_LIST_UNLOCK();
86733cde130SBruce M Simpson IN6_MULTI_UNLOCK();
8682cd6ad76SHans Petter Selasky in6m_release_list_deferred(&inmh);
869dea72f06SHans Petter Selasky
870dea72f06SHans Petter Selasky /*
871dea72f06SHans Petter Selasky * Make sure all multicast deletions invoking if_ioctl() are
872dea72f06SHans Petter Selasky * completed before returning. Else we risk accessing a freed
873dea72f06SHans Petter Selasky * ifnet structure pointer.
874dea72f06SHans Petter Selasky */
8753689652cSHans Petter Selasky in6m_release_wait(NULL);
87671498f30SBruce M Simpson }
8779901091eSBjoern A. Zeeb
8789901091eSBjoern A. Zeeb void
in6_ifattach_destroy(void)8799901091eSBjoern A. Zeeb in6_ifattach_destroy(void)
8809901091eSBjoern A. Zeeb {
8819901091eSBjoern A. Zeeb
8829901091eSBjoern A. Zeeb callout_drain(&V_in6_tmpaddrtimer_ch);
8839901091eSBjoern A. Zeeb }
8849901091eSBjoern A. Zeeb
8859901091eSBjoern A. Zeeb static void
in6_ifattach_init(void * dummy)8869901091eSBjoern A. Zeeb in6_ifattach_init(void *dummy)
8879901091eSBjoern A. Zeeb {
8889901091eSBjoern A. Zeeb
8899901091eSBjoern A. Zeeb /* Timer for regeneranation of temporary addresses randomize ID. */
890663428eaSMark Johnston callout_init(&V_in6_tmpaddrtimer_ch, 1);
8919901091eSBjoern A. Zeeb callout_reset(&V_in6_tmpaddrtimer_ch,
8929901091eSBjoern A. Zeeb (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
8939901091eSBjoern A. Zeeb V_ip6_temp_regen_advance) * hz,
8949901091eSBjoern A. Zeeb in6_tmpaddrtimer, curvnet);
8959901091eSBjoern A. Zeeb }
8969901091eSBjoern A. Zeeb
8979901091eSBjoern A. Zeeb /*
8989901091eSBjoern A. Zeeb * Cheat.
8999901091eSBjoern A. Zeeb * This must be after route_init(), which is now SI_ORDER_THIRD.
9009901091eSBjoern A. Zeeb */
9019901091eSBjoern A. Zeeb SYSINIT(in6_ifattach_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
9029901091eSBjoern A. Zeeb in6_ifattach_init, NULL);
903