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