xref: /openbsd-src/sys/netinet/in.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: in.c,v 1.144 2017/11/04 13:11:54 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 (ENXIO);
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 		return (EOPNOTSUPP);
397 	}
398 	return (0);
399 }
400 /*
401  * Delete any existing route for an interface.
402  */
403 void
404 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
405 {
406 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT))
407 		in_scrubhost(ia, &ia->ia_dstaddr);
408 	else if (!ISSET(ifp->if_flags, IFF_LOOPBACK))
409 		in_remove_prefix(ia);
410 }
411 
412 /*
413  * Initialize an interface's internet address
414  * and routing table entry.
415  */
416 int
417 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
418     int newaddr)
419 {
420 	u_int32_t i = sin->sin_addr.s_addr;
421 	struct sockaddr_in oldaddr;
422 	int error = 0, rterror;
423 
424 	NET_ASSERT_LOCKED();
425 
426 	/*
427 	 * Always remove the address from the tree to make sure its
428 	 * position gets updated in case the key changes.
429 	 */
430 	if (!newaddr) {
431 		rt_ifa_dellocal(&ia->ia_ifa);
432 		ifa_del(ifp, &ia->ia_ifa);
433 	}
434 	oldaddr = ia->ia_addr;
435 	ia->ia_addr = *sin;
436 
437 	if (ia->ia_netmask == 0) {
438 		if (IN_CLASSA(i))
439 			ia->ia_netmask = IN_CLASSA_NET;
440 		else if (IN_CLASSB(i))
441 			ia->ia_netmask = IN_CLASSB_NET;
442 		else
443 			ia->ia_netmask = IN_CLASSC_NET;
444 		ia->ia_sockmask.sin_addr.s_addr = ia->ia_netmask;
445 	}
446 
447 	/*
448 	 * Give the interface a chance to initialize
449 	 * if this is its first address,
450 	 * and to validate the address if necessary.
451 	 */
452 	if ((error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
453 		ia->ia_addr = oldaddr;
454 	}
455 
456 	/*
457 	 * Add the address to the local list and the global tree.  If an
458 	 * error occured, put back the original address.
459 	 */
460 	ifa_add(ifp, &ia->ia_ifa);
461 	rterror = rt_ifa_addlocal(&ia->ia_ifa);
462 
463 	if (rterror) {
464 		if (!newaddr)
465 			ifa_del(ifp, &ia->ia_ifa);
466 		if (!error)
467 			error = rterror;
468 		goto out;
469 	}
470 	if (error)
471 		goto out;
472 
473 
474 	ia->ia_net = i & ia->ia_netmask;
475 	in_socktrim(&ia->ia_sockmask);
476 	/*
477 	 * Add route for the network.
478 	 */
479 	ia->ia_ifa.ifa_metric = ifp->if_metric;
480 	if (ISSET(ifp->if_flags, IFF_BROADCAST)) {
481 		if (IN_RFC3021_SUBNET(ia->ia_netmask))
482 			ia->ia_broadaddr.sin_addr.s_addr = 0;
483 		else {
484 			ia->ia_broadaddr.sin_addr.s_addr =
485 			    ia->ia_net | ~ia->ia_netmask;
486 		}
487 	}
488 
489 	if (ISSET(ifp->if_flags, IFF_POINTOPOINT)) {
490 		/* XXX We should not even call in_ifinit() in this case. */
491 		if (ia->ia_dstaddr.sin_family != AF_INET)
492 			goto out;
493 		error = in_addhost(ia, &ia->ia_dstaddr);
494 	} else if (!ISSET(ifp->if_flags, IFF_LOOPBACK)) {
495 		error = in_insert_prefix(ia);
496 	}
497 
498 	/*
499 	 * If the interface supports multicast, join the "all hosts"
500 	 * multicast group on that interface.
501 	 */
502 	if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
503 		struct in_addr addr;
504 
505 		addr.s_addr = INADDR_ALLHOSTS_GROUP;
506 		ia->ia_allhosts = in_addmulti(&addr, ifp);
507 	}
508 
509 out:
510 	if (error && newaddr)
511 		in_purgeaddr(&ia->ia_ifa);
512 
513 	return (error);
514 }
515 
516 void
517 in_purgeaddr(struct ifaddr *ifa)
518 {
519 	struct ifnet *ifp = ifa->ifa_ifp;
520 	struct in_ifaddr *ia = ifatoia(ifa);
521 	extern int ifatrash;
522 
523 	NET_ASSERT_LOCKED();
524 
525 	in_ifscrub(ifp, ia);
526 
527 	rt_ifa_dellocal(&ia->ia_ifa);
528 	rt_ifa_purge(&ia->ia_ifa);
529 	ifa_del(ifp, &ia->ia_ifa);
530 
531 	if (ia->ia_allhosts != NULL) {
532 		in_delmulti(ia->ia_allhosts);
533 		ia->ia_allhosts = NULL;
534 	}
535 
536 	ifatrash++;
537 	ia->ia_ifp = NULL;
538 	ifafree(&ia->ia_ifa);
539 }
540 
541 int
542 in_addhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
543 {
544 	return rt_ifa_add(&ia->ia_ifa, RTF_HOST, sintosa(dst));
545 }
546 
547 int
548 in_scrubhost(struct in_ifaddr *ia, struct sockaddr_in *dst)
549 {
550 	return rt_ifa_del(&ia->ia_ifa, RTF_HOST, sintosa(dst));
551 }
552 
553 /*
554  * Insert the cloning and broadcast routes for this subnet.
555  */
556 int
557 in_insert_prefix(struct in_ifaddr *ia)
558 {
559 	struct ifaddr *ifa = &ia->ia_ifa;
560 	int error;
561 
562 	error = rt_ifa_add(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr);
563 	if (error)
564 		return (error);
565 
566 	if (ia->ia_broadaddr.sin_addr.s_addr != 0)
567 		error = rt_ifa_add(ifa, RTF_HOST | RTF_BROADCAST,
568 		    ifa->ifa_broadaddr);
569 
570 	return (error);
571 }
572 
573 void
574 in_remove_prefix(struct in_ifaddr *ia)
575 {
576 	struct ifaddr *ifa = &ia->ia_ifa;
577 
578 	rt_ifa_del(ifa, RTF_CLONING | RTF_CONNECTED, ifa->ifa_addr);
579 
580 	if (ia->ia_broadaddr.sin_addr.s_addr != 0)
581 		rt_ifa_del(ifa, RTF_HOST | RTF_BROADCAST, ifa->ifa_broadaddr);
582 }
583 
584 /*
585  * Return 1 if the address is a local broadcast address.
586  */
587 int
588 in_broadcast(struct in_addr in, u_int rtableid)
589 {
590 	struct ifnet *ifn;
591 	struct ifaddr *ifa;
592 	u_int rdomain;
593 
594 	rdomain = rtable_l2(rtableid);
595 
596 #define ia (ifatoia(ifa))
597 	TAILQ_FOREACH(ifn, &ifnet, if_list) {
598 		if (ifn->if_rdomain != rdomain)
599 			continue;
600 		if ((ifn->if_flags & IFF_BROADCAST) == 0)
601 			continue;
602 		TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
603 			if (ifa->ifa_addr->sa_family == AF_INET &&
604 			    in.s_addr != ia->ia_addr.sin_addr.s_addr &&
605 			    in.s_addr == ia->ia_broadaddr.sin_addr.s_addr)
606 				return 1;
607 	}
608 	return (0);
609 #undef ia
610 }
611 
612 /*
613  * Add an address to the list of IP multicast addresses for a given interface.
614  */
615 struct in_multi *
616 in_addmulti(struct in_addr *ap, struct ifnet *ifp)
617 {
618 	struct in_multi *inm;
619 	struct ifreq ifr;
620 
621 	/*
622 	 * See if address already in list.
623 	 */
624 	IN_LOOKUP_MULTI(*ap, ifp, inm);
625 	if (inm != NULL) {
626 		/*
627 		 * Found it; just increment the reference count.
628 		 */
629 		++inm->inm_refcnt;
630 	} else {
631 		/*
632 		 * New address; allocate a new multicast record
633 		 * and link it into the interface's multicast list.
634 		 */
635 		inm = malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZERO);
636 		if (inm == NULL)
637 			return (NULL);
638 
639 		inm->inm_sin.sin_len = sizeof(struct sockaddr_in);
640 		inm->inm_sin.sin_family = AF_INET;
641 		inm->inm_sin.sin_addr = *ap;
642 		inm->inm_refcnt = 1;
643 		inm->inm_ifidx = ifp->if_index;
644 		inm->inm_ifma.ifma_addr = sintosa(&inm->inm_sin);
645 
646 		/*
647 		 * Ask the network driver to update its multicast reception
648 		 * filter appropriately for the new address.
649 		 */
650 		memset(&ifr, 0, sizeof(ifr));
651 		memcpy(&ifr.ifr_addr, &inm->inm_sin, sizeof(inm->inm_sin));
652 		if ((*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
653 			free(inm, M_IPMADDR, sizeof(*inm));
654 			return (NULL);
655 		}
656 
657 		TAILQ_INSERT_HEAD(&ifp->if_maddrlist, &inm->inm_ifma,
658 		    ifma_list);
659 
660 		/*
661 		 * Let IGMP know that we have joined a new IP multicast group.
662 		 */
663 		igmp_joingroup(inm);
664 	}
665 
666 	return (inm);
667 }
668 
669 /*
670  * Delete a multicast address record.
671  */
672 void
673 in_delmulti(struct in_multi *inm)
674 {
675 	struct ifreq ifr;
676 	struct ifnet *ifp;
677 
678 	NET_ASSERT_LOCKED();
679 
680 	if (--inm->inm_refcnt == 0) {
681 		/*
682 		 * No remaining claims to this record; let IGMP know that
683 		 * we are leaving the multicast group.
684 		 */
685 		igmp_leavegroup(inm);
686 		ifp = if_get(inm->inm_ifidx);
687 
688 		/*
689 		 * Notify the network driver to update its multicast
690 		 * reception filter.
691 		 */
692 		if (ifp != NULL) {
693 			memset(&ifr, 0, sizeof(ifr));
694 			satosin(&ifr.ifr_addr)->sin_len =
695 			    sizeof(struct sockaddr_in);
696 			satosin(&ifr.ifr_addr)->sin_family = AF_INET;
697 			satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
698 			(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
699 
700 			TAILQ_REMOVE(&ifp->if_maddrlist, &inm->inm_ifma,
701 			    ifma_list);
702 		}
703 		if_put(ifp);
704 
705 		free(inm, M_IPMADDR, sizeof(*inm));
706 	}
707 }
708 
709 /*
710  * Return 1 if the multicast group represented by ``ap'' has been
711  * joined by interface ``ifp'', 0 otherwise.
712  */
713 int
714 in_hasmulti(struct in_addr *ap, struct ifnet *ifp)
715 {
716 	struct in_multi *inm;
717 	int joined;
718 
719 	IN_LOOKUP_MULTI(*ap, ifp, inm);
720 	joined = (inm != NULL);
721 
722 	return (joined);
723 }
724 
725 void
726 in_ifdetach(struct ifnet *ifp)
727 {
728 	struct ifaddr *ifa, *next;
729 
730 	/* nuke any of IPv4 addresses we have */
731 	TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, next) {
732 		if (ifa->ifa_addr->sa_family != AF_INET)
733 			continue;
734 		in_purgeaddr(ifa);
735 		dohooks(ifp->if_addrhooks, 0);
736 	}
737 }
738 
739 void
740 in_prefixlen2mask(struct in_addr *maskp, int plen)
741 {
742 	if (plen == 0)
743 		maskp->s_addr = 0;
744 	else
745 		maskp->s_addr = htonl(0xffffffff << (32 - plen));
746 }
747