1/*	$OpenBSD: in6_ifattach.c,v 1.122 2023/07/09 19:06:48 bluhm Exp $	*/
2/*	$KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei 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
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/socket.h>
36#include <sys/sockio.h>
37#include <sys/kernel.h>
38#include <sys/syslog.h>
39
40#include <crypto/sha2.h>
41
42#include <net/if.h>
43#include <net/if_var.h>
44#include <net/if_dl.h>
45#include <net/if_types.h>
46#include <net/route.h>
47
48#include <netinet/in.h>
49
50#include <netinet6/in6_var.h>
51#include <netinet/ip6.h>
52#include <netinet6/ip6_var.h>
53#include <netinet6/in6_ifattach.h>
54#include <netinet6/nd6.h>
55#ifdef MROUTING
56#include <netinet6/ip6_mroute.h>
57#endif
58
59void	in6_get_rand_ifid(struct ifnet *, struct in6_addr *);
60int	in6_get_hw_ifid(struct ifnet *, struct in6_addr *);
61void	in6_get_ifid(struct ifnet *, struct in6_addr *);
62int	in6_ifattach_loopback(struct ifnet *);
63
64#define EUI64_GBIT	0x01
65#define EUI64_UBIT	0x02
66#define EUI64_TO_IFID(in6)	do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
67#define EUI64_GROUP(in6)	((in6)->s6_addr[8] & EUI64_GBIT)
68#define EUI64_INDIVIDUAL(in6)	(!EUI64_GROUP(in6))
69#define EUI64_LOCAL(in6)	((in6)->s6_addr[8] & EUI64_UBIT)
70#define EUI64_UNIVERSAL(in6)	(!EUI64_LOCAL(in6))
71
72#define IFID_LOCAL(in6)		(!EUI64_LOCAL(in6))
73#define IFID_UNIVERSAL(in6)	(!EUI64_UNIVERSAL(in6))
74
75/*
76 * Generate a random interface identifier.
77 *
78 * in6 - upper 64bits are preserved
79 */
80void
81in6_get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
82{
83	arc4random_buf(&in6->s6_addr32[2], 8);
84
85	/* make sure to set "u" bit to local, and "g" bit to individual. */
86	in6->s6_addr[8] &= ~EUI64_GBIT;	/* g bit to "individual" */
87	in6->s6_addr[8] |= EUI64_UBIT;	/* u bit to "local" */
88
89	/* convert EUI64 into IPv6 interface identifier */
90	EUI64_TO_IFID(in6);
91}
92
93/*
94 * Get interface identifier for the specified interface.
95 *
96 * in6 - upper 64bits are preserved
97 */
98int
99in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
100{
101	struct sockaddr_dl *sdl;
102	char *addr;
103	size_t addrlen;
104	static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
105	static u_int8_t allone[8] =
106		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
107
108	sdl = ifp->if_sadl;
109	if (sdl == NULL || sdl->sdl_alen == 0)
110		return -1;
111
112	addr = LLADDR(sdl);
113	addrlen = sdl->sdl_alen;
114
115	switch (ifp->if_type) {
116	case IFT_IEEE1394:
117	case IFT_IEEE80211:
118		/* IEEE1394 uses 16byte length address starting with EUI64 */
119		if (addrlen > 8)
120			addrlen = 8;
121		break;
122	default:
123		break;
124	}
125
126	/* get EUI64 */
127	switch (ifp->if_type) {
128	/* IEEE802/EUI64 cases - what others? */
129	case IFT_ETHER:
130	case IFT_CARP:
131	case IFT_IEEE1394:
132	case IFT_IEEE80211:
133		/* look at IEEE802/EUI64 only */
134		if (addrlen != 8 && addrlen != 6)
135			return -1;
136
137		/*
138		 * check for invalid MAC address - on bsdi, we see it a lot
139		 * since wildboar configures all-zero MAC on pccard before
140		 * card insertion.
141		 */
142		if (bcmp(addr, allzero, addrlen) == 0)
143			return -1;
144		if (bcmp(addr, allone, addrlen) == 0)
145			return -1;
146
147		/* make EUI64 address */
148		if (addrlen == 8)
149			memcpy(&in6->s6_addr[8], addr, 8);
150		else if (addrlen == 6) {
151			in6->s6_addr[8] = addr[0];
152			in6->s6_addr[9] = addr[1];
153			in6->s6_addr[10] = addr[2];
154			in6->s6_addr[11] = 0xff;
155			in6->s6_addr[12] = 0xfe;
156			in6->s6_addr[13] = addr[3];
157			in6->s6_addr[14] = addr[4];
158			in6->s6_addr[15] = addr[5];
159		}
160		break;
161
162	case IFT_GIF:
163		/*
164		 * RFC2893 says: "SHOULD use IPv4 address as ifid source".
165		 * however, IPv4 address is not very suitable as unique
166		 * identifier source (can be renumbered).
167		 * we don't do this.
168		 */
169		return -1;
170
171	default:
172		return -1;
173	}
174
175	/* sanity check: g bit must not indicate "group" */
176	if (EUI64_GROUP(in6))
177		return -1;
178
179	/* convert EUI64 into IPv6 interface identifier */
180	EUI64_TO_IFID(in6);
181
182	/*
183	 * sanity check: ifid must not be all zero, avoid conflict with
184	 * subnet router anycast
185	 */
186	if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
187	    bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
188		return -1;
189	}
190
191	return 0;
192}
193
194/*
195 * Get interface identifier for the specified interface.  If it is not
196 * available on ifp0, borrow interface identifier from other information
197 * sources.
198 */
199void
200in6_get_ifid(struct ifnet *ifp0, struct in6_addr *in6)
201{
202	struct ifnet *ifp;
203
204	/* first, try to get it from the interface itself */
205	if (in6_get_hw_ifid(ifp0, in6) == 0) {
206		nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
207		    ifp0->if_xname));
208		goto success;
209	}
210
211	/* next, try to get it from some other hardware interface */
212	TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
213		if (ifp == ifp0)
214			continue;
215		if (in6_get_hw_ifid(ifp, in6) == 0)
216			goto success;
217	}
218
219	/* last resort: get from random number source */
220	in6_get_rand_ifid(ifp, in6);
221	nd6log((LOG_DEBUG,
222	    "%s: interface identifier generated by random number\n",
223	    ifp0->if_xname));
224success:
225	nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
226	    ifp0->if_xname, in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
227	    in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
228	    in6->s6_addr[14], in6->s6_addr[15]));
229}
230
231/*
232 * ifid - used as EUI64 if not NULL, overrides other EUI64 sources
233 */
234
235int
236in6_ifattach_linklocal(struct ifnet *ifp, struct in6_addr *ifid)
237{
238	struct in6_aliasreq ifra;
239	struct in6_ifaddr *ia6;
240	int error, flags;
241
242	NET_ASSERT_LOCKED();
243
244	/*
245	 * configure link-local address.
246	 */
247	bzero(&ifra, sizeof(ifra));
248	strlcpy(ifra.ifra_name, ifp->if_xname, sizeof(ifra.ifra_name));
249	ifra.ifra_addr.sin6_family = AF_INET6;
250	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
251	ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
252	ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
253	ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
254	if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
255		ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
256		ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
257	} else if (ifid) {
258		ifra.ifra_addr.sin6_addr = *ifid;
259		ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
260		ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
261		ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
262		ifra.ifra_addr.sin6_addr.s6_addr[8] &= ~EUI64_GBIT;
263		ifra.ifra_addr.sin6_addr.s6_addr[8] |= EUI64_UBIT;
264	} else
265		in6_get_ifid(ifp, &ifra.ifra_addr.sin6_addr);
266
267	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
268	ifra.ifra_prefixmask.sin6_family = AF_INET6;
269	ifra.ifra_prefixmask.sin6_addr = in6mask64;
270	/* link-local addresses should NEVER expire. */
271	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
272	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
273
274	/*
275	 * XXX: Some P2P interfaces seem not to send packets just after
276	 * becoming up, so we skip p2p interfaces for safety.
277	 */
278	if (in6if_do_dad(ifp) && ((ifp->if_flags & IFF_POINTOPOINT) == 0))
279		ifra.ifra_flags |= IN6_IFF_TENTATIVE;
280
281	error = in6_update_ifa(ifp, &ifra, in6ifa_ifpforlinklocal(ifp, 0));
282	if (error != 0)
283		return (error);
284
285	ia6 = in6ifa_ifpforlinklocal(ifp, 0);
286
287	/* Perform DAD, if needed. */
288	if (ia6->ia6_flags & IN6_IFF_TENTATIVE)
289		nd6_dad_start(&ia6->ia_ifa);
290
291	if (ifp->if_flags & IFF_LOOPBACK) {
292		if_addrhooks_run(ifp);
293		return (0); /* No need to install a connected route. */
294	}
295
296	flags = RTF_CONNECTED | RTF_MPATH;
297	if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
298		flags |= RTF_CLONING;
299
300	error = rt_ifa_add(&ia6->ia_ifa, flags, ia6->ia_ifa.ifa_addr,
301	    ifp->if_rdomain);
302	if (error) {
303		in6_purgeaddr(&ia6->ia_ifa);
304		return (error);
305	}
306	if_addrhooks_run(ifp);
307
308	return (0);
309}
310
311int
312in6_ifattach_loopback(struct ifnet *ifp)
313{
314	struct in6_addr in6 = in6addr_loopback;
315	struct in6_aliasreq ifra;
316
317	KASSERT(ifp->if_flags & IFF_LOOPBACK);
318
319	if (in6ifa_ifpwithaddr(ifp, &in6) != NULL)
320		return (0);
321
322	bzero(&ifra, sizeof(ifra));
323	strlcpy(ifra.ifra_name, ifp->if_xname, sizeof(ifra.ifra_name));
324	ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
325	ifra.ifra_prefixmask.sin6_family = AF_INET6;
326	ifra.ifra_prefixmask.sin6_addr = in6mask128;
327
328	/*
329	 * Always initialize ia_dstaddr (= broadcast address) to loopback
330	 * address.  Follows IPv4 practice - see in_ifinit().
331	 */
332	ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
333	ifra.ifra_dstaddr.sin6_family = AF_INET6;
334	ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
335
336	ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
337	ifra.ifra_addr.sin6_family = AF_INET6;
338	ifra.ifra_addr.sin6_addr = in6addr_loopback;
339
340	/* the loopback  address should NEVER expire. */
341	ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
342	ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
343
344	/*
345	 * We are sure that this is a newly assigned address, so we can set
346	 * NULL to the 3rd arg.
347	 */
348	return (in6_update_ifa(ifp, &ifra, NULL));
349}
350
351/*
352 * XXX multiple loopback interface needs more care.  for instance,
353 * nodelocal address needs to be configured onto only one of them.
354 * XXX multiple link-local address case
355 */
356int
357in6_ifattach(struct ifnet *ifp)
358{
359	/* some of the interfaces are inherently not IPv6 capable */
360	switch (ifp->if_type) {
361	case IFT_BRIDGE:
362	case IFT_ENC:
363	case IFT_PFLOG:
364	case IFT_PFSYNC:
365		return (0);
366	}
367
368	/*
369	 * if link mtu is too small, don't try to configure IPv6.
370	 * remember there could be some link-layer that has special
371	 * fragmentation logic.
372	 */
373	if (ifp->if_mtu < IPV6_MMTU)
374		return (EINVAL);
375
376	if (nd6_need_cache(ifp) && (ifp->if_flags & IFF_MULTICAST) == 0)
377		return (EINVAL);
378
379	/*
380	 * Assign loopback address if this lo(4) interface is the
381	 * default for its rdomain.
382	 */
383	if ((ifp->if_flags & IFF_LOOPBACK) &&
384	    (ifp->if_index == rtable_loindex(ifp->if_rdomain))) {
385		int error;
386
387		error = in6_ifattach_loopback(ifp);
388		if (error)
389			return (error);
390	}
391
392	switch (ifp->if_type) {
393	case IFT_WIREGUARD:
394		return (0);
395	}
396
397	/* Assign a link-local address, if there's none. */
398	if (in6ifa_ifpforlinklocal(ifp, 0) == NULL) {
399		if (in6_ifattach_linklocal(ifp, NULL) != 0) {
400			/* failed to assign linklocal address. bark? */
401		}
402	}
403
404	return (0);
405}
406
407/*
408 * NOTE: in6_ifdetach() does not support loopback if at this moment.
409 */
410void
411in6_ifdetach(struct ifnet *ifp)
412{
413	struct ifaddr *ifa, *next;
414	struct rtentry *rt;
415	struct sockaddr_in6 sin6;
416
417#ifdef MROUTING
418	/* remove ip6_mrouter stuff */
419	ip6_mrouter_detach(ifp);
420#endif
421
422	/* nuke any of IPv6 addresses we have */
423	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) {
424		if (ifa->ifa_addr->sa_family != AF_INET6)
425			continue;
426		in6_purgeaddr(ifa);
427		if_addrhooks_run(ifp);
428	}
429
430	/*
431	 * Remove neighbor management table.  Must be called after
432	 * purging addresses.
433	 */
434	nd6_purge(ifp);
435
436	/* remove route to interface local allnodes multicast (ff01::1) */
437	bzero(&sin6, sizeof(sin6));
438	sin6.sin6_len = sizeof(struct sockaddr_in6);
439	sin6.sin6_family = AF_INET6;
440	sin6.sin6_addr = in6addr_intfacelocal_allnodes;
441	sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
442	rt = rtalloc(sin6tosa(&sin6), 0, ifp->if_rdomain);
443	if (rt && rt->rt_ifidx == ifp->if_index)
444		rtdeletemsg(rt, ifp, ifp->if_rdomain);
445	rtfree(rt);
446
447	/* remove route to link-local allnodes multicast (ff02::1) */
448	bzero(&sin6, sizeof(sin6));
449	sin6.sin6_len = sizeof(struct sockaddr_in6);
450	sin6.sin6_family = AF_INET6;
451	sin6.sin6_addr = in6addr_linklocal_allnodes;
452	sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
453	rt = rtalloc(sin6tosa(&sin6), 0, ifp->if_rdomain);
454	if (rt && rt->rt_ifidx == ifp->if_index)
455		rtdeletemsg(rt, ifp, ifp->if_rdomain);
456	rtfree(rt);
457
458	if (ifp->if_xflags & (IFXF_AUTOCONF6 | IFXF_AUTOCONF6TEMP))
459		ifp->if_xflags &= ~(IFXF_AUTOCONF6 | IFXF_AUTOCONF6TEMP);
460}
461