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