in.c revision 1.41 1 /* $NetBSD: in.c,v 1.41 1998/07/05 00:51:28 jonathan Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Public Access Networks Corporation ("Panix"). It was developed under
9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1982, 1986, 1991, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by the University of
55 * California, Berkeley and its contributors.
56 * 4. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission.
59 *
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 * SUCH DAMAGE.
71 *
72 * @(#)in.c 8.4 (Berkeley) 1/9/95
73 */
74
75 #include "opt_inet.h"
76 #include "opt_mrouting.h"
77
78 #include <sys/param.h>
79 #include <sys/ioctl.h>
80 #include <sys/errno.h>
81 #include <sys/malloc.h>
82 #include <sys/socket.h>
83 #include <sys/socketvar.h>
84 #include <sys/systm.h>
85 #include <sys/proc.h>
86
87 #include <net/if.h>
88 #include <net/route.h>
89
90 #include <net/if_ether.h>
91
92 #include <netinet/in_systm.h>
93 #include <netinet/in.h>
94 #include <netinet/in_var.h>
95 #include <netinet/if_inarp.h>
96 #include <netinet/ip_mroute.h>
97 #include <netinet/igmp_var.h>
98
99 #include "ether.h"
100
101 #ifdef INET
102
103 #ifndef SUBNETSARELOCAL
104 #define SUBNETSARELOCAL 1
105 #endif
106 int subnetsarelocal = SUBNETSARELOCAL;
107
108 /*
109 * Return 1 if an internet address is for a ``local'' host
110 * (one to which we have a connection). If subnetsarelocal
111 * is true, this includes other subnets of the local net.
112 * Otherwise, it includes only the directly-connected (sub)nets.
113 */
114 int
115 in_localaddr(in)
116 struct in_addr in;
117 {
118 register struct in_ifaddr *ia;
119
120 if (subnetsarelocal) {
121 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
122 if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
123 return (1);
124 } else {
125 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
126 if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
127 return (1);
128 }
129 return (0);
130 }
131
132 /*
133 * Determine whether an IP address is in a reserved set of addresses
134 * that may not be forwarded, or whether datagrams to that destination
135 * may be forwarded.
136 */
137 int
138 in_canforward(in)
139 struct in_addr in;
140 {
141 register u_int32_t net;
142
143 if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
144 return (0);
145 if (IN_CLASSA(in.s_addr)) {
146 net = in.s_addr & IN_CLASSA_NET;
147 if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
148 return (0);
149 }
150 return (1);
151 }
152
153 /*
154 * Trim a mask in a sockaddr
155 */
156 void
157 in_socktrim(ap)
158 struct sockaddr_in *ap;
159 {
160 register char *cplim = (char *) &ap->sin_addr;
161 register char *cp = (char *) (&ap->sin_addr + 1);
162
163 ap->sin_len = 0;
164 while (--cp >= cplim)
165 if (*cp) {
166 (ap)->sin_len = cp - (char *) (ap) + 1;
167 break;
168 }
169 }
170
171 /*
172 * Routine to take an Internet address and convert into a
173 * "dotted quad" representation for printing.
174 */
175 const char *
176 in_fmtaddr(addr)
177 struct in_addr addr;
178 {
179 static char buf[sizeof("123.456.789.123")];
180
181 addr.s_addr = ntohl(addr.s_addr);
182
183 sprintf(buf, "%d.%d.%d.%d",
184 (addr.s_addr >> 24) & 0xFF,
185 (addr.s_addr >> 16) & 0xFF,
186 (addr.s_addr >> 8) & 0xFF,
187 (addr.s_addr >> 0) & 0xFF);
188 return buf;
189 }
190
191 /*
192 * Maintain the "in_maxmtu" variable, which is the largest
193 * mtu for non-local interfaces with AF_INET addresses assigned
194 * to them that are up.
195 */
196 unsigned long in_maxmtu;
197
198 void
199 in_setmaxmtu()
200 {
201 register struct in_ifaddr *ia;
202 register struct ifnet *ifp;
203 unsigned long maxmtu = 0;
204
205 for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) {
206 if ((ifp = ia->ia_ifp) == 0)
207 continue;
208 if ((ifp->if_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
209 continue;
210 if (ifp->if_mtu > maxmtu)
211 maxmtu = ifp->if_mtu;
212 }
213 if (maxmtu)
214 in_maxmtu = maxmtu;
215 }
216
217 int in_interfaces; /* number of external internet interfaces */
218
219 /*
220 * Generic internet control operations (ioctl's).
221 * Ifp is 0 if not an interface-specific ioctl.
222 */
223 /* ARGSUSED */
224 int
225 in_control(so, cmd, data, ifp, p)
226 struct socket *so;
227 u_long cmd;
228 caddr_t data;
229 register struct ifnet *ifp;
230 struct proc *p;
231 {
232 register struct ifreq *ifr = (struct ifreq *)data;
233 register struct in_ifaddr *ia = 0;
234 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
235 struct sockaddr_in oldaddr;
236 int error, hostIsNew, maskIsNew;
237
238 /*
239 * Find address for this interface, if it exists.
240 */
241 if (ifp)
242 IFP_TO_IA(ifp, ia);
243
244 switch (cmd) {
245
246 case SIOCAIFADDR:
247 case SIOCDIFADDR:
248 if (ifra->ifra_addr.sin_family == AF_INET)
249 for (ia = IN_IFADDR_HASH(ifra->ifra_addr.sin_addr.s_addr).lh_first;
250 ia != 0; ia = ia->ia_hash.le_next) {
251 if (ia->ia_ifp == ifp &&
252 in_hosteq(ia->ia_addr.sin_addr,
253 ifra->ifra_addr.sin_addr))
254 break;
255 }
256 if (cmd == SIOCDIFADDR && ia == 0)
257 return (EADDRNOTAVAIL);
258 /* FALLTHROUGH */
259 case SIOCSIFADDR:
260 case SIOCSIFNETMASK:
261 case SIOCSIFDSTADDR:
262 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
263 return (EPERM);
264
265 if (ifp == 0)
266 panic("in_control");
267 if (ia == 0) {
268 MALLOC(ia, struct in_ifaddr *, sizeof(*ia),
269 M_IFADDR, M_WAITOK);
270 if (ia == 0)
271 return (ENOBUFS);
272 bzero((caddr_t)ia, sizeof *ia);
273 TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
274 TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
275 ifa_list);
276 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
277 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
278 ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
279 ia->ia_sockmask.sin_len = 8;
280 if (ifp->if_flags & IFF_BROADCAST) {
281 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
282 ia->ia_broadaddr.sin_family = AF_INET;
283 }
284 ia->ia_ifp = ifp;
285 LIST_INIT(&ia->ia_multiaddrs);
286 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
287 in_interfaces++;
288 }
289 break;
290
291 case SIOCSIFBRDADDR:
292 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
293 return (EPERM);
294 /* FALLTHROUGH */
295
296 case SIOCGIFADDR:
297 case SIOCGIFNETMASK:
298 case SIOCGIFDSTADDR:
299 case SIOCGIFBRDADDR:
300 if (ia == 0)
301 return (EADDRNOTAVAIL);
302 break;
303 }
304 switch (cmd) {
305
306 case SIOCGIFADDR:
307 *satosin(&ifr->ifr_addr) = ia->ia_addr;
308 break;
309
310 case SIOCGIFBRDADDR:
311 if ((ifp->if_flags & IFF_BROADCAST) == 0)
312 return (EINVAL);
313 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
314 break;
315
316 case SIOCGIFDSTADDR:
317 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
318 return (EINVAL);
319 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
320 break;
321
322 case SIOCGIFNETMASK:
323 *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
324 break;
325
326 case SIOCSIFDSTADDR:
327 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
328 return (EINVAL);
329 oldaddr = ia->ia_dstaddr;
330 ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
331 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
332 (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
333 ia->ia_dstaddr = oldaddr;
334 return (error);
335 }
336 if (ia->ia_flags & IFA_ROUTE) {
337 ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
338 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
339 ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
340 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
341 }
342 break;
343
344 case SIOCSIFBRDADDR:
345 if ((ifp->if_flags & IFF_BROADCAST) == 0)
346 return (EINVAL);
347 ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
348 break;
349
350 case SIOCSIFADDR:
351 return (in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1));
352
353 case SIOCSIFNETMASK:
354 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
355 ifra->ifra_addr.sin_addr.s_addr;
356 break;
357
358 case SIOCAIFADDR:
359 maskIsNew = 0;
360 hostIsNew = 1;
361 error = 0;
362 if (ia->ia_addr.sin_family == AF_INET) {
363 if (ifra->ifra_addr.sin_len == 0) {
364 ifra->ifra_addr = ia->ia_addr;
365 hostIsNew = 0;
366 } else if (in_hosteq(ia->ia_addr.sin_addr, ifra->ifra_addr.sin_addr))
367 hostIsNew = 0;
368 }
369 if (ifra->ifra_mask.sin_len) {
370 in_ifscrub(ifp, ia);
371 ia->ia_sockmask = ifra->ifra_mask;
372 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
373 maskIsNew = 1;
374 }
375 if ((ifp->if_flags & IFF_POINTOPOINT) &&
376 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
377 in_ifscrub(ifp, ia);
378 ia->ia_dstaddr = ifra->ifra_dstaddr;
379 maskIsNew = 1; /* We lie; but the effect's the same */
380 }
381 if (ifra->ifra_addr.sin_family == AF_INET &&
382 (hostIsNew || maskIsNew))
383 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
384 if ((ifp->if_flags & IFF_BROADCAST) &&
385 (ifra->ifra_broadaddr.sin_family == AF_INET))
386 ia->ia_broadaddr = ifra->ifra_broadaddr;
387 return (error);
388
389 case SIOCDIFADDR:
390 in_ifscrub(ifp, ia);
391 LIST_REMOVE(ia, ia_hash);
392 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
393 TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
394 IFAFREE((&ia->ia_ifa));
395 in_setmaxmtu();
396 break;
397
398 #ifdef MROUTING
399 case SIOCGETVIFCNT:
400 case SIOCGETSGCNT:
401 return (mrt_ioctl(so, cmd, data));
402 #endif /* MROUTING */
403
404 default:
405 if (ifp == 0 || ifp->if_ioctl == 0)
406 return (EOPNOTSUPP);
407 error = (*ifp->if_ioctl)(ifp, cmd, data);
408 in_setmaxmtu();
409 return(error);
410 }
411 return (0);
412 }
413
414 /*
415 * Delete any existing route for an interface.
416 */
417 void
418 in_ifscrub(ifp, ia)
419 register struct ifnet *ifp;
420 register struct in_ifaddr *ia;
421 {
422
423 if ((ia->ia_flags & IFA_ROUTE) == 0)
424 return;
425 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
426 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
427 else
428 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
429 ia->ia_flags &= ~IFA_ROUTE;
430 }
431
432 /*
433 * Initialize an interface's internet address
434 * and routing table entry.
435 */
436 int
437 in_ifinit(ifp, ia, sin, scrub)
438 register struct ifnet *ifp;
439 register struct in_ifaddr *ia;
440 struct sockaddr_in *sin;
441 int scrub;
442 {
443 register u_int32_t i = sin->sin_addr.s_addr;
444 struct sockaddr_in oldaddr;
445 int s = splimp(), flags = RTF_UP, error;
446
447 /*
448 * Set up new addresses.
449 */
450 oldaddr = ia->ia_addr;
451 if (ia->ia_addr.sin_family == AF_INET)
452 LIST_REMOVE(ia, ia_hash);
453 ia->ia_addr = *sin;
454 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
455
456 /*
457 * Give the interface a chance to initialize
458 * if this is its first address,
459 * and to validate the address if necessary.
460 */
461 if (ifp->if_ioctl &&
462 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia)))
463 goto bad;
464 splx(s);
465 if (scrub) {
466 ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
467 in_ifscrub(ifp, ia);
468 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
469 }
470
471 if (IN_CLASSA(i))
472 ia->ia_netmask = IN_CLASSA_NET;
473 else if (IN_CLASSB(i))
474 ia->ia_netmask = IN_CLASSB_NET;
475 else
476 ia->ia_netmask = IN_CLASSC_NET;
477 /*
478 * The subnet mask usually includes at least the standard network part,
479 * but may may be smaller in the case of supernetting.
480 * If it is set, we believe it.
481 */
482 if (ia->ia_subnetmask == 0) {
483 ia->ia_subnetmask = ia->ia_netmask;
484 ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
485 } else
486 ia->ia_netmask &= ia->ia_subnetmask;
487
488 ia->ia_net = i & ia->ia_netmask;
489 ia->ia_subnet = i & ia->ia_subnetmask;
490 in_socktrim(&ia->ia_sockmask);
491 /* re-calculate the "in_maxmtu" value */
492 in_setmaxmtu();
493 /*
494 * Add route for the network.
495 */
496 ia->ia_ifa.ifa_metric = ifp->if_metric;
497 if (ifp->if_flags & IFF_BROADCAST) {
498 ia->ia_broadaddr.sin_addr.s_addr =
499 ia->ia_subnet | ~ia->ia_subnetmask;
500 ia->ia_netbroadcast.s_addr =
501 ia->ia_net | ~ia->ia_netmask;
502 } else if (ifp->if_flags & IFF_LOOPBACK) {
503 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
504 flags |= RTF_HOST;
505 } else if (ifp->if_flags & IFF_POINTOPOINT) {
506 if (ia->ia_dstaddr.sin_family != AF_INET)
507 return (0);
508 flags |= RTF_HOST;
509 }
510 error = rtinit(&ia->ia_ifa, (int)RTM_ADD, flags);
511 if (!error)
512 ia->ia_flags |= IFA_ROUTE;
513 /*
514 * If the interface supports multicast, join the "all hosts"
515 * multicast group on that interface.
516 */
517 if (ifp->if_flags & IFF_MULTICAST) {
518 struct in_addr addr;
519
520 addr.s_addr = INADDR_ALLHOSTS_GROUP;
521 in_addmulti(&addr, ifp);
522 }
523 return (error);
524 bad:
525 splx(s);
526 LIST_REMOVE(ia, ia_hash);
527 ia->ia_addr = oldaddr;
528 if (ia->ia_addr.sin_family == AF_INET)
529 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
530 ia, ia_hash);
531 return (error);
532 }
533
534 /*
535 * Return 1 if the address might be a local broadcast address.
536 */
537 int
538 in_broadcast(in, ifp)
539 struct in_addr in;
540 struct ifnet *ifp;
541 {
542 register struct ifaddr *ifa;
543
544 if (in.s_addr == INADDR_BROADCAST ||
545 in_nullhost(in))
546 return 1;
547 if ((ifp->if_flags & IFF_BROADCAST) == 0)
548 return 0;
549 /*
550 * Look through the list of addresses for a match
551 * with a broadcast address.
552 */
553 #define ia (ifatoia(ifa))
554 for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
555 if (ifa->ifa_addr->sa_family == AF_INET &&
556 (in_hosteq(in, ia->ia_broadaddr.sin_addr) ||
557 in_hosteq(in, ia->ia_netbroadcast) ||
558 /*
559 * Check for old-style (host 0) broadcast.
560 */
561 in.s_addr == ia->ia_subnet ||
562 in.s_addr == ia->ia_net))
563 return 1;
564 return (0);
565 #undef ia
566 }
567
568 /*
569 * Add an address to the list of IP multicast addresses for a given interface.
570 */
571 struct in_multi *
572 in_addmulti(ap, ifp)
573 register struct in_addr *ap;
574 register struct ifnet *ifp;
575 {
576 register struct in_multi *inm;
577 struct ifreq ifr;
578 struct in_ifaddr *ia;
579 int s = splsoftnet();
580
581 /*
582 * See if address already in list.
583 */
584 IN_LOOKUP_MULTI(*ap, ifp, inm);
585 if (inm != NULL) {
586 /*
587 * Found it; just increment the reference count.
588 */
589 ++inm->inm_refcount;
590 } else {
591 /*
592 * New address; allocate a new multicast record
593 * and link it into the interface's multicast list.
594 */
595 inm = (struct in_multi *)malloc(sizeof(*inm),
596 M_IPMADDR, M_NOWAIT);
597 if (inm == NULL) {
598 splx(s);
599 return (NULL);
600 }
601 inm->inm_addr = *ap;
602 inm->inm_ifp = ifp;
603 inm->inm_refcount = 1;
604 IFP_TO_IA(ifp, ia);
605 if (ia == NULL) {
606 free(inm, M_IPMADDR);
607 splx(s);
608 return (NULL);
609 }
610 inm->inm_ia = ia;
611 LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
612 /*
613 * Ask the network driver to update its multicast reception
614 * filter appropriately for the new address.
615 */
616 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
617 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
618 satosin(&ifr.ifr_addr)->sin_addr = *ap;
619 if ((ifp->if_ioctl == NULL) ||
620 (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
621 LIST_REMOVE(inm, inm_list);
622 free(inm, M_IPMADDR);
623 splx(s);
624 return (NULL);
625 }
626 /*
627 * Let IGMP know that we have joined a new IP multicast group.
628 */
629 igmp_joingroup(inm);
630 }
631 splx(s);
632 return (inm);
633 }
634
635 /*
636 * Delete a multicast address record.
637 */
638 void
639 in_delmulti(inm)
640 register struct in_multi *inm;
641 {
642 struct ifreq ifr;
643 int s = splsoftnet();
644
645 if (--inm->inm_refcount == 0) {
646 /*
647 * No remaining claims to this record; let IGMP know that
648 * we are leaving the multicast group.
649 */
650 igmp_leavegroup(inm);
651 /*
652 * Unlink from list.
653 */
654 LIST_REMOVE(inm, inm_list);
655 /*
656 * Notify the network driver to update its multicast reception
657 * filter.
658 */
659 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
660 satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
661 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
662 (caddr_t)&ifr);
663 free(inm, M_IPMADDR);
664 }
665 splx(s);
666 }
667 #endif
668