xref: /openbsd-src/sys/netinet/in.c (revision 2777ee89d0e541ec819d05abee114837837abbec)
1 /*	$OpenBSD: in.c,v 1.127 2016/04/18 06:43:51 mpi 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 void in_len2mask(struct in_addr *, int);
87 int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
88 	struct ifnet *);
89 
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
102 in_canforward(struct in_addr in)
103 {
104 	u_int32_t net;
105 
106 	if (IN_EXPERIMENTAL(in.s_addr) || 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
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
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
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 /*
170  * Generic internet control operations (ioctl's).
171  */
172 int
173 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
174 {
175 	struct ifreq *ifr = (struct ifreq *)data;
176 	struct ifaddr *ifa;
177 	struct in_ifaddr *ia = NULL;
178 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
179 	struct sockaddr_in oldaddr;
180 	int error;
181 	int newifaddr;
182 	int s;
183 
184 	switch (cmd) {
185 #ifdef MROUTING
186 	case SIOCGETVIFCNT:
187 	case SIOCGETSGCNT:
188 		return (mrt_ioctl(so, cmd, data));
189 #endif /* MROUTING */
190 	case SIOCALIFADDR:
191 	case SIOCDLIFADDR:
192 		if ((so->so_state & SS_PRIV) == 0)
193 			return (EPERM);
194 		/* FALLTHROUGH */
195 	case SIOCGLIFADDR:
196 		if (ifp == NULL)
197 			return (EINVAL);
198 		return in_lifaddr_ioctl(so, cmd, data, ifp);
199 	default:
200 		if (ifp == NULL)
201 			return (EOPNOTSUPP);
202 	}
203 
204 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
205 		if (ifa->ifa_addr->sa_family == AF_INET) {
206 			ia = ifatoia(ifa);
207 			break;
208 		}
209 	}
210 
211 	switch (cmd) {
212 
213 	case SIOCAIFADDR:
214 	case SIOCDIFADDR:
215 		if (ifra->ifra_addr.sin_family == AF_INET) {
216 			for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) {
217 				if ((ifa->ifa_addr->sa_family == AF_INET) &&
218 				    ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
219 				    ifra->ifra_addr.sin_addr.s_addr)
220 					break;
221 			}
222 			ia = ifatoia(ifa);
223 		}
224 		if (cmd == SIOCDIFADDR && ia == NULL)
225 			return (EADDRNOTAVAIL);
226 		/* FALLTHROUGH */
227 	case SIOCSIFADDR:
228 		if ((so->so_state & SS_PRIV) == 0)
229 			return (EPERM);
230 
231 		if (ia == NULL) {
232 			ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
233 			ia->ia_addr.sin_family = AF_INET;
234 			ia->ia_addr.sin_len = sizeof(ia->ia_addr);
235 			ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
236 			ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
237 			ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
238 			ia->ia_sockmask.sin_len = 8;
239 			if (ifp->if_flags & IFF_BROADCAST) {
240 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
241 				ia->ia_broadaddr.sin_family = AF_INET;
242 			}
243 			ia->ia_ifp = ifp;
244 
245 			newifaddr = 1;
246 		} else
247 			newifaddr = 0;
248 		break;
249 
250 	case SIOCSIFNETMASK:
251 	case SIOCSIFDSTADDR:
252 	case SIOCSIFBRDADDR:
253 		if ((so->so_state & SS_PRIV) == 0)
254 			return (EPERM);
255 		/* FALLTHROUGH */
256 
257 	case SIOCGIFADDR:
258 	case SIOCGIFNETMASK:
259 	case SIOCGIFDSTADDR:
260 	case SIOCGIFBRDADDR:
261 		if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
262 			for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) {
263 				if ((ifa->ifa_addr->sa_family == AF_INET) &&
264 				    ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
265 				    satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
266 					ia = ifatoia(ifa);
267 					break;
268 				}
269 			}
270 		}
271 		if (ia == NULL)
272 			return (EADDRNOTAVAIL);
273 		break;
274 	}
275 	switch (cmd) {
276 
277 	case SIOCGIFADDR:
278 		*satosin(&ifr->ifr_addr) = ia->ia_addr;
279 		break;
280 
281 	case SIOCGIFBRDADDR:
282 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
283 			return (EINVAL);
284 		*satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
285 		break;
286 
287 	case SIOCGIFDSTADDR:
288 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
289 			return (EINVAL);
290 		*satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
291 		break;
292 
293 	case SIOCGIFNETMASK:
294 		*satosin(&ifr->ifr_addr) = ia->ia_sockmask;
295 		break;
296 
297 	case SIOCSIFDSTADDR:
298 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
299 			return (EINVAL);
300 		s = splsoftnet();
301 		oldaddr = ia->ia_dstaddr;
302 		ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
303 		if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
304 					(ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
305 			ia->ia_dstaddr = oldaddr;
306 			splx(s);
307 			return (error);
308 		}
309 		in_scrubhost(ia, &oldaddr);
310 		in_addhost(ia, &ia->ia_dstaddr);
311 		splx(s);
312 		break;
313 
314 	case SIOCSIFBRDADDR:
315 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
316 			return (EINVAL);
317 		ifa_update_broadaddr(ifp, &ia->ia_ifa, &ifr->ifr_broadaddr);
318 		break;
319 
320 	case SIOCSIFADDR:
321 		s = splsoftnet();
322 		in_ifscrub(ifp, ia);
323 		error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), newifaddr);
324 		if (!error)
325 			dohooks(ifp->if_addrhooks, 0);
326 		splx(s);
327 		return (error);
328 
329 	case SIOCSIFNETMASK:
330 		ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
331 		    ifra->ifra_addr.sin_addr.s_addr;
332 		break;
333 
334 	case SIOCAIFADDR: {
335 		int needinit = 0;
336 
337 		error = 0;
338 
339 		s = splsoftnet();
340 		if (ia->ia_addr.sin_family == AF_INET) {
341 			if (ifra->ifra_addr.sin_len == 0)
342 				ifra->ifra_addr = ia->ia_addr;
343 			else if (ifra->ifra_addr.sin_addr.s_addr !=
344 			    ia->ia_addr.sin_addr.s_addr || newifaddr)
345 				needinit = 1;
346 		}
347 		if (ifra->ifra_mask.sin_len) {
348 			in_ifscrub(ifp, ia);
349 			ia->ia_sockmask = ifra->ifra_mask;
350 			ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr;
351 			needinit = 1;
352 		}
353 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
354 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
355 			in_ifscrub(ifp, ia);
356 			ia->ia_dstaddr = ifra->ifra_dstaddr;
357 			needinit  = 1;
358 		}
359 		if ((ifp->if_flags & IFF_BROADCAST) &&
360 		    (ifra->ifra_broadaddr.sin_family == AF_INET)) {
361 			if (newifaddr)
362 				ia->ia_broadaddr = ifra->ifra_broadaddr;
363 			else
364 				ifa_update_broadaddr(ifp, &ia->ia_ifa,
365 				    sintosa(&ifra->ifra_broadaddr));
366 		}
367 		if (ifra->ifra_addr.sin_family == AF_INET && needinit) {
368 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, newifaddr);
369 		}
370 		if (!error)
371 			dohooks(ifp->if_addrhooks, 0);
372 		splx(s);
373 		return (error);
374 		}
375 	case SIOCDIFADDR:
376 		/*
377 		 * Even if the individual steps were safe, shouldn't
378 		 * these kinds of changes happen atomically?  What
379 		 * should happen to a packet that was routed after
380 		 * the scrub but before the other steps?
381 		 */
382 		s = splsoftnet();
383 		in_purgeaddr(&ia->ia_ifa);
384 		dohooks(ifp->if_addrhooks, 0);
385 		splx(s);
386 		break;
387 
388 	default:
389 		if (ifp->if_ioctl == NULL)
390 			return (EOPNOTSUPP);
391 		return ((*ifp->if_ioctl)(ifp, cmd, data));
392 	}
393 	return (0);
394 }
395 
396 /*
397  * SIOC[GAD]LIFADDR.
398  *	SIOCGLIFADDR: get first address. (???)
399  *	SIOCGLIFADDR with IFLR_PREFIX:
400  *		get first address that matches the specified prefix.
401  *	SIOCALIFADDR: add the specified address.
402  *	SIOCALIFADDR with IFLR_PREFIX:
403  *		EINVAL since we can't deduce hostid part of the address.
404  *	SIOCDLIFADDR: delete the specified address.
405  *	SIOCDLIFADDR with IFLR_PREFIX:
406  *		delete the first address that matches the specified prefix.
407  * return values:
408  *	EINVAL on invalid parameters
409  *	EADDRNOTAVAIL on prefix match failed/specified address not found
410  *	other values may be returned from in_ioctl()
411  */
412 int
413 in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
414     struct ifnet *ifp)
415 {
416 	struct if_laddrreq *iflr = (struct if_laddrreq *)data;
417 	struct ifaddr *ifa;
418 	struct sockaddr *sa;
419 
420 	/* sanity checks */
421 	if (!data || !ifp) {
422 		panic("invalid argument to in_lifaddr_ioctl");
423 		/*NOTRECHED*/
424 	}
425 
426 	switch (cmd) {
427 	case SIOCGLIFADDR:
428 		/* address must be specified on GET with IFLR_PREFIX */
429 		if ((iflr->flags & IFLR_PREFIX) == 0)
430 			break;
431 		/*FALLTHROUGH*/
432 	case SIOCALIFADDR:
433 	case SIOCDLIFADDR:
434 		/* address must be specified on ADD and DELETE */
435 		sa = (struct sockaddr *)&iflr->addr;
436 		if (sa->sa_family != AF_INET)
437 			return EINVAL;
438 		if (sa->sa_len != sizeof(struct sockaddr_in))
439 			return EINVAL;
440 		/* XXX need improvement */
441 		sa = (struct sockaddr *)&iflr->dstaddr;
442 		if (sa->sa_family
443 		 && sa->sa_family != AF_INET)
444 			return EINVAL;
445 		if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
446 			return EINVAL;
447 		break;
448 	default: /*shouldn't happen*/
449 #if 0
450 		panic("invalid cmd to in_lifaddr_ioctl");
451 		/*NOTREACHED*/
452 #else
453 		return EOPNOTSUPP;
454 #endif
455 	}
456 	if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
457 		return EINVAL;
458 
459 	switch (cmd) {
460 	case SIOCALIFADDR:
461 	    {
462 		struct in_aliasreq ifra;
463 
464 		if (iflr->flags & IFLR_PREFIX)
465 			return EINVAL;
466 
467 		/* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
468 		bzero(&ifra, sizeof(ifra));
469 		memcpy(ifra.ifra_name, iflr->iflr_name,
470 		    sizeof(ifra.ifra_name));
471 
472 		memcpy(&ifra.ifra_addr, &iflr->addr,
473 		    ((struct sockaddr *)&iflr->addr)->sa_len);
474 
475 		if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {	/*XXX*/
476 			memcpy(&ifra.ifra_dstaddr, &iflr->dstaddr,
477 			    ((struct sockaddr *)&iflr->dstaddr)->sa_len);
478 		}
479 
480 		ifra.ifra_mask.sin_family = AF_INET;
481 		ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
482 		in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
483 
484 		return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp);
485 	    }
486 	case SIOCGLIFADDR:
487 	case SIOCDLIFADDR:
488 	    {
489 		struct in_ifaddr *ia;
490 		struct in_addr mask, candidate, match;
491 		struct sockaddr_in *sin;
492 		int cmp;
493 
494 		bzero(&mask, sizeof(mask));
495 		if (iflr->flags & IFLR_PREFIX) {
496 			/* lookup a prefix rather than address. */
497 			in_len2mask(&mask, iflr->prefixlen);
498 
499 			sin = (struct sockaddr_in *)&iflr->addr;
500 			match.s_addr = sin->sin_addr.s_addr;
501 			match.s_addr &= mask.s_addr;
502 
503 			/* if you set extra bits, that's wrong */
504 			if (match.s_addr != sin->sin_addr.s_addr)
505 				return EINVAL;
506 
507 			cmp = 1;
508 		} else {
509 			if (cmd == SIOCGLIFADDR) {
510 				/* on getting an address, take the 1st match */
511 				cmp = 0;	/*XXX*/
512 			} else {
513 				/* on deleting an address, do exact match */
514 				in_len2mask(&mask, 32);
515 				sin = (struct sockaddr_in *)&iflr->addr;
516 				match.s_addr = sin->sin_addr.s_addr;
517 
518 				cmp = 1;
519 			}
520 		}
521 
522 		TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
523 			if (ifa->ifa_addr->sa_family != AF_INET)
524 				continue;
525 			if (!cmp)
526 				break;
527 			candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
528 			candidate.s_addr &= mask.s_addr;
529 			if (candidate.s_addr == match.s_addr)
530 				break;
531 		}
532 		if (!ifa)
533 			return EADDRNOTAVAIL;
534 		ia = ifatoia(ifa);
535 
536 		if (cmd == SIOCGLIFADDR) {
537 			/* fill in the if_laddrreq structure */
538 			memcpy(&iflr->addr, &ia->ia_addr, ia->ia_addr.sin_len);
539 
540 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
541 				memcpy(&iflr->dstaddr, &ia->ia_dstaddr,
542 				    ia->ia_dstaddr.sin_len);
543 			} else
544 				bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
545 
546 			iflr->prefixlen =
547 				in_mask2len(&ia->ia_sockmask.sin_addr);
548 
549 			iflr->flags = 0;	/*XXX*/
550 
551 			return 0;
552 		} else {
553 			struct in_aliasreq ifra;
554 
555 			/* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
556 			bzero(&ifra, sizeof(ifra));
557 			memcpy(ifra.ifra_name, iflr->iflr_name,
558 			    sizeof(ifra.ifra_name));
559 
560 			memcpy(&ifra.ifra_addr, &ia->ia_addr,
561 			    ia->ia_addr.sin_len);
562 			if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
563 				memcpy(&ifra.ifra_dstaddr, &ia->ia_dstaddr,
564 				    ia->ia_dstaddr.sin_len);
565 			}
566 			memcpy(&ifra.ifra_dstaddr, &ia->ia_sockmask,
567 			    ia->ia_sockmask.sin_len);
568 
569 			return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp);
570 		}
571 	    }
572 	}
573 
574 	return EOPNOTSUPP;	/*just for safety*/
575 }
576 
577 /*
578  * Delete any existing route for an interface.
579  */
580 void
581 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
582 {
583 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT))
584 		in_scrubhost(ia, &ia->ia_dstaddr);
585 	else if (!ISSET(ifp->if_flags, IFF_LOOPBACK))
586 		in_remove_prefix(ia);
587 }
588 
589 /*
590  * Initialize an interface's internet address
591  * and routing table entry.
592  */
593 int
594 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
595     int newaddr)
596 {
597 	u_int32_t i = sin->sin_addr.s_addr;
598 	struct sockaddr_in oldaddr;
599 	int error = 0;
600 
601 	splsoftassert(IPL_SOFTNET);
602 
603 	/*
604 	 * Always remove the address from the tree to make sure its
605 	 * position gets updated in case the key changes.
606 	 */
607 	if (!newaddr) {
608 		rt_ifa_dellocal(&ia->ia_ifa);
609 		ifa_del(ifp, &ia->ia_ifa);
610 	}
611 	oldaddr = ia->ia_addr;
612 	ia->ia_addr = *sin;
613 
614 	/*
615 	 * Give the interface a chance to initialize
616 	 * if this is its first address,
617 	 * and to validate the address if necessary.
618 	 */
619 	if (ifp->if_ioctl &&
620 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
621 		ia->ia_addr = oldaddr;
622 	}
623 
624 	/*
625 	 * Add the address to the local list and the global tree.  If an
626 	 * error occured, put back the original address.
627 	 */
628 	ifa_add(ifp, &ia->ia_ifa);
629 	rt_ifa_addlocal(&ia->ia_ifa);
630 
631 	if (error)
632 		goto out;
633 
634 	if (ia->ia_netmask == 0) {
635 		if (IN_CLASSA(i))
636 			ia->ia_netmask = IN_CLASSA_NET;
637 		else if (IN_CLASSB(i))
638 			ia->ia_netmask = IN_CLASSB_NET;
639 		else
640 			ia->ia_netmask = IN_CLASSC_NET;
641 		ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask;
642 	}
643 
644 	ia->ia_net = i & ia->ia_netmask;
645 	in_socktrim(&ia->ia_sockmask);
646 	/*
647 	 * Add route for the network.
648 	 */
649 	ia->ia_ifa.ifa_metric = ifp->if_metric;
650 	if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
651 		if (IN_RFC3021_SUBNET(ia->ia_netmask))
652 			ia->ia_broadaddr.sin_addr.s_addr = 0;
653 		else {
654 			ia->ia_broadaddr.sin_addr.s_addr =
655 			    ia->ia_net | ~ia->ia_netmask;
656 		}
657 	}
658 
659 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) {
660 		/* XXX We should not even call in_ifinit() in this case. */
661 		if (ia->ia_dstaddr.sin_family != AF_INET)
662 			goto out;
663 		error = in_addhost(ia, &ia->ia_dstaddr);
664 	} else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) {
665 		error = in_insert_prefix(ia);
666 	}
667 
668 	/*
669 	 * If the interface supports multicast, join the "all hosts"
670 	 * multicast group on that interface.
671 	 */
672 	if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
673 		struct in_addr addr;
674 
675 		addr.s_addr = INADDR_ALLHOSTS_GROUP;
676 		ia->ia_allhosts = in_addmulti(&addr, ifp);
677 	}
678 
679 out:
680 	if (error && newaddr)
681 		in_purgeaddr(&ia->ia_ifa);
682 
683 	return (error);
684 }
685 
686 void
687 in_purgeaddr(struct ifaddr *ifa)
688 {
689 	struct ifnet *ifp = ifa->ifa_ifp;
690 	struct in_ifaddr *ia = ifatoia(ifa);
691 
692 	splsoftassert(IPL_SOFTNET);
693 
694 	in_ifscrub(ifp, ia);
695 
696 	rt_ifa_dellocal(&ia->ia_ifa);
697 	ifa_del(ifp, &ia->ia_ifa);
698 
699 	if (ia->ia_allhosts != NULL) {
700 		in_delmulti(ia->ia_allhosts);
701 		ia->ia_allhosts = NULL;
702 	}
703 
704 	ia->ia_ifp = NULL;
705 	ifafree(&ia->ia_ifa);
706 }
707 
708 int
709 in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
710 {
711 	return rt_ifa_add(&ia->ia_ifa, RTF_HOST, sintosa(dst));
712 }
713 
714 int
715 in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
716 {
717 	return rt_ifa_del(&ia->ia_ifa, RTF_HOST, sintosa(dst));
718 }
719 
720 /*
721  * Insert the cloning and broadcast routes for this subnet.
722  */
723 int
724 in_insert_prefix(struct in_ifaddr *ia)
725 {
726 	struct ifaddr *ifa = &ia->ia_ifa;
727 	int error;
728 
729 	error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr);
730 	if (error)
731 		return (error);
732 
733 	if (ia->ia_broadaddr.sin_addr.s_addr != 0)
734 		error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST,
735 		    ifa->ifa_broadaddr);
736 
737 	return (error);
738 }
739 
740 void
741 in_remove_prefix(struct in_ifaddr *ia)
742 {
743 	struct ifaddr *ifa = &ia->ia_ifa;
744 
745 	rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr);
746 
747 	if (ia->ia_broadaddr.sin_addr.s_addr != 0)
748 		rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST, ifa->ifa_broadaddr);
749 }
750 
751 /*
752  * Return 1 if the address is a local broadcast address.
753  */
754 int
755 in_broadcast(struct in_addr in, u_int rtableid)
756 {
757 	struct ifnet *ifn;
758 	struct ifaddr *ifa;
759 	u_int rdomain;
760 
761 	rdomain = rtable_l2(rtableid);
762 
763 #define ia (ifatoia(ifa))
764 	TAILQ_FOREACH(ifn, &ifnet, if_list) {
765 		if (ifn->if_rdomain != rdomain)
766 			continue;
767 		if ((ifn->if_flags & IFF_BROADCAST) == 0)
768 			continue;
769 		TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
770 			if (ifa->ifa_addr->sa_family == AF_INET &&
771 			    in.s_addr != ia->ia_addr.sin_addr.s_addr &&
772 			    in.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
773 				return 1;
774 	}
775 	return (0);
776 #undef ia
777 }
778 
779 /*
780  * Add an address to the list of IP multicast addresses for a given interface.
781  */
782 struct in_multi *
783 in_addmulti(struct in_addr *ap, struct ifnet *ifp)
784 {
785 	struct in_multi *inm;
786 	struct ifreq ifr;
787 	int s;
788 
789 	/*
790 	 * See if address already in list.
791 	 */
792 	IN_LOOKUP_MULTI(*ap, ifp, inm);
793 	if (inm != NULL) {
794 		/*
795 		 * Found it; just increment the reference count.
796 		 */
797 		++inm->inm_refcnt;
798 	} else {
799 		if (ifp->if_ioctl == NULL)
800 			return (NULL);
801 
802 		/*
803 		 * New address; allocate a new multicast record
804 		 * and link it into the interface's multicast list.
805 		 */
806 		inm = malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZERO);
807 		if (inm == NULL)
808 			return (NULL);
809 
810 		inm->inm_sin.sin_len = sizeof(struct sockaddr_in);
811 		inm->inm_sin.sin_family = AF_INET;
812 		inm->inm_sin.sin_addr = *ap;
813 		inm->inm_refcnt = 1;
814 		inm->inm_ifidx = ifp->if_index;
815 		inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin);
816 
817 		/*
818 		 * Ask the network driver to update its multicast reception
819 		 * filter appropriately for the new address.
820 		 */
821 		memset(&ifr, 0, sizeof(ifr));
822 		memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin));
823 		if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
824 			free(inm, M_IPMADDR, sizeof(*inm));
825 			return (NULL);
826 		}
827 
828 		s = splsoftnet();
829 		TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma,
830 		    ifma_list);
831 		splx(s);
832 
833 		/*
834 		 * Let IGMP know that we have joined a new IP multicast group.
835 		 */
836 		igmp_joingroup(inm);
837 	}
838 
839 	return (inm);
840 }
841 
842 /*
843  * Delete a multicast address record.
844  */
845 void
846 in_delmulti(struct in_multi *inm)
847 {
848 	struct ifreq ifr;
849 	struct ifnet *ifp;
850 	int s;
851 
852 	if (--inm->inm_refcnt == 0) {
853 		/*
854 		 * No remaining claims to this record; let IGMP know that
855 		 * we are leaving the multicast group.
856 		 */
857 		igmp_leavegroup(inm);
858 		ifp = if_get(inm->inm_ifidx);
859 
860 		/*
861 		 * Notify the network driver to update its multicast
862 		 * reception filter.
863 		 */
864 		if (ifp != NULL) {
865 			memset(&ifr, 0, sizeof(ifr));
866 			satosin(&ifr.ifr_addr)->sin_len =
867 			    sizeof(struct sockaddr_in);
868 			satosin(&ifr.ifr_addr)->sin_family = AF_INET;
869 			satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
870 			(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
871 
872 			s = splsoftnet();
873 			TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma,
874 			    ifma_list);
875 			splx(s);
876 		}
877 		if_put(ifp);
878 
879 		free(inm, M_IPMADDR, sizeof(*inm));
880 	}
881 }
882 
883 /*
884  * Return 1 if the multicast group represented by ``ap'' has been
885  * joined by interface ``ifp'', 0 otherwise.
886  */
887 int
888 in_hasmulti(struct in_addr *ap, struct ifnet *ifp)
889 {
890 	struct in_multi *inm;
891 	int joined;
892 
893 	KERNEL_LOCK();
894 	IN_LOOKUP_MULTI(*ap, ifp, inm);
895 	joined = (inm != NULL);
896 	KERNEL_UNLOCK();
897 
898 	return (joined);
899 }
900 
901 void
902 in_ifdetach(struct ifnet *ifp)
903 {
904 	struct ifaddr *ifa, *next;
905 
906 	/* nuke any of IPv4 addresses we have */
907 	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) {
908 		if (ifa->ifa_addr->sa_family != AF_INET)
909 			continue;
910 		in_purgeaddr(ifa);
911 		dohooks(ifp->if_addrhooks, 0);
912 	}
913 }
914 
915 void
916 in_prefixlen2mask(struct in_addr *maskp, int plen)
917 {
918 	if (plen == 0)
919 		maskp->s_addr = 0;
920 	else
921 		maskp->s_addr = htonl(0xffffffff << (32 - plen));
922 }
923