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
59 void in6_get_rand_ifid(struct ifnet *, struct in6_addr *);
60 int in6_get_hw_ifid(struct ifnet *, struct in6_addr *);
61 void in6_get_ifid(struct ifnet *, struct in6_addr *);
62 int 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 */
80 void
in6_get_rand_ifid(struct ifnet * ifp,struct in6_addr * in6)81 in6_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 */
98 int
in6_get_hw_ifid(struct ifnet * ifp,struct in6_addr * in6)99 in6_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 */
199 void
in6_get_ifid(struct ifnet * ifp0,struct in6_addr * in6)200 in6_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));
224 success:
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
235 int
in6_ifattach_linklocal(struct ifnet * ifp,struct in6_addr * ifid)236 in6_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
311 int
in6_ifattach_loopback(struct ifnet * ifp)312 in6_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 */
356 int
in6_ifattach(struct ifnet * ifp)357 in6_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 */
410 void
in6_ifdetach(struct ifnet * ifp)411 in6_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