xref: /original-bsd/sys/netinet/in.c (revision ee0c2e02)
1 /*
2  * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)in.c	7.28 (Berkeley) 02/04/93
8  */
9 
10 #include <sys/param.h>
11 #include <sys/ioctl.h>
12 #include <sys/errno.h>
13 #include <sys/malloc.h>
14 #include <sys/socket.h>
15 #include <sys/socketvar.h>
16 
17 #include <net/if.h>
18 #include <net/route.h>
19 #include <net/af.h>
20 
21 #include <netinet/in_systm.h>
22 #include <netinet/in.h>
23 #include <netinet/in_var.h>
24 
25 #ifdef INET
26 /*
27  * Formulate an Internet address from network + host.
28  */
29 struct in_addr
30 in_makeaddr(net, host)
31 	u_long net, host;
32 {
33 	register struct in_ifaddr *ia;
34 	register u_long mask;
35 	u_long addr;
36 
37 	if (IN_CLASSA(net))
38 		mask = IN_CLASSA_HOST;
39 	else if (IN_CLASSB(net))
40 		mask = IN_CLASSB_HOST;
41 	else
42 		mask = IN_CLASSC_HOST;
43 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
44 		if ((ia->ia_netmask & net) == ia->ia_net) {
45 			mask = ~ia->ia_subnetmask;
46 			break;
47 		}
48 	addr = htonl(net | (host & mask));
49 	return (*(struct in_addr *)&addr);
50 }
51 
52 /*
53  * Return the network number from an internet address.
54  */
55 u_long
56 in_netof(in)
57 	struct in_addr in;
58 {
59 	register u_long i = ntohl(in.s_addr);
60 	register u_long net;
61 	register struct in_ifaddr *ia;
62 
63 	if (IN_CLASSA(i))
64 		net = i & IN_CLASSA_NET;
65 	else if (IN_CLASSB(i))
66 		net = i & IN_CLASSB_NET;
67 	else if (IN_CLASSC(i))
68 		net = i & IN_CLASSC_NET;
69 	else if (IN_CLASSD(i))
70 		net = i & IN_CLASSD_NET;
71 	else
72 		return (0);
73 
74 	/*
75 	 * Check whether network is a subnet;
76 	 * if so, return subnet number.
77 	 */
78 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
79 		if (net == ia->ia_net)
80 			return (i & ia->ia_subnetmask);
81 	return (net);
82 }
83 
84 /*
85  * Compute and save network mask as sockaddr from an internet address.
86  */
87 in_sockmaskof(in, sockmask)
88 	struct in_addr in;
89 	register struct sockaddr_in *sockmask;
90 {
91 	register u_long net;
92 	register u_long mask;
93     {
94 	register u_long i = ntohl(in.s_addr);
95 
96 	if (i == 0)
97 		net = 0, mask = 0;
98 	else if (IN_CLASSA(i))
99 		net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
100 	else if (IN_CLASSB(i))
101 		net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
102 	else if (IN_CLASSC(i))
103 		net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
104 	else
105 		net = i, mask = -1;
106     }
107     {
108 	register struct in_ifaddr *ia;
109 	/*
110 	 * Check whether network is a subnet;
111 	 * if so, return subnet number.
112 	 */
113 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
114 		if (net == ia->ia_net)
115 			mask =  ia->ia_subnetmask;
116     }
117     {
118 	register char *cpbase = (char *)&(sockmask->sin_addr);
119 	register char *cp = (char *)(1 + &(sockmask->sin_addr));
120 
121 	sockmask->sin_addr.s_addr = htonl(mask);
122 	sockmask->sin_len = 0;
123 	while (--cp >= cpbase)
124 		if (*cp) {
125 			sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
126 			break;
127 		}
128     }
129 }
130 
131 /*
132  * Return the host portion of an internet address.
133  */
134 u_long
135 in_lnaof(in)
136 	struct in_addr in;
137 {
138 	register u_long i = ntohl(in.s_addr);
139 	register u_long net, host;
140 	register struct in_ifaddr *ia;
141 
142 	if (IN_CLASSA(i)) {
143 		net = i & IN_CLASSA_NET;
144 		host = i & IN_CLASSA_HOST;
145 	} else if (IN_CLASSB(i)) {
146 		net = i & IN_CLASSB_NET;
147 		host = i & IN_CLASSB_HOST;
148 	} else if (IN_CLASSC(i)) {
149 		net = i & IN_CLASSC_NET;
150 		host = i & IN_CLASSC_HOST;
151 	} else if (IN_CLASSD(i)) {
152 		net = i & IN_CLASSD_NET;
153 		host = i & IN_CLASSD_HOST;
154 	} else
155 		return (i);
156 
157 	/*
158 	 * Check whether network is a subnet;
159 	 * if so, use the modified interpretation of `host'.
160 	 */
161 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
162 		if (net == ia->ia_net)
163 			return (host &~ ia->ia_subnetmask);
164 	return (host);
165 }
166 
167 #ifndef SUBNETSARELOCAL
168 #define	SUBNETSARELOCAL	1
169 #endif
170 int subnetsarelocal = SUBNETSARELOCAL;
171 /*
172  * Return 1 if an internet address is for a ``local'' host
173  * (one to which we have a connection).  If subnetsarelocal
174  * is true, this includes other subnets of the local net.
175  * Otherwise, it includes only the directly-connected (sub)nets.
176  */
177 in_localaddr(in)
178 	struct in_addr in;
179 {
180 	register u_long i = ntohl(in.s_addr);
181 	register struct in_ifaddr *ia;
182 
183 	if (subnetsarelocal) {
184 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
185 			if ((i & ia->ia_netmask) == ia->ia_net)
186 				return (1);
187 	} else {
188 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
189 			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
190 				return (1);
191 	}
192 	return (0);
193 }
194 
195 /*
196  * Determine whether an IP address is in a reserved set of addresses
197  * that may not be forwarded, or whether datagrams to that destination
198  * may be forwarded.
199  */
200 in_canforward(in)
201 	struct in_addr in;
202 {
203 	register u_long i = ntohl(in.s_addr);
204 	register u_long net;
205 
206 	if (IN_EXPERIMENTAL(i))
207 		return (0);
208 	if (IN_CLASSA(i)) {
209 		net = i & IN_CLASSA_NET;
210 		if (net == 0 || net == IN_LOOPBACKNET)
211 			return (0);
212 	}
213 	return (1);
214 }
215 
216 int	in_interfaces;		/* number of external internet interfaces */
217 extern	struct ifnet loif;
218 
219 /*
220  * Generic internet control operations (ioctl's).
221  * Ifp is 0 if not an interface-specific ioctl.
222  */
223 /* ARGSUSED */
224 in_control(so, cmd, data, ifp)
225 	struct socket *so;
226 	int cmd;
227 	caddr_t data;
228 	register struct ifnet *ifp;
229 {
230 	register struct ifreq *ifr = (struct ifreq *)data;
231 	register struct in_ifaddr *ia = 0;
232 	register struct ifaddr *ifa;
233 	struct in_ifaddr *oia;
234 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
235 	struct sockaddr_in oldaddr;
236 	int error, hostIsNew, maskIsNew;
237 	u_long i;
238 
239 	/*
240 	 * Find address for this interface, if it exists.
241 	 */
242 	if (ifp)
243 		for (ia = in_ifaddr; ia; ia = ia->ia_next)
244 			if (ia->ia_ifp == ifp)
245 				break;
246 
247 	switch (cmd) {
248 
249 	case SIOCAIFADDR:
250 	case SIOCDIFADDR:
251 		if (ifra->ifra_addr.sin_family == AF_INET)
252 		    for (oia = ia; ia; ia = ia->ia_next) {
253 			if (ia->ia_ifp == ifp  &&
254 			    ia->ia_addr.sin_addr.s_addr ==
255 				ifra->ifra_addr.sin_addr.s_addr)
256 			    break;
257 		}
258 		if (cmd == SIOCDIFADDR && ia == 0)
259 			return (EADDRNOTAVAIL);
260 		/* FALLTHROUGH */
261 	case SIOCSIFADDR:
262 	case SIOCSIFNETMASK:
263 	case SIOCSIFDSTADDR:
264 		if ((so->so_state & SS_PRIV) == 0)
265 			return (EPERM);
266 
267 		if (ifp == 0)
268 			panic("in_control");
269 		if (ia == (struct in_ifaddr *)0) {
270 			oia = (struct in_ifaddr *)
271 				malloc(sizeof *oia, M_IFADDR, M_WAITOK);
272 			if (oia == (struct in_ifaddr *)NULL)
273 				return (ENOBUFS);
274 			bzero((caddr_t)oia, sizeof *oia);
275 			if (ia = in_ifaddr) {
276 				for ( ; ia->ia_next; ia = ia->ia_next)
277 					continue;
278 				ia->ia_next = oia;
279 			} else
280 				in_ifaddr = oia;
281 			ia = oia;
282 			if (ifa = ifp->if_addrlist) {
283 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
284 					continue;
285 				ifa->ifa_next = (struct ifaddr *) ia;
286 			} else
287 				ifp->if_addrlist = (struct ifaddr *) ia;
288 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
289 			ia->ia_ifa.ifa_dstaddr
290 					= (struct sockaddr *)&ia->ia_dstaddr;
291 			ia->ia_ifa.ifa_netmask
292 					= (struct sockaddr *)&ia->ia_sockmask;
293 			ia->ia_sockmask.sin_len = 8;
294 			if (ifp->if_flags & IFF_BROADCAST) {
295 				ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
296 				ia->ia_broadaddr.sin_family = AF_INET;
297 			}
298 			ia->ia_ifp = ifp;
299 			if (ifp != &loif)
300 				in_interfaces++;
301 		}
302 		break;
303 
304 	case SIOCSIFBRDADDR:
305 		if ((so->so_state & SS_PRIV) == 0)
306 			return (EPERM);
307 		/* FALLTHROUGH */
308 
309 	case SIOCGIFADDR:
310 	case SIOCGIFNETMASK:
311 	case SIOCGIFDSTADDR:
312 	case SIOCGIFBRDADDR:
313 		if (ia == (struct in_ifaddr *)0)
314 			return (EADDRNOTAVAIL);
315 		break;
316 	}
317 	switch (cmd) {
318 
319 	case SIOCGIFADDR:
320 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
321 		break;
322 
323 	case SIOCGIFBRDADDR:
324 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
325 			return (EINVAL);
326 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
327 		break;
328 
329 	case SIOCGIFDSTADDR:
330 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
331 			return (EINVAL);
332 		*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
333 		break;
334 
335 	case SIOCGIFNETMASK:
336 		*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
337 		break;
338 
339 	case SIOCSIFDSTADDR:
340 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
341 			return (EINVAL);
342 		oldaddr = ia->ia_dstaddr;
343 		ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
344 		if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
345 					(ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
346 			ia->ia_dstaddr = oldaddr;
347 			return (error);
348 		}
349 		if (ia->ia_flags & IFA_ROUTE) {
350 			ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
351 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
352 			ia->ia_ifa.ifa_dstaddr =
353 					(struct sockaddr *)&ia->ia_dstaddr;
354 			rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
355 		}
356 		break;
357 
358 	case SIOCSIFBRDADDR:
359 		if ((ifp->if_flags & IFF_BROADCAST) == 0)
360 			return (EINVAL);
361 		ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
362 		break;
363 
364 	case SIOCSIFADDR:
365 		return (in_ifinit(ifp, ia,
366 		    (struct sockaddr_in *) &ifr->ifr_addr, 1));
367 
368 	case SIOCSIFNETMASK:
369 		i = ifra->ifra_addr.sin_addr.s_addr;
370 		ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
371 		break;
372 
373 	case SIOCAIFADDR:
374 		maskIsNew = 0;
375 		hostIsNew = 1;
376 		error = 0;
377 		if (ia->ia_addr.sin_family == AF_INET) {
378 			if (ifra->ifra_addr.sin_len == 0) {
379 				ifra->ifra_addr = ia->ia_addr;
380 				hostIsNew = 0;
381 			} else if (ifra->ifra_addr.sin_addr.s_addr ==
382 					       ia->ia_addr.sin_addr.s_addr)
383 				hostIsNew = 0;
384 		}
385 		if (ifra->ifra_mask.sin_len) {
386 			in_ifscrub(ifp, ia);
387 			ia->ia_sockmask = ifra->ifra_mask;
388 			ia->ia_subnetmask =
389 			     ntohl(ia->ia_sockmask.sin_addr.s_addr);
390 			maskIsNew = 1;
391 		}
392 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
393 		    (ifra->ifra_dstaddr.sin_family == AF_INET)) {
394 			in_ifscrub(ifp, ia);
395 			ia->ia_dstaddr = ifra->ifra_dstaddr;
396 			maskIsNew  = 1; /* We lie; but the effect's the same */
397 		}
398 		if (ifra->ifra_addr.sin_family == AF_INET &&
399 		    (hostIsNew || maskIsNew))
400 			error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
401 		if ((ifp->if_flags & IFF_BROADCAST) &&
402 		    (ifra->ifra_broadaddr.sin_family == AF_INET))
403 			ia->ia_broadaddr = ifra->ifra_broadaddr;
404 		return (error);
405 
406 	case SIOCDIFADDR:
407 		in_ifscrub(ifp, ia);
408 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
409 			ifp->if_addrlist = ifa->ifa_next;
410 		else {
411 			while (ifa->ifa_next &&
412 			       (ifa->ifa_next != (struct ifaddr *)ia))
413 				    ifa = ifa->ifa_next;
414 			if (ifa->ifa_next)
415 				ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
416 			else
417 				printf("Couldn't unlink inifaddr from ifp\n");
418 		}
419 		oia = ia;
420 		if (oia == (ia = in_ifaddr))
421 			in_ifaddr = ia->ia_next;
422 		else {
423 			while (ia->ia_next && (ia->ia_next != oia))
424 				ia = ia->ia_next;
425 			if (ia->ia_next)
426 				ia->ia_next = oia->ia_next;
427 			else
428 				printf("Didn't unlink inifadr from list\n");
429 		}
430 		IFAFREE((&oia->ia_ifa));
431 		break;
432 
433 	default:
434 		if (ifp == 0 || ifp->if_ioctl == 0)
435 			return (EOPNOTSUPP);
436 		return ((*ifp->if_ioctl)(ifp, cmd, data));
437 	}
438 	return (0);
439 }
440 
441 /*
442  * Delete any existing route for an interface.
443  */
444 in_ifscrub(ifp, ia)
445 	register struct ifnet *ifp;
446 	register struct in_ifaddr *ia;
447 {
448 
449 	if ((ia->ia_flags & IFA_ROUTE) == 0)
450 		return;
451 	if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
452 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
453 	else
454 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
455 	ia->ia_flags &= ~IFA_ROUTE;
456 }
457 
458 /*
459  * Initialize an interface's internet address
460  * and routing table entry.
461  */
462 in_ifinit(ifp, ia, sin, scrub)
463 	register struct ifnet *ifp;
464 	register struct in_ifaddr *ia;
465 	struct sockaddr_in *sin;
466 	int scrub;
467 {
468 	register u_long i = ntohl(sin->sin_addr.s_addr);
469 	struct sockaddr_in oldaddr;
470 	int s = splimp(), flags = RTF_UP, error, ether_output();
471 	void arp_rtrequest();
472 
473 	oldaddr = ia->ia_addr;
474 	ia->ia_addr = *sin;
475 	/*
476 	 * Give the interface a chance to initialize
477 	 * if this is its first address,
478 	 * and to validate the address if necessary.
479 	 */
480 	if (ifp->if_ioctl &&
481 	    (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
482 		splx(s);
483 		ia->ia_addr = oldaddr;
484 		return (error);
485 	}
486 	if (ifp->if_output == ether_output) { /* XXX: Another Kludge */
487 		ia->ia_ifa.ifa_rtrequest = arp_rtrequest;
488 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
489 	}
490 	splx(s);
491 	if (scrub) {
492 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
493 		in_ifscrub(ifp, ia);
494 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
495 	}
496 	if (IN_CLASSA(i))
497 		ia->ia_netmask = IN_CLASSA_NET;
498 	else if (IN_CLASSB(i))
499 		ia->ia_netmask = IN_CLASSB_NET;
500 	else
501 		ia->ia_netmask = IN_CLASSC_NET;
502 	ia->ia_net = i & ia->ia_netmask;
503 	/*
504 	 * The subnet mask includes at least the standard network part,
505 	 * but may already have been set to a larger value.
506 	 */
507 	ia->ia_subnetmask |= ia->ia_netmask;
508 	ia->ia_subnet = i & ia->ia_subnetmask;
509 	ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
510 	{
511 		register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr));
512 		register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr);
513 		while (--cp >= cpbase)
514 			if (*cp) {
515 				ia->ia_sockmask.sin_len =
516 					1 + cp - (char *) &(ia->ia_sockmask);
517 				break;
518 			}
519 	}
520 	/*
521 	 * Add route for the network.
522 	 */
523 	ia->ia_ifa.ifa_metric = ifp->if_metric;
524 	if (ifp->if_flags & IFF_BROADCAST) {
525 		ia->ia_broadaddr.sin_addr =
526 			in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
527 		ia->ia_netbroadcast.s_addr =
528 		    htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
529 	} else if (ifp->if_flags & IFF_LOOPBACK) {
530 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
531 		flags |= RTF_HOST;
532 	} else if (ifp->if_flags & IFF_POINTOPOINT) {
533 		if (ia->ia_dstaddr.sin_family != AF_INET)
534 			return (0);
535 		flags |= RTF_HOST;
536 	}
537 	if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
538 		ia->ia_flags |= IFA_ROUTE;
539 	/*
540 	 * If the interface supports multicast, join the "all hosts"
541 	 * multicast group on that interface.
542 	 */
543 	if (ifp->if_flags & IFF_MULTICAST) {
544 		struct in_addr addr;
545 
546 		addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
547 		in_addmulti(&addr, ifp);
548 	}
549 	return (error);
550 }
551 
552 /*
553  * Return address info for specified internet network.
554  */
555 struct in_ifaddr *
556 in_iaonnetof(net)
557 	u_long net;
558 {
559 	register struct in_ifaddr *ia;
560 
561 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
562 		if (ia->ia_subnet == net)
563 			return (ia);
564 	return ((struct in_ifaddr *)0);
565 }
566 
567 /*
568  * Return 1 if the address might be a local broadcast address.
569  */
570 in_broadcast(in)
571 	struct in_addr in;
572 {
573 	register struct in_ifaddr *ia;
574 	u_long t;
575 
576 	/*
577 	 * Look through the list of addresses for a match
578 	 * with a broadcast address.
579 	 */
580 	for (ia = in_ifaddr; ia; ia = ia->ia_next)
581 	    if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
582 		if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
583 		     return (1);
584 		/*
585 		 * Check for old-style (host 0) broadcast.
586 		 */
587 		if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
588 		    return (1);
589 	}
590 	if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
591 		return (1);
592 	return (0);
593 }
594 
595 /*
596  * Add an address to the list of IP multicast addresses for a given interface.
597  */
598 struct in_multi *
599 in_addmulti(ap, ifp)
600 	register struct in_addr *ap;
601 	register struct ifnet *ifp;
602 {
603 	register struct in_multi *inm;
604 	struct ifreq ifr;
605 	struct in_ifaddr *ia;
606 	int s = splnet();
607 	int error;
608 
609 	/*
610 	 * See if address already in list.
611 	 */
612 	IN_LOOKUP_MULTI(*ap, ifp, inm);
613 	if (inm != NULL) {
614 		/*
615 		 * Found it; just increment the reference count.
616 		 */
617 		++inm->inm_refcount;
618 	}
619 	else {
620 		/*
621 		 * New address; allocate a new multicast record
622 		 * and link it into the interface's multicast list.
623 		 */
624 		inm = (struct in_multi *)malloc(sizeof(*inm),
625 		    M_IPMADDR, M_NOWAIT);
626 		if (inm == NULL) {
627 			splx(s);
628 			return (NULL);
629 		}
630 		inm->inm_addr = *ap;
631 		inm->inm_ifp = ifp;
632 		inm->inm_refcount = 1;
633 		IFP_TO_IA(ifp, ia);
634 		if (ia == NULL) {
635 			free(inm, M_IPMADDR);
636 			splx(s);
637 			return (NULL);
638 		}
639 		inm->inm_ia = ia;
640 		/*
641 		 * Ask the network driver to update its multicast reception
642 		 * filter appropriately for the new address.
643 		 */
644 		((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
645 		((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
646 		if (ifp->if_ioctl == NULL) {
647 			free(inm, M_IPMADDR);
648 			splx(s);
649 			return (NULL);
650 		}
651 		error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr);
652 		if (error != 0) {
653 			free(inm, M_IPMADDR);
654 			splx(s);
655 			return (NULL);
656 		}
657 		inm->inm_next = ia->ia_multiaddrs;
658 		ia->ia_multiaddrs = inm;
659 		/*
660 		 * Let IGMP know that we have joined a new IP multicast group.
661 		 */
662 		igmp_joingroup(inm);
663 	}
664 	splx(s);
665 	return (inm);
666 }
667 
668 /*
669  * Delete a multicast address record.
670  */
671 int
672 in_delmulti(inm)
673 	register struct in_multi *inm;
674 {
675 	register struct in_multi **p;
676 	struct ifreq ifr;
677 	int s = splnet();
678 
679 	if (--inm->inm_refcount == 0) {
680 		/*
681 		 * No remaining claims to this record; let IGMP know that
682 		 * we are leaving the multicast group.
683 		 */
684 		igmp_leavegroup(inm);
685 		/*
686 		 * Unlink from list.
687 		 */
688 		for (p = &inm->inm_ia->ia_multiaddrs;
689 		     *p != inm;
690 		     p = &(*p)->inm_next)
691 			 continue;
692 		*p = (*p)->inm_next;
693 		/*
694 		 * Notify the network driver to update its multicast reception
695 		 * filter.
696 		 */
697 		((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
698 		((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
699 								inm->inm_addr;
700 		(*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
701 							     (caddr_t)&ifr);
702 		free(inm, M_IPMADDR);
703 	}
704 	splx(s);
705 }
706 #endif
707