xref: /openbsd/sys/netinet/in.c (revision a61bf6f2)
1 /*	$OpenBSD: in.c,v 1.186 2024/01/06 10:58:45 bluhm Exp $	*/
2 /*	$NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $	*/
3 
4 /*
5  * Copyright (C) 2001 WIDE Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /*
33  * Copyright (c) 1982, 1986, 1991, 1993
34  *	The Regents of the University of California.  All rights reserved.
35  *
36  * Redistribution and use in source and binary forms, with or without
37  * modification, are permitted provided that the following conditions
38  * are met:
39  * 1. Redistributions of source code must retain the above copyright
40  *    notice, this list of conditions and the following disclaimer.
41  * 2. Redistributions in binary form must reproduce the above copyright
42  *    notice, this list of conditions and the following disclaimer in the
43  *    documentation and/or other materials provided with the distribution.
44  * 3. Neither the name of the University nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58  * SUCH DAMAGE.
59  *
60  *	@(#)in.c	8.2 (Berkeley) 11/15/93
61  */
62 
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/ioctl.h>
66 #include <sys/malloc.h>
67 #include <sys/socket.h>
68 #include <sys/socketvar.h>
69 
70 #include <net/if.h>
71 #include <net/if_var.h>
72 #include <net/route.h>
73 
74 #include <netinet/in.h>
75 #include <netinet/in_var.h>
76 #include <netinet/igmp_var.h>
77 
78 #ifdef MROUTING
79 #include <netinet/ip_mroute.h>
80 #endif
81 
82 #include "ether.h"
83 
84 
85 void in_socktrim(struct sockaddr_in *);
86 
87 int in_ioctl_set_ifaddr(u_long, caddr_t, struct ifnet *);
88 int in_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *);
89 int in_ioctl_get(u_long, caddr_t, struct ifnet *);
90 void in_purgeaddr(struct ifaddr *);
91 int in_addhost(struct in_ifaddr *, struct sockaddr_in *);
92 int in_scrubhost(struct in_ifaddr *, struct sockaddr_in *);
93 int in_insert_prefix(struct in_ifaddr *);
94 void in_remove_prefix(struct in_ifaddr *);
95 
96 /*
97  * Determine whether an IP address is in a reserved set of addresses
98  * that may not be forwarded, or whether datagrams to that destination
99  * may be forwarded.
100  */
101 int
in_canforward(struct in_addr in)102 in_canforward(struct in_addr in)
103 {
104 	u_int32_t net;
105 
106 	if (IN_MULTICAST(in.s_addr))
107 		return (0);
108 	if (IN_CLASSA(in.s_addr)) {
109 		net = in.s_addr & IN_CLASSA_NET;
110 		if (net == 0 ||
111 		    net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
112 			return (0);
113 	}
114 	return (1);
115 }
116 
117 /*
118  * Trim a mask in a sockaddr
119  */
120 void
in_socktrim(struct sockaddr_in * ap)121 in_socktrim(struct sockaddr_in *ap)
122 {
123 	char *cplim = (char *) &ap->sin_addr;
124 	char *cp = (char *) (&ap->sin_addr + 1);
125 
126 	ap->sin_len = 0;
127 	while (--cp >= cplim)
128 		if (*cp) {
129 			(ap)->sin_len = cp - (char *) (ap) + 1;
130 			break;
131 		}
132 }
133 
134 int
in_mask2len(struct in_addr * mask)135 in_mask2len(struct in_addr *mask)
136 {
137 	int x, y;
138 	u_char *p;
139 
140 	p = (u_char *)mask;
141 	for (x = 0; x < sizeof(*mask); x++) {
142 		if (p[x] != 0xff)
143 			break;
144 	}
145 	y = 0;
146 	if (x < sizeof(*mask)) {
147 		for (y = 0; y < 8; y++) {
148 			if ((p[x] & (0x80 >> y)) == 0)
149 				break;
150 		}
151 	}
152 	return x * 8 + y;
153 }
154 
155 void
in_len2mask(struct in_addr * mask,int len)156 in_len2mask(struct in_addr *mask, int len)
157 {
158 	int i;
159 	u_char *p;
160 
161 	p = (u_char *)mask;
162 	bzero(mask, sizeof(*mask));
163 	for (i = 0; i < len / 8; i++)
164 		p[i] = 0xff;
165 	if (len % 8)
166 		p[i] = (0xff00 >> (len % 8)) & 0xff;
167 }
168 
169 int
in_nam2sin(const struct mbuf * nam,struct sockaddr_in ** sin)170 in_nam2sin(const struct mbuf *nam, struct sockaddr_in **sin)
171 {
172 	struct sockaddr *sa = mtod(nam, struct sockaddr *);
173 
174 	if (nam->m_len < offsetof(struct sockaddr, sa_data))
175 		return EINVAL;
176 	if (sa->sa_family != AF_INET)
177 		return EAFNOSUPPORT;
178 	if (sa->sa_len != nam->m_len)
179 		return EINVAL;
180 	if (sa->sa_len != sizeof(struct sockaddr_in))
181 		return EINVAL;
182 	*sin = satosin(sa);
183 
184 	return 0;
185 }
186 
187 int
in_sa2sin(struct sockaddr * sa,struct sockaddr_in ** sin)188 in_sa2sin(struct sockaddr *sa, struct sockaddr_in **sin)
189 {
190 	if (sa->sa_family != AF_INET)
191 		return EAFNOSUPPORT;
192 	if (sa->sa_len != sizeof(struct sockaddr_in))
193 		return EINVAL;
194 	*sin = satosin(sa);
195 
196 	return 0;
197 }
198 
199 int
in_control(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp)200 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
201 {
202 	int privileged;
203 
204 	privileged = 0;
205 	if ((so->so_state & SS_PRIV) != 0)
206 		privileged++;
207 
208 	switch (cmd) {
209 #ifdef MROUTING
210 	case SIOCGETVIFCNT:
211 	case SIOCGETSGCNT:
212 		return mrt_ioctl(so, cmd, data);
213 #endif /* MROUTING */
214 	default:
215 		return in_ioctl(cmd, data, ifp, privileged);
216 	}
217 }
218 
219 int
in_ioctl(u_long cmd,caddr_t data,struct ifnet * ifp,int privileged)220 in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged)
221 {
222 	struct ifreq *ifr = (struct ifreq *)data;
223 	struct ifaddr *ifa;
224 	struct in_ifaddr *ia = NULL;
225 	struct sockaddr_in *sin = NULL, oldaddr;
226 	int error = 0;
227 
228 	if (ifp == NULL)
229 		return (ENXIO);
230 
231 	switch (cmd) {
232 	case SIOCGIFADDR:
233 	case SIOCGIFNETMASK:
234 	case SIOCGIFDSTADDR:
235 	case SIOCGIFBRDADDR:
236 		return in_ioctl_get(cmd, data, ifp);
237 	case SIOCSIFADDR:
238 		if (!privileged)
239 			return (EPERM);
240 		return in_ioctl_set_ifaddr(cmd, data, ifp);
241 	case SIOCAIFADDR:
242 	case SIOCDIFADDR:
243 		if (!privileged)
244 			return (EPERM);
245 		return in_ioctl_change_ifaddr(cmd, data, ifp);
246 	case SIOCSIFNETMASK:
247 	case SIOCSIFDSTADDR:
248 	case SIOCSIFBRDADDR:
249 		break;
250 	default:
251 		return (EOPNOTSUPP);
252 	}
253 
254 	if (!privileged)
255 		return (EPERM);
256 
257 	if (ifr->ifr_addr.sa_family == AF_INET) {
258 		error = in_sa2sin(&ifr->ifr_addr, &sin);
259 		if (error)
260 			return (error);
261 	}
262 
263 	NET_LOCK();
264 	KERNEL_LOCK();
265 
266 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
267 		if (ifa->ifa_addr->sa_family != AF_INET)
268 			continue;
269 		/* find first address or exact match */
270 		if (ia == NULL)
271 			ia = ifatoia(ifa);
272 		if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY)
273 			break;
274 		if (ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
275 		    sin->sin_addr.s_addr) {
276 			ia = ifatoia(ifa);
277 			break;
278 		}
279 	}
280 	if (ia == NULL) {
281 		error = EADDRNOTAVAIL;
282 		goto err;
283 	}
284 
285 	switch (cmd) {
286 	case SIOCSIFDSTADDR:
287 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
288 			error = EINVAL;
289 			break;
290 		}
291 		error = in_sa2sin(&ifr->ifr_dstaddr, &sin);
292 		if (error)
293 			break;
294 		oldaddr = ia->ia_dstaddr;
295 		ia->ia_dstaddr = *sin;
296 		error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (caddr_t)ia);
297 		if (error) {
298 			ia->ia_dstaddr = oldaddr;
299 			break;
300 		}
301 		in_scrubhost(ia, &oldaddr);
302 		in_addhost(ia, &ia->ia_dstaddr);
303 		break;
304 
305 	case SIOCSIFBRDADDR:
306 		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
307 			error = EINVAL;
308 			break;
309 		}
310 		error = in_sa2sin(&ifr->ifr_broadaddr, &sin);
311 		if (error)
312 			break;
313 		ifa_update_broadaddr(ifp, &ia->ia_ifa, sintosa(sin));
314 		break;
315 
316 	case SIOCSIFNETMASK:
317 		if (ifr->ifr_addr.sa_len < 8) {
318 			error = EINVAL;
319 			break;
320 		}
321 		/* do not check inet family or strict len */
322 		sin = satosin(&ifr->ifr_addr);
323 		if (ntohl(sin->sin_addr.s_addr) &
324 		    (~ntohl(sin->sin_addr.s_addr) >> 1)) {
325 			/* non-contiguous netmask */
326 			error = EINVAL;
327 			break;
328 		}
329 		ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
330 		    sin->sin_addr.s_addr;
331 		break;
332 	}
333 err:
334 	KERNEL_UNLOCK();
335 	NET_UNLOCK();
336 	return (error);
337 }
338 
339 int
in_ioctl_set_ifaddr(u_long cmd,caddr_t data,struct ifnet * ifp)340 in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
341 {
342 	struct ifreq *ifr = (struct ifreq *)data;
343 	struct ifaddr *ifa;
344 	struct in_ifaddr *ia = NULL;
345 	struct sockaddr_in *sin;
346 	int error = 0;
347 	int newifaddr;
348 
349 	if (cmd != SIOCSIFADDR)
350 		panic("%s: invalid ioctl %lu", __func__, cmd);
351 
352 	error = in_sa2sin(&ifr->ifr_addr, &sin);
353 	if (error)
354 		return (error);
355 
356 	NET_LOCK();
357 	KERNEL_LOCK();
358 
359 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
360 		if (ifa->ifa_addr->sa_family != AF_INET)
361 			continue;
362 		/* find first address */
363 		ia = ifatoia(ifa);
364 		break;
365 	}
366 	if (ia == NULL) {
367 		ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
368 		refcnt_init_trace(&ia->ia_ifa.ifa_refcnt, DT_REFCNT_IDX_IFADDR);
369 		ia->ia_addr.sin_family = AF_INET;
370 		ia->ia_addr.sin_len = sizeof(ia->ia_addr);
371 		ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
372 		ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
373 		ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
374 		ia->ia_sockmask.sin_len = 8;
375 		if (ifp->if_flags & IFF_BROADCAST) {
376 			ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
377 			ia->ia_broadaddr.sin_family = AF_INET;
378 		}
379 		ia->ia_ifp = ifp;
380 
381 		newifaddr = 1;
382 	} else
383 		newifaddr = 0;
384 
385 	in_ifscrub(ifp, ia);
386 	error = in_ifinit(ifp, ia, sin, newifaddr);
387 	if (!error)
388 		if_addrhooks_run(ifp);
389 
390 	KERNEL_UNLOCK();
391 	NET_UNLOCK();
392 	return error;
393 }
394 
395 int
in_ioctl_change_ifaddr(u_long cmd,caddr_t data,struct ifnet * ifp)396 in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
397 {
398 	struct ifaddr *ifa;
399 	struct in_ifaddr *ia = NULL;
400 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
401 	struct sockaddr_in *sin = NULL, *dstsin = NULL, *broadsin = NULL;
402 	struct sockaddr_in *masksin = NULL;
403 	int error = 0;
404 	int newifaddr;
405 
406 	if (ifra->ifra_addr.sin_family == AF_INET) {
407 		error = in_sa2sin(sintosa(&ifra->ifra_addr), &sin);
408 		if (error)
409 			return (error);
410 	}
411 
412 	NET_LOCK();
413 	KERNEL_LOCK();
414 
415 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
416 		if (ifa->ifa_addr->sa_family != AF_INET)
417 			continue;
418 		/* find first address, if no exact match wanted */
419 		if (sin == NULL || sin->sin_addr.s_addr ==
420 		    ifatoia(ifa)->ia_addr.sin_addr.s_addr) {
421 			ia = ifatoia(ifa);
422 			break;
423 		}
424 	}
425 
426 	switch (cmd) {
427 	case SIOCAIFADDR: {
428 		int needinit = 0;
429 
430 		if (ifra->ifra_mask.sin_len) {
431 			if (ifra->ifra_mask.sin_len < 8) {
432 				error = EINVAL;
433 				break;
434 			}
435 			/* do not check inet family or strict len */
436 			masksin = &ifra->ifra_mask;
437 			if (ntohl(masksin->sin_addr.s_addr) &
438 			    (~ntohl(masksin->sin_addr.s_addr) >> 1)) {
439 				/* non-contiguous netmask */
440 				error = EINVAL;
441 				break;
442 			}
443 		}
444 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
445 		    ifra->ifra_dstaddr.sin_family == AF_INET) {
446 			error = in_sa2sin(sintosa(&ifra->ifra_dstaddr),
447 			    &dstsin);
448 			if (error)
449 				break;
450 		}
451 		if ((ifp->if_flags & IFF_BROADCAST) &&
452 		    ifra->ifra_broadaddr.sin_family == AF_INET) {
453 			error = in_sa2sin(sintosa(&ifra->ifra_broadaddr),
454 			    &broadsin);
455 			if (error)
456 				break;
457 		}
458 
459 		if (ia == NULL) {
460 			ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
461 			refcnt_init_trace(&ia->ia_ifa.ifa_refcnt,
462 			    DT_REFCNT_IDX_IFADDR);
463 			ia->ia_addr.sin_family = AF_INET;
464 			ia->ia_addr.sin_len = sizeof(ia->ia_addr);
465 			ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
466 			ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
467 			ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
468 			ia->ia_sockmask.sin_len = 8;
469 			if (ifp->if_flags & IFF_BROADCAST) {
470 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
471 				ia->ia_broadaddr.sin_family = AF_INET;
472 			}
473 			ia->ia_ifp = ifp;
474 
475 			newifaddr = 1;
476 		} else
477 			newifaddr = 0;
478 
479 		if (sin == NULL) {
480 			sin = &ia->ia_addr;
481 		} else if (newifaddr ||
482 		    sin->sin_addr.s_addr != ia->ia_addr.sin_addr.s_addr) {
483 			needinit = 1;
484 		}
485 		if (masksin != NULL) {
486 			in_ifscrub(ifp, ia);
487 			ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
488 			    masksin->sin_addr.s_addr;
489 			needinit = 1;
490 		}
491 		if (dstsin != NULL) {
492 			in_ifscrub(ifp, ia);
493 			ia->ia_dstaddr = *dstsin;
494 			needinit = 1;
495 		}
496 		if (broadsin != NULL) {
497 			if (newifaddr)
498 				ia->ia_broadaddr = *broadsin;
499 			else
500 				ifa_update_broadaddr(ifp, &ia->ia_ifa,
501 				    sintosa(broadsin));
502 		}
503 		if (needinit) {
504 			error = in_ifinit(ifp, ia, sin, newifaddr);
505 			if (error)
506 				break;
507 		}
508 		if_addrhooks_run(ifp);
509 		break;
510 	    }
511 	case SIOCDIFADDR:
512 		if (ia == NULL) {
513 			error = EADDRNOTAVAIL;
514 			break;
515 		}
516 		/*
517 		 * Even if the individual steps were safe, shouldn't
518 		 * these kinds of changes happen atomically?  What
519 		 * should happen to a packet that was routed after
520 		 * the scrub but before the other steps?
521 		 */
522 		in_purgeaddr(&ia->ia_ifa);
523 		if_addrhooks_run(ifp);
524 		break;
525 
526 	default:
527 		panic("%s: invalid ioctl %lu", __func__, cmd);
528 	}
529 
530 	KERNEL_UNLOCK();
531 	NET_UNLOCK();
532 	return (error);
533 }
534 
535 int
in_ioctl_get(u_long cmd,caddr_t data,struct ifnet * ifp)536 in_ioctl_get(u_long cmd, caddr_t data, struct ifnet *ifp)
537 {
538 	struct ifreq *ifr = (struct ifreq *)data;
539 	struct ifaddr *ifa;
540 	struct in_ifaddr *ia = NULL;
541 	struct sockaddr *sa;
542 	struct sockaddr_in *sin = NULL;
543 	int error = 0;
544 
545 	sa = &ifr->ifr_addr;
546 	if (sa->sa_family == AF_INET) {
547 		sa->sa_len = sizeof(struct sockaddr_in);
548 		error = in_sa2sin(sa, &sin);
549 		if (error)
550 			return (error);
551 	}
552 
553 	NET_LOCK_SHARED();
554 
555 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
556 		if (ifa->ifa_addr->sa_family != AF_INET)
557 			continue;
558 		/* find first address or exact match */
559 		if (ia == NULL)
560 			ia = ifatoia(ifa);
561 		if (sin == NULL || sin->sin_addr.s_addr == INADDR_ANY)
562 			break;
563 		if (ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
564 		    sin->sin_addr.s_addr) {
565 			ia = ifatoia(ifa);
566 			break;
567 		}
568 	}
569 	if (ia == NULL) {
570 		error = EADDRNOTAVAIL;
571 		goto err;
572 	}
573 
574 	switch(cmd) {
575 	case SIOCGIFADDR:
576 		*satosin(&ifr->ifr_addr) = ia->ia_addr;
577 		break;
578 
579 	case SIOCGIFBRDADDR:
580 		if ((ifp->if_flags & IFF_BROADCAST) == 0) {
581 			error = EINVAL;
582 			break;
583 		}
584 		*satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
585 		break;
586 
587 	case SIOCGIFDSTADDR:
588 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
589 			error = EINVAL;
590 			break;
591 		}
592 		*satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
593 		break;
594 
595 	case SIOCGIFNETMASK:
596 		*satosin(&ifr->ifr_addr) = ia->ia_sockmask;
597 		break;
598 
599 	default:
600 		panic("%s: invalid ioctl %lu", __func__, cmd);
601 	}
602 
603 err:
604 	NET_UNLOCK_SHARED();
605 	return (error);
606 }
607 
608 /*
609  * Delete any existing route for an interface.
610  */
611 void
in_ifscrub(struct ifnet * ifp,struct in_ifaddr * ia)612 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
613 {
614 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT))
615 		in_scrubhost(ia, &ia->ia_dstaddr);
616 	else if (!ISSET(ifp->if_flags, IFF_LOOPBACK))
617 		in_remove_prefix(ia);
618 }
619 
620 /*
621  * Initialize an interface's internet address
622  * and routing table entry.
623  */
624 int
in_ifinit(struct ifnet * ifp,struct in_ifaddr * ia,struct sockaddr_in * sin,int newaddr)625 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
626     int newaddr)
627 {
628 	u_int32_t i = sin->sin_addr.s_addr;
629 	struct sockaddr_in oldaddr;
630 	int error = 0, rterror;
631 
632 	NET_ASSERT_LOCKED();
633 
634 	/*
635 	 * Always remove the address from the tree to make sure its
636 	 * position gets updated in case the key changes.
637 	 */
638 	if (!newaddr) {
639 		rt_ifa_dellocal(&ia->ia_ifa);
640 		ifa_del(ifp, &ia->ia_ifa);
641 	}
642 	oldaddr = ia->ia_addr;
643 	ia->ia_addr = *sin;
644 
645 	if (ia->ia_netmask == 0) {
646 		if (IN_CLASSA(i))
647 			ia->ia_netmask = IN_CLASSA_NET;
648 		else if (IN_CLASSB(i))
649 			ia->ia_netmask = IN_CLASSB_NET;
650 		else
651 			ia->ia_netmask = IN_CLASSC_NET;
652 		ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask;
653 	}
654 
655 	/*
656 	 * Give the interface a chance to initialize
657 	 * if this is its first address,
658 	 * and to validate the address if necessary.
659 	 */
660 	if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
661 		ia->ia_addr = oldaddr;
662 	}
663 
664 	/*
665 	 * Add the address to the local list and the global tree.  If an
666 	 * error occurred, put back the original address.
667 	 */
668 	ifa_add(ifp, &ia->ia_ifa);
669 	rterror = rt_ifa_addlocal(&ia->ia_ifa);
670 
671 	if (rterror) {
672 		if (!newaddr)
673 			ifa_del(ifp, &ia->ia_ifa);
674 		if (!error)
675 			error = rterror;
676 		goto out;
677 	}
678 	if (error)
679 		goto out;
680 
681 
682 	ia->ia_net = i & ia->ia_netmask;
683 	in_socktrim(&ia->ia_sockmask);
684 	/*
685 	 * Add route for the network.
686 	 */
687 	ia->ia_ifa.ifa_metric = ifp->if_metric;
688 	if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
689 		if (IN_RFC3021_SUBNET(ia->ia_netmask))
690 			ia->ia_broadaddr.sin_addr.s_addr = 0;
691 		else {
692 			ia->ia_broadaddr.sin_addr.s_addr =
693 			    ia->ia_net | ~ia->ia_netmask;
694 		}
695 	}
696 
697 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) {
698 		/* XXX We should not even call in_ifinit() in this case. */
699 		if (ia->ia_dstaddr.sin_family != AF_INET)
700 			goto out;
701 		error = in_addhost(ia, &ia->ia_dstaddr);
702 	} else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) {
703 		error = in_insert_prefix(ia);
704 	}
705 
706 	/*
707 	 * If the interface supports multicast, join the "all hosts"
708 	 * multicast group on that interface.
709 	 */
710 	if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
711 		struct in_addr addr;
712 
713 		addr.s_addr = INADDR_ALLHOSTS_GROUP;
714 		ia->ia_allhosts = in_addmulti(&addr, ifp);
715 	}
716 
717 out:
718 	if (error && newaddr)
719 		in_purgeaddr(&ia->ia_ifa);
720 
721 	return (error);
722 }
723 
724 void
in_purgeaddr(struct ifaddr * ifa)725 in_purgeaddr(struct ifaddr *ifa)
726 {
727 	struct ifnet *ifp = ifa->ifa_ifp;
728 	struct in_ifaddr *ia = ifatoia(ifa);
729 
730 	NET_ASSERT_LOCKED();
731 
732 	in_ifscrub(ifp, ia);
733 
734 	rt_ifa_dellocal(&ia->ia_ifa);
735 	rt_ifa_purge(&ia->ia_ifa);
736 	ifa_del(ifp, &ia->ia_ifa);
737 
738 	if (ia->ia_allhosts != NULL) {
739 		in_delmulti(ia->ia_allhosts);
740 		ia->ia_allhosts = NULL;
741 	}
742 
743 	ia->ia_ifp = NULL;
744 	ifafree(&ia->ia_ifa);
745 }
746 
747 int
in_addhost(struct in_ifaddr * ia,struct sockaddr_in * dst)748 in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
749 {
750 	return rt_ifa_add(&ia->ia_ifa, RTF_HOST | RTF_MPATH,
751 	    sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain);
752 }
753 
754 int
in_scrubhost(struct in_ifaddr * ia,struct sockaddr_in * dst)755 in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
756 {
757 	return rt_ifa_del(&ia->ia_ifa, RTF_HOST,
758 	    sintosa(dst), ia->ia_ifa.ifa_ifp->if_rdomain);
759 }
760 
761 /*
762  * Insert the cloning and broadcast routes for this subnet.
763  */
764 int
in_insert_prefix(struct in_ifaddr * ia)765 in_insert_prefix(struct in_ifaddr *ia)
766 {
767 	struct ifaddr *ifa = &ia->ia_ifa;
768 	int error;
769 
770 	error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED | RTF_MPATH,
771 	    ifa->ifa_addr, ifa->ifa_ifp->if_rdomain);
772 	if (error)
773 		return (error);
774 
775 	if (ia->ia_broadaddr.sin_addr.s_addr != 0) {
776 		error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST | RTF_MPATH,
777 		    ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain);
778 	}
779 
780 	return (error);
781 }
782 
783 void
in_remove_prefix(struct in_ifaddr * ia)784 in_remove_prefix(struct in_ifaddr *ia)
785 {
786 	struct ifaddr *ifa = &ia->ia_ifa;
787 
788 	rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED,
789 	    ifa->ifa_addr, ifa->ifa_ifp->if_rdomain);
790 
791 	if (ia->ia_broadaddr.sin_addr.s_addr != 0) {
792 		rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST,
793 		    ifa->ifa_broadaddr, ifa->ifa_ifp->if_rdomain);
794 	}
795 }
796 
797 /*
798  * Return 1 if the address is a local broadcast address.
799  */
800 int
in_broadcast(struct in_addr in,u_int rtableid)801 in_broadcast(struct in_addr in, u_int rtableid)
802 {
803 	struct ifnet *ifn;
804 	struct ifaddr *ifa;
805 	u_int rdomain;
806 
807 	rdomain = rtable_l2(rtableid);
808 
809 #define ia (ifatoia(ifa))
810 	TAILQ_FOREACH(ifn, &ifnetlist, if_list) {
811 		if (ifn->if_rdomain != rdomain)
812 			continue;
813 		if ((ifn->if_flags & IFF_BROADCAST) == 0)
814 			continue;
815 		TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
816 			if (ifa->ifa_addr->sa_family == AF_INET &&
817 			    in.s_addr != ia->ia_addr.sin_addr.s_addr &&
818 			    in.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
819 				return 1;
820 	}
821 	return (0);
822 #undef ia
823 }
824 
825 /*
826  * Add an address to the list of IP multicast addresses for a given interface.
827  */
828 struct in_multi *
in_addmulti(struct in_addr * ap,struct ifnet * ifp)829 in_addmulti(struct in_addr *ap, struct ifnet *ifp)
830 {
831 	struct in_multi *inm;
832 	struct ifreq ifr;
833 
834 	/*
835 	 * See if address already in list.
836 	 */
837 	IN_LOOKUP_MULTI(*ap, ifp, inm);
838 	if (inm != NULL) {
839 		/*
840 		 * Found it; just increment the reference count.
841 		 */
842 		refcnt_take(&inm->inm_refcnt);
843 	} else {
844 		/*
845 		 * New address; allocate a new multicast record
846 		 * and link it into the interface's multicast list.
847 		 */
848 		inm = malloc(sizeof(*inm), M_IPMADDR, M_WAITOK | M_ZERO);
849 		inm->inm_sin.sin_len = sizeof(struct sockaddr_in);
850 		inm->inm_sin.sin_family = AF_INET;
851 		inm->inm_sin.sin_addr = *ap;
852 		refcnt_init_trace(&inm->inm_refcnt, DT_REFCNT_IDX_IFMADDR);
853 		inm->inm_ifidx = ifp->if_index;
854 		inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin);
855 
856 		/*
857 		 * Ask the network driver to update its multicast reception
858 		 * filter appropriately for the new address.
859 		 */
860 		memset(&ifr, 0, sizeof(ifr));
861 		memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin));
862 		KERNEL_LOCK();
863 		if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
864 			KERNEL_UNLOCK();
865 			free(inm, M_IPMADDR, sizeof(*inm));
866 			return (NULL);
867 		}
868 		KERNEL_UNLOCK();
869 
870 		TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma,
871 		    ifma_list);
872 
873 		/*
874 		 * Let IGMP know that we have joined a new IP multicast group.
875 		 */
876 		igmp_joingroup(inm, ifp);
877 	}
878 
879 	return (inm);
880 }
881 
882 /*
883  * Delete a multicast address record.
884  */
885 void
in_delmulti(struct in_multi * inm)886 in_delmulti(struct in_multi *inm)
887 {
888 	struct ifreq ifr;
889 	struct ifnet *ifp;
890 
891 	NET_ASSERT_LOCKED();
892 
893 	if (refcnt_rele(&inm->inm_refcnt) == 0)
894 		return;
895 
896 	ifp = if_get(inm->inm_ifidx);
897 	if (ifp != NULL) {
898 		/*
899 		 * No remaining claims to this record; let IGMP know that
900 		 * we are leaving the multicast group.
901 		 */
902 		igmp_leavegroup(inm, ifp);
903 
904 		/*
905 		 * Notify the network driver to update its multicast
906 		 * reception filter.
907 		 */
908 		memset(&ifr, 0, sizeof(ifr));
909 		satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
910 		satosin(&ifr.ifr_addr)->sin_family = AF_INET;
911 		satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
912 		KERNEL_LOCK();
913 		(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
914 		KERNEL_UNLOCK();
915 
916 		TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma, ifma_list);
917 	}
918 	if_put(ifp);
919 
920 	free(inm, M_IPMADDR, sizeof(*inm));
921 }
922 
923 /*
924  * Return 1 if the multicast group represented by ``ap'' has been
925  * joined by interface ``ifp'', 0 otherwise.
926  */
927 int
in_hasmulti(struct in_addr * ap,struct ifnet * ifp)928 in_hasmulti(struct in_addr *ap, struct ifnet *ifp)
929 {
930 	struct in_multi *inm;
931 	int joined;
932 
933 	IN_LOOKUP_MULTI(*ap, ifp, inm);
934 	joined = (inm != NULL);
935 
936 	return (joined);
937 }
938 
939 void
in_ifdetach(struct ifnet * ifp)940 in_ifdetach(struct ifnet *ifp)
941 {
942 	struct ifaddr *ifa, *next;
943 
944 	/* nuke any of IPv4 addresses we have */
945 	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) {
946 		if (ifa->ifa_addr->sa_family != AF_INET)
947 			continue;
948 		in_purgeaddr(ifa);
949 		if_addrhooks_run(ifp);
950 	}
951 
952 	if (ifp->if_xflags & IFXF_AUTOCONF4)
953 		ifp->if_xflags &= ~IFXF_AUTOCONF4;
954 }
955 
956 void
in_prefixlen2mask(struct in_addr * maskp,int plen)957 in_prefixlen2mask(struct in_addr *maskp, int plen)
958 {
959 	if (plen == 0)
960 		maskp->s_addr = 0;
961 	else
962 		maskp->s_addr = htonl(0xffffffff << (32 - plen));
963 }
964