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