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