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