xref: /openbsd-src/sys/netinet/in.c (revision c0dd97bfcad3dab6c31ec12b9de1274fd2d2f993)
1 /*	$OpenBSD: in.c,v 1.143 2017/10/24 09:30:15 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 
87 void in_purgeaddr(struct ifaddr *);
88 int in_addhost(struct in_ifaddr *, struct sockaddr_in *);
89 int in_scrubhost(struct in_ifaddr *, struct sockaddr_in *);
90 int in_insert_prefix(struct in_ifaddr *);
91 void in_remove_prefix(struct in_ifaddr *);
92 
93 /*
94  * Determine whether an IP address is in a reserved set of addresses
95  * that may not be forwarded, or whether datagrams to that destination
96  * may be forwarded.
97  */
98 int
99 in_canforward(struct in_addr in)
100 {
101 	u_int32_t net;
102 
103 	if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
104 		return (0);
105 	if (IN_CLASSA(in.s_addr)) {
106 		net = in.s_addr & IN_CLASSA_NET;
107 		if (net == 0 ||
108 		    net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
109 			return (0);
110 	}
111 	return (1);
112 }
113 
114 /*
115  * Trim a mask in a sockaddr
116  */
117 void
118 in_socktrim(struct sockaddr_in *ap)
119 {
120 	char *cplim = (char *) &ap->sin_addr;
121 	char *cp = (char *) (&ap->sin_addr + 1);
122 
123 	ap->sin_len = 0;
124 	while (--cp >= cplim)
125 		if (*cp) {
126 			(ap)->sin_len = cp - (char *) (ap) + 1;
127 			break;
128 		}
129 }
130 
131 int
132 in_mask2len(struct in_addr *mask)
133 {
134 	int x, y;
135 	u_char *p;
136 
137 	p = (u_char *)mask;
138 	for (x = 0; x < sizeof(*mask); x++) {
139 		if (p[x] != 0xff)
140 			break;
141 	}
142 	y = 0;
143 	if (x < sizeof(*mask)) {
144 		for (y = 0; y < 8; y++) {
145 			if ((p[x] & (0x80 >> y)) == 0)
146 				break;
147 		}
148 	}
149 	return x * 8 + y;
150 }
151 
152 void
153 in_len2mask(struct in_addr *mask, int len)
154 {
155 	int i;
156 	u_char *p;
157 
158 	p = (u_char *)mask;
159 	bzero(mask, sizeof(*mask));
160 	for (i = 0; i < len / 8; i++)
161 		p[i] = 0xff;
162 	if (len % 8)
163 		p[i] = (0xff00 >> (len % 8)) & 0xff;
164 }
165 
166 int
167 in_nam2sin(const struct mbuf *nam, struct sockaddr_in **sin)
168 {
169 	struct sockaddr *sa = mtod(nam, struct sockaddr *);
170 
171 	if (nam->m_len < offsetof(struct sockaddr, sa_data))
172 		return EINVAL;
173 	if (sa->sa_family != AF_INET)
174 		return EAFNOSUPPORT;
175 	if (sa->sa_len != nam->m_len)
176 		return EINVAL;
177 	if (sa->sa_len != sizeof(struct sockaddr_in))
178 		return EINVAL;
179 	*sin = satosin(sa);
180 
181 	return 0;
182 }
183 
184 int
185 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
186 {
187 	int privileged;
188 
189 	privileged = 0;
190 	if ((so->so_state & SS_PRIV) != 0)
191 		privileged++;
192 
193 #ifdef MROUTING
194 	switch (cmd) {
195 	case SIOCGETVIFCNT:
196 	case SIOCGETSGCNT:
197 		return (mrt_ioctl(so, cmd, data));
198 	}
199 #endif /* MROUTING */
200 
201 	return (in_ioctl(cmd, data, ifp, privileged));
202 }
203 
204 int
205 in_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, int privileged)
206 {
207 	struct ifreq *ifr = (struct ifreq *)data;
208 	struct ifaddr *ifa;
209 	struct in_ifaddr *ia = NULL;
210 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
211 	struct sockaddr_in oldaddr;
212 	int error;
213 	int newifaddr;
214 
215 	if (ifp == NULL)
216 		return (EOPNOTSUPP);
217 
218 	NET_ASSERT_LOCKED();
219 
220 	TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
221 		if (ifa->ifa_addr->sa_family == AF_INET) {
222 			ia = ifatoia(ifa);
223 			break;
224 		}
225 	}
226 
227 	switch (cmd) {
228 
229 	case SIOCAIFADDR:
230 	case SIOCDIFADDR:
231 		if (ifra->ifra_addr.sin_family == AF_INET) {
232 			for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) {
233 				if ((ifa->ifa_addr->sa_family == AF_INET) &&
234 				    ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
235 				    ifra->ifra_addr.sin_addr.s_addr)
236 					break;
237 			}
238 			ia = ifatoia(ifa);
239 		}
240 		if (cmd == SIOCDIFADDR && ia == NULL)
241 			return (EADDRNOTAVAIL);
242 		/* FALLTHROUGH */
243 	case SIOCSIFADDR:
244 		if (!privileged)
245 			return (EPERM);
246 
247 		if (ia == NULL) {
248 			ia = malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
249 			ia->ia_addr.sin_family = AF_INET;
250 			ia->ia_addr.sin_len = sizeof(ia->ia_addr);
251 			ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
252 			ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
253 			ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
254 			ia->ia_sockmask.sin_len = 8;
255 			if (ifp->if_flags & IFF_BROADCAST) {
256 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
257 				ia->ia_broadaddr.sin_family = AF_INET;
258 			}
259 			ia->ia_ifp = ifp;
260 
261 			newifaddr = 1;
262 		} else
263 			newifaddr = 0;
264 		break;
265 
266 	case SIOCSIFNETMASK:
267 	case SIOCSIFDSTADDR:
268 	case SIOCSIFBRDADDR:
269 		if (!privileged)
270 			return (EPERM);
271 		/* FALLTHROUGH */
272 
273 	case SIOCGIFADDR:
274 	case SIOCGIFNETMASK:
275 	case SIOCGIFDSTADDR:
276 	case SIOCGIFBRDADDR:
277 		if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
278 			for (; ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_list)) {
279 				if ((ifa->ifa_addr->sa_family == AF_INET) &&
280 				    ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
281 				    satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
282 					ia = ifatoia(ifa);
283 					break;
284 				}
285 			}
286 		}
287 		if (ia == NULL)
288 			return (EADDRNOTAVAIL);
289 		break;
290 	}
291 	switch (cmd) {
292 
293 	case SIOCGIFADDR:
294 		*satosin(&ifr->ifr_addr) = ia->ia_addr;
295 		break;
296 
297 	case SIOCGIFBRDADDR:
298 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
299 			return (EINVAL);
300 		*satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
301 		break;
302 
303 	case SIOCGIFDSTADDR:
304 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
305 			return (EINVAL);
306 		*satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
307 		break;
308 
309 	case SIOCGIFNETMASK:
310 		*satosin(&ifr->ifr_addr) = ia->ia_sockmask;
311 		break;
312 
313 	case SIOCSIFDSTADDR:
314 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
315 			return (EINVAL);
316 		oldaddr = ia->ia_dstaddr;
317 		ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
318 		error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (caddr_t)ia);
319 		if (error) {
320 			ia->ia_dstaddr = oldaddr;
321 			return (error);
322 		}
323 		in_scrubhost(ia, &oldaddr);
324 		in_addhost(ia, &ia->ia_dstaddr);
325 		break;
326 
327 	case SIOCSIFBRDADDR:
328 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
329 			return (EINVAL);
330 		ifa_update_broadaddr(ifp, &ia->ia_ifa, &ifr->ifr_broadaddr);
331 		break;
332 
333 	case SIOCSIFADDR:
334 		in_ifscrub(ifp, ia);
335 		error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), newifaddr);
336 		if (!error)
337 			dohooks(ifp->if_addrhooks, 0);
338 		return (error);
339 
340 	case SIOCSIFNETMASK:
341 		ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr =
342 		    ifra->ifra_addr.sin_addr.s_addr;
343 		break;
344 
345 	case SIOCAIFADDR: {
346 		int needinit = 0;
347 
348 		error = 0;
349 
350 		if (ia->ia_addr.sin_family == AF_INET) {
351 			if (ifra->ifra_addr.sin_len == 0)
352 				ifra->ifra_addr = ia->ia_addr;
353 			else if (ifra->ifra_addr.sin_addr.s_addr !=
354 			    ia->ia_addr.sin_addr.s_addr || newifaddr)
355 				needinit = 1;
356 		}
357 		if (ifra->ifra_mask.sin_len) {
358 			in_ifscrub(ifp, ia);
359 			ia->ia_sockmask = ifra->ifra_mask;
360 			ia->ia_netmask = ia->ia_sockmask.sin_addr.s_addr;
361 			needinit = 1;
362 		}
363 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
364 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
365 			in_ifscrub(ifp, ia);
366 			ia->ia_dstaddr = ifra->ifra_dstaddr;
367 			needinit  = 1;
368 		}
369 		if ((ifp->if_flags & IFF_BROADCAST) &&
370 		    (ifra->ifra_broadaddr.sin_family == AF_INET)) {
371 			if (newifaddr)
372 				ia->ia_broadaddr = ifra->ifra_broadaddr;
373 			else
374 				ifa_update_broadaddr(ifp, &ia->ia_ifa,
375 				    sintosa(&ifra->ifra_broadaddr));
376 		}
377 		if (ifra->ifra_addr.sin_family == AF_INET && needinit) {
378 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, newifaddr);
379 		}
380 		if (!error)
381 			dohooks(ifp->if_addrhooks, 0);
382 		return (error);
383 		}
384 	case SIOCDIFADDR:
385 		/*
386 		 * Even if the individual steps were safe, shouldn't
387 		 * these kinds of changes happen atomically?  What
388 		 * should happen to a packet that was routed after
389 		 * the scrub but before the other steps?
390 		 */
391 		in_purgeaddr(&ia->ia_ifa);
392 		dohooks(ifp->if_addrhooks, 0);
393 		break;
394 
395 	default:
396 		error = ((*ifp->if_ioctl)(ifp, cmd, data));
397 		return (error);
398 	}
399 	return (0);
400 }
401 /*
402  * Delete any existing route for an interface.
403  */
404 void
405 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
406 {
407 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT))
408 		in_scrubhost(ia, &ia->ia_dstaddr);
409 	else if (!ISSET(ifp->if_flags, IFF_LOOPBACK))
410 		in_remove_prefix(ia);
411 }
412 
413 /*
414  * Initialize an interface's internet address
415  * and routing table entry.
416  */
417 int
418 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
419     int newaddr)
420 {
421 	u_int32_t i = sin->sin_addr.s_addr;
422 	struct sockaddr_in oldaddr;
423 	int error = 0, rterror;
424 
425 	NET_ASSERT_LOCKED();
426 
427 	/*
428 	 * Always remove the address from the tree to make sure its
429 	 * position gets updated in case the key changes.
430 	 */
431 	if (!newaddr) {
432 		rt_ifa_dellocal(&ia->ia_ifa);
433 		ifa_del(ifp, &ia->ia_ifa);
434 	}
435 	oldaddr = ia->ia_addr;
436 	ia->ia_addr = *sin;
437 
438 	if (ia->ia_netmask == 0) {
439 		if (IN_CLASSA(i))
440 			ia->ia_netmask = IN_CLASSA_NET;
441 		else if (IN_CLASSB(i))
442 			ia->ia_netmask = IN_CLASSB_NET;
443 		else
444 			ia->ia_netmask = IN_CLASSC_NET;
445 		ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask;
446 	}
447 
448 	/*
449 	 * Give the interface a chance to initialize
450 	 * if this is its first address,
451 	 * and to validate the address if necessary.
452 	 */
453 	if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
454 		ia->ia_addr = oldaddr;
455 	}
456 
457 	/*
458 	 * Add the address to the local list and the global tree.  If an
459 	 * error occured, put back the original address.
460 	 */
461 	ifa_add(ifp, &ia->ia_ifa);
462 	rterror = rt_ifa_addlocal(&ia->ia_ifa);
463 
464 	if (rterror) {
465 		if (!newaddr)
466 			ifa_del(ifp, &ia->ia_ifa);
467 		if (!error)
468 			error = rterror;
469 		goto out;
470 	}
471 	if (error)
472 		goto out;
473 
474 
475 	ia->ia_net = i & ia->ia_netmask;
476 	in_socktrim(&ia->ia_sockmask);
477 	/*
478 	 * Add route for the network.
479 	 */
480 	ia->ia_ifa.ifa_metric = ifp->if_metric;
481 	if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
482 		if (IN_RFC3021_SUBNET(ia->ia_netmask))
483 			ia->ia_broadaddr.sin_addr.s_addr = 0;
484 		else {
485 			ia->ia_broadaddr.sin_addr.s_addr =
486 			    ia->ia_net | ~ia->ia_netmask;
487 		}
488 	}
489 
490 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) {
491 		/* XXX We should not even call in_ifinit() in this case. */
492 		if (ia->ia_dstaddr.sin_family != AF_INET)
493 			goto out;
494 		error = in_addhost(ia, &ia->ia_dstaddr);
495 	} else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) {
496 		error = in_insert_prefix(ia);
497 	}
498 
499 	/*
500 	 * If the interface supports multicast, join the "all hosts"
501 	 * multicast group on that interface.
502 	 */
503 	if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
504 		struct in_addr addr;
505 
506 		addr.s_addr = INADDR_ALLHOSTS_GROUP;
507 		ia->ia_allhosts = in_addmulti(&addr, ifp);
508 	}
509 
510 out:
511 	if (error && newaddr)
512 		in_purgeaddr(&ia->ia_ifa);
513 
514 	return (error);
515 }
516 
517 void
518 in_purgeaddr(struct ifaddr *ifa)
519 {
520 	struct ifnet *ifp = ifa->ifa_ifp;
521 	struct in_ifaddr *ia = ifatoia(ifa);
522 	extern int ifatrash;
523 
524 	NET_ASSERT_LOCKED();
525 
526 	in_ifscrub(ifp, ia);
527 
528 	rt_ifa_dellocal(&ia->ia_ifa);
529 	rt_ifa_purge(&ia->ia_ifa);
530 	ifa_del(ifp, &ia->ia_ifa);
531 
532 	if (ia->ia_allhosts != NULL) {
533 		in_delmulti(ia->ia_allhosts);
534 		ia->ia_allhosts = NULL;
535 	}
536 
537 	ifatrash++;
538 	ia->ia_ifp = NULL;
539 	ifafree(&ia->ia_ifa);
540 }
541 
542 int
543 in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
544 {
545 	return rt_ifa_add(&ia->ia_ifa, RTF_HOST, sintosa(dst));
546 }
547 
548 int
549 in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
550 {
551 	return rt_ifa_del(&ia->ia_ifa, RTF_HOST, sintosa(dst));
552 }
553 
554 /*
555  * Insert the cloning and broadcast routes for this subnet.
556  */
557 int
558 in_insert_prefix(struct in_ifaddr *ia)
559 {
560 	struct ifaddr *ifa = &ia->ia_ifa;
561 	int error;
562 
563 	error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr);
564 	if (error)
565 		return (error);
566 
567 	if (ia->ia_broadaddr.sin_addr.s_addr != 0)
568 		error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST,
569 		    ifa->ifa_broadaddr);
570 
571 	return (error);
572 }
573 
574 void
575 in_remove_prefix(struct in_ifaddr *ia)
576 {
577 	struct ifaddr *ifa = &ia->ia_ifa;
578 
579 	rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr);
580 
581 	if (ia->ia_broadaddr.sin_addr.s_addr != 0)
582 		rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST, ifa->ifa_broadaddr);
583 }
584 
585 /*
586  * Return 1 if the address is a local broadcast address.
587  */
588 int
589 in_broadcast(struct in_addr in, u_int rtableid)
590 {
591 	struct ifnet *ifn;
592 	struct ifaddr *ifa;
593 	u_int rdomain;
594 
595 	rdomain = rtable_l2(rtableid);
596 
597 #define ia (ifatoia(ifa))
598 	TAILQ_FOREACH(ifn, &ifnet, if_list) {
599 		if (ifn->if_rdomain != rdomain)
600 			continue;
601 		if ((ifn->if_flags & IFF_BROADCAST) == 0)
602 			continue;
603 		TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
604 			if (ifa->ifa_addr->sa_family == AF_INET &&
605 			    in.s_addr != ia->ia_addr.sin_addr.s_addr &&
606 			    in.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
607 				return 1;
608 	}
609 	return (0);
610 #undef ia
611 }
612 
613 /*
614  * Add an address to the list of IP multicast addresses for a given interface.
615  */
616 struct in_multi *
617 in_addmulti(struct in_addr *ap, struct ifnet *ifp)
618 {
619 	struct in_multi *inm;
620 	struct ifreq ifr;
621 
622 	/*
623 	 * See if address already in list.
624 	 */
625 	IN_LOOKUP_MULTI(*ap, ifp, inm);
626 	if (inm != NULL) {
627 		/*
628 		 * Found it; just increment the reference count.
629 		 */
630 		++inm->inm_refcnt;
631 	} else {
632 		/*
633 		 * New address; allocate a new multicast record
634 		 * and link it into the interface's multicast list.
635 		 */
636 		inm = malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZERO);
637 		if (inm == NULL)
638 			return (NULL);
639 
640 		inm->inm_sin.sin_len = sizeof(struct sockaddr_in);
641 		inm->inm_sin.sin_family = AF_INET;
642 		inm->inm_sin.sin_addr = *ap;
643 		inm->inm_refcnt = 1;
644 		inm->inm_ifidx = ifp->if_index;
645 		inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin);
646 
647 		/*
648 		 * Ask the network driver to update its multicast reception
649 		 * filter appropriately for the new address.
650 		 */
651 		memset(&ifr, 0, sizeof(ifr));
652 		memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin));
653 		if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
654 			free(inm, M_IPMADDR, sizeof(*inm));
655 			return (NULL);
656 		}
657 
658 		TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma,
659 		    ifma_list);
660 
661 		/*
662 		 * Let IGMP know that we have joined a new IP multicast group.
663 		 */
664 		igmp_joingroup(inm);
665 	}
666 
667 	return (inm);
668 }
669 
670 /*
671  * Delete a multicast address record.
672  */
673 void
674 in_delmulti(struct in_multi *inm)
675 {
676 	struct ifreq ifr;
677 	struct ifnet *ifp;
678 
679 	NET_ASSERT_LOCKED();
680 
681 	if (--inm->inm_refcnt == 0) {
682 		/*
683 		 * No remaining claims to this record; let IGMP know that
684 		 * we are leaving the multicast group.
685 		 */
686 		igmp_leavegroup(inm);
687 		ifp = if_get(inm->inm_ifidx);
688 
689 		/*
690 		 * Notify the network driver to update its multicast
691 		 * reception filter.
692 		 */
693 		if (ifp != NULL) {
694 			memset(&ifr, 0, sizeof(ifr));
695 			satosin(&ifr.ifr_addr)->sin_len =
696 			    sizeof(struct sockaddr_in);
697 			satosin(&ifr.ifr_addr)->sin_family = AF_INET;
698 			satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
699 			(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
700 
701 			TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma,
702 			    ifma_list);
703 		}
704 		if_put(ifp);
705 
706 		free(inm, M_IPMADDR, sizeof(*inm));
707 	}
708 }
709 
710 /*
711  * Return 1 if the multicast group represented by ``ap'' has been
712  * joined by interface ``ifp'', 0 otherwise.
713  */
714 int
715 in_hasmulti(struct in_addr *ap, struct ifnet *ifp)
716 {
717 	struct in_multi *inm;
718 	int joined;
719 
720 	IN_LOOKUP_MULTI(*ap, ifp, inm);
721 	joined = (inm != NULL);
722 
723 	return (joined);
724 }
725 
726 void
727 in_ifdetach(struct ifnet *ifp)
728 {
729 	struct ifaddr *ifa, *next;
730 
731 	/* nuke any of IPv4 addresses we have */
732 	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) {
733 		if (ifa->ifa_addr->sa_family != AF_INET)
734 			continue;
735 		in_purgeaddr(ifa);
736 		dohooks(ifp->if_addrhooks, 0);
737 	}
738 }
739 
740 void
741 in_prefixlen2mask(struct in_addr *maskp, int plen)
742 {
743 	if (plen == 0)
744 		maskp->s_addr = 0;
745 	else
746 		maskp->s_addr = htonl(0xffffffff << (32 - plen));
747 }
748