]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in.c
xnu-1228.12.14.tar.gz
[apple/xnu.git] / bsd / netinet / in.c
1 /*
2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1982, 1986, 1991, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)in.c 8.4 (Berkeley) 1/9/95
61 * $FreeBSD: src/sys/netinet/in.c,v 1.44.2.5 2001/08/13 16:26:17 ume Exp $
62 */
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/sockio.h>
67 #include <sys/socketvar.h>
68 #include <sys/malloc.h>
69 #include <sys/proc.h>
70 #include <sys/socket.h>
71 #include <sys/kernel.h>
72 #include <sys/sysctl.h>
73 #include <sys/kern_event.h>
74 #include <sys/syslog.h>
75
76 #include <pexpert/pexpert.h>
77
78 #include <net/if.h>
79 #include <net/if_types.h>
80 #include <net/route.h>
81 #include <net/kpi_protocol.h>
82
83 #include <netinet/in.h>
84 #include <netinet/in_var.h>
85 #include <netinet/in_pcb.h>
86
87 #include <netinet/igmp_var.h>
88 #include <net/dlil.h>
89
90 #include <netinet/ip_var.h>
91
92 #include <netinet/tcp.h>
93 #include <netinet/tcp_timer.h>
94 #include <netinet/tcp_var.h>
95
96 #include <sys/file.h>
97
98
99 static int in_mask2len(struct in_addr *);
100 static void in_len2mask(struct in_addr *, int);
101 static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
102 struct ifnet *, struct proc *);
103
104 static void in_socktrim(struct sockaddr_in *);
105 static int in_ifinit(struct ifnet *,
106 struct in_ifaddr *, struct sockaddr_in *, int);
107
108 static int subnetsarelocal = 0;
109 SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
110 &subnetsarelocal, 0, "");
111
112 struct in_multihead in_multihead; /* XXX BSS initialization */
113
114 /* Track whether or not the SIOCARPIPLL ioctl has been called */
115 __private_extern__ u_int32_t ipv4_ll_arp_aware = 0;
116
117 int
118 inaddr_local(struct in_addr in)
119 {
120 struct rtentry *rt;
121 struct sockaddr_in sin;
122 int local = 0;
123
124 sin.sin_family = AF_INET;
125 sin.sin_len = sizeof (sin);
126 sin.sin_addr = in;
127 rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
128
129 if (rt != NULL) {
130 if (rt->rt_gateway->sa_family == AF_LINK ||
131 (rt->rt_ifp->if_flags & IFF_LOOPBACK))
132 local = 1;
133 rtfree(rt);
134 } else {
135 local = in_localaddr(in);
136 }
137 return (local);
138 }
139
140 /*
141 * Return 1 if an internet address is for a ``local'' host
142 * (one to which we have a connection). If subnetsarelocal
143 * is true, this includes other subnets of the local net.
144 * Otherwise, it includes only the directly-connected (sub)nets.
145 */
146 int
147 in_localaddr(struct in_addr in)
148 {
149 u_long i = ntohl(in.s_addr);
150 struct in_ifaddr *ia;
151
152 if (subnetsarelocal) {
153 lck_mtx_lock(rt_mtx);
154 for (ia = in_ifaddrhead.tqh_first; ia;
155 ia = ia->ia_link.tqe_next)
156 if ((i & ia->ia_netmask) == ia->ia_net) {
157 lck_mtx_unlock(rt_mtx);
158 return (1);
159 }
160 lck_mtx_unlock(rt_mtx);
161 } else {
162 lck_mtx_lock(rt_mtx);
163 for (ia = in_ifaddrhead.tqh_first; ia;
164 ia = ia->ia_link.tqe_next)
165 if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
166 lck_mtx_unlock(rt_mtx);
167 return (1);
168 }
169 lck_mtx_unlock(rt_mtx);
170 }
171 return (0);
172 }
173
174 /*
175 * Determine whether an IP address is in a reserved set of addresses
176 * that may not be forwarded, or whether datagrams to that destination
177 * may be forwarded.
178 */
179 int
180 in_canforward(struct in_addr in)
181 {
182 u_long i = ntohl(in.s_addr);
183 u_long net;
184
185 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
186 return (0);
187 if (IN_CLASSA(i)) {
188 net = i & IN_CLASSA_NET;
189 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
190 return (0);
191 }
192 return (1);
193 }
194
195 /*
196 * Trim a mask in a sockaddr
197 */
198 static void
199 in_socktrim(struct sockaddr_in *ap)
200 {
201 char *cplim = (char *) &ap->sin_addr;
202 char *cp = (char *) (&ap->sin_addr + 1);
203
204 ap->sin_len = 0;
205 while (--cp >= cplim)
206 if (*cp) {
207 (ap)->sin_len = cp - (char *) (ap) + 1;
208 break;
209 }
210 }
211
212 static int
213 in_mask2len(struct in_addr *mask)
214 {
215 size_t x, y;
216 u_char *p;
217
218 p = (u_char *)mask;
219 for (x = 0; x < sizeof(*mask); x++) {
220 if (p[x] != 0xff)
221 break;
222 }
223 y = 0;
224 if (x < sizeof(*mask)) {
225 for (y = 0; y < 8; y++) {
226 if ((p[x] & (0x80 >> y)) == 0)
227 break;
228 }
229 }
230 return x * 8 + y;
231 }
232
233 static void
234 in_len2mask(struct in_addr *mask, int len)
235 {
236 int i;
237 u_char *p;
238
239 p = (u_char *)mask;
240 bzero(mask, sizeof(*mask));
241 for (i = 0; i < len / 8; i++)
242 p[i] = 0xff;
243 if (len % 8)
244 p[i] = (0xff00 >> (len % 8)) & 0xff;
245 }
246
247 static int in_interfaces; /* number of external internet interfaces */
248
249 /*
250 * Generic internet control operations (ioctl's).
251 * Ifp is 0 if not an interface-specific ioctl.
252 *
253 * Returns: 0 Success
254 * EINVAL
255 * EADDRNOTAVAIL
256 * EDESTADDRREQ
257 * EPERM
258 * ENOBUFS
259 * EBUSY
260 * EOPNOTSUPP
261 * proc_suser:EPERM
262 * suser:EPERM
263 * in_lifaddr_ioctl:???
264 * dlil_ioctl:???
265 * in_ifinit:???
266 * dlil_plumb_protocol:???
267 * dlil_unplumb_protocol:???
268 */
269 /* ARGSUSED */
270 int
271 in_control(
272 struct socket *so,
273 u_long cmd,
274 caddr_t data,
275 struct ifnet *ifp,
276 struct proc *p)
277 {
278 struct ifreq *ifr = (struct ifreq *)data;
279 struct in_ifaddr *ia = NULL, *iap;
280 struct ifaddr *ifa;
281 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
282 struct sockaddr_in oldaddr;
283 int error = 0;
284 int hostIsNew, maskIsNew;
285 struct kev_msg ev_msg;
286 struct kev_in_data in_event_data;
287
288
289 switch (cmd) {
290 case SIOCALIFADDR:
291 case SIOCDLIFADDR:
292 if (p && (error = proc_suser(p)) != 0)
293 return error;
294 /*fall through*/
295 case SIOCGLIFADDR:
296 if (!ifp)
297 return EINVAL;
298 return in_lifaddr_ioctl(so, cmd, data, ifp, p);
299 }
300
301 /*
302 * Find address for this interface, if it exists.
303 *
304 * If an alias address was specified, find that one instead of
305 * the first one on the interface.
306 */
307 if (ifp) {
308 lck_mtx_lock(rt_mtx);
309 for (iap = in_ifaddrhead.tqh_first; iap;
310 iap = iap->ia_link.tqe_next)
311 if (iap->ia_ifp == ifp) {
312 if (((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr ==
313 iap->ia_addr.sin_addr.s_addr) {
314 ia = iap;
315 break;
316 } else if (ia == NULL) {
317 ia = iap;
318 if (ifr->ifr_addr.sa_family != AF_INET)
319 break;
320 }
321 }
322 /* take a reference on ia before releasing mutex */
323 if (ia != NULL) {
324 ifaref(&ia->ia_ifa);
325 }
326 lck_mtx_unlock(rt_mtx);
327 }
328 switch (cmd) {
329 case SIOCAUTOADDR:
330 case SIOCARPIPLL:
331 if (p && (error = proc_suser(p)) != 0) {
332 goto done;
333 }
334 if (ifp == 0) {
335 error = EADDRNOTAVAIL;
336 goto done;
337 }
338 break;
339
340 case SIOCAIFADDR:
341 case SIOCDIFADDR:
342 if (ifp == 0) {
343 error = EADDRNOTAVAIL;
344 goto done;
345 }
346 if (ifra->ifra_addr.sin_family == AF_INET) {
347 struct in_ifaddr *oia;
348
349 lck_mtx_lock(rt_mtx);
350 for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
351 if (ia->ia_ifp == ifp &&
352 ia->ia_addr.sin_addr.s_addr ==
353 ifra->ifra_addr.sin_addr.s_addr)
354 break;
355 }
356 /* take a reference on ia before releasing mutex */
357 if (ia != NULL && ia != oia) {
358 ifaref(&ia->ia_ifa);
359 }
360 lck_mtx_unlock(rt_mtx);
361 if (oia != NULL && oia != ia) {
362 ifafree(&oia->ia_ifa);
363 }
364 if ((ifp->if_flags & IFF_POINTOPOINT)
365 && (cmd == SIOCAIFADDR)
366 && (ifra->ifra_dstaddr.sin_addr.s_addr
367 == INADDR_ANY)) {
368 error = EDESTADDRREQ;
369 goto done;
370 }
371 }
372 else if (cmd == SIOCAIFADDR) {
373 error = EINVAL;
374 goto done;
375 }
376 if (cmd == SIOCDIFADDR && ia == 0) {
377 error = EADDRNOTAVAIL;
378 goto done;
379 }
380 /* FALLTHROUGH */
381 case SIOCSIFADDR:
382 case SIOCSIFNETMASK:
383 case SIOCSIFDSTADDR:
384 if ((so->so_state & SS_PRIV) == 0) {
385 error = EPERM;
386 goto done;
387 }
388 if (ifp == 0) {
389 error = EADDRNOTAVAIL;
390 goto done;
391 }
392 if (ifra->ifra_addr.sin_family != AF_INET
393 && cmd == SIOCSIFADDR) {
394 error = EINVAL;
395 goto done;
396 }
397 if (ia == (struct in_ifaddr *)0) {
398 ia = (struct in_ifaddr *)
399 _MALLOC(sizeof *ia, M_IFADDR, M_WAITOK);
400 if (ia == (struct in_ifaddr *)NULL) {
401 error = ENOBUFS;
402 goto done;
403 }
404 bzero((caddr_t)ia, sizeof *ia);
405 /*
406 * Protect from ipintr() traversing address list
407 * while we're modifying it.
408 */
409
410 ifa = &ia->ia_ifa;
411
412 ia->ia_addr.sin_family = AF_INET;
413 ia->ia_addr.sin_len = sizeof (ia->ia_addr);
414 ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
415 ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
416 ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
417 ia->ia_sockmask.sin_len = 8;
418 ifnet_lock_exclusive(ifp);
419 if (ifp->if_flags & IFF_BROADCAST) {
420 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
421 ia->ia_broadaddr.sin_family = AF_INET;
422 }
423 ia->ia_ifp = ifp;
424 if (!(ifp->if_flags & IFF_LOOPBACK))
425 in_interfaces++;
426 if_attach_ifa(ifp, ifa);
427 ifnet_lock_done(ifp);
428
429 lck_mtx_lock(rt_mtx);
430 ifaref(&ia->ia_ifa);
431 TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
432 lck_mtx_unlock(rt_mtx);
433
434 /* Generic protocol plumbing */
435
436 if ((error = proto_plumb(PF_INET, ifp))) {
437 if (error != EEXIST) {
438 kprintf("in.c: warning can't plumb proto if=%s%d type %d error=%d\n",
439 ifp->if_name, ifp->if_unit, ifp->if_type, error);
440 }
441 error = 0; /*discard error, can be cold with unsupported interfaces */
442 }
443
444 }
445 break;
446
447 case SIOCPROTOATTACH:
448 case SIOCPROTODETACH:
449 if (p && (error = proc_suser(p)) != 0) {
450 goto done;
451 }
452 if (ifp == 0) {
453 error = EADDRNOTAVAIL;
454 goto done;
455 }
456 break;
457
458 case SIOCSIFBRDADDR:
459 #ifdef __APPLE__
460 if ((so->so_state & SS_PRIV) == 0) {
461 error = EPERM;
462 goto done;
463 }
464 #else
465 if (p && (error = suser(p)) != 0) {
466 goto done;
467 }
468 #endif
469 /* FALLTHROUGH */
470
471 case SIOCGIFADDR:
472 case SIOCGIFNETMASK:
473 case SIOCGIFDSTADDR:
474 case SIOCGIFBRDADDR:
475 if (ia == (struct in_ifaddr *)0) {
476 error = EADDRNOTAVAIL;
477 goto done;
478 }
479 break;
480 }
481 switch (cmd) {
482 case SIOCAUTOADDR:
483 ifnet_lock_exclusive(ifp);
484 if (ifr->ifr_intval)
485 ifp->if_eflags |= IFEF_AUTOCONFIGURING;
486 else
487 ifp->if_eflags &= ~IFEF_AUTOCONFIGURING;
488 ifnet_lock_done(ifp);
489 break;
490
491 case SIOCARPIPLL:
492 ipv4_ll_arp_aware = 1;
493 ifnet_lock_exclusive(ifp);
494 if (ifr->ifr_data)
495 ifp->if_eflags |= IFEF_ARPLL;
496 else
497 ifp->if_eflags &= ~IFEF_ARPLL;
498 ifnet_lock_done(ifp);
499 break;
500
501 case SIOCGIFADDR:
502 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
503 break;
504
505 case SIOCGIFBRDADDR:
506 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
507 error = EINVAL;
508 break;
509 }
510 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
511 break;
512
513 case SIOCGIFDSTADDR:
514 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
515 error = EINVAL;
516 break;
517 }
518 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
519 break;
520
521 case SIOCGIFNETMASK:
522 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
523 break;
524
525 case SIOCSIFDSTADDR:
526 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
527 error = EINVAL;
528 break;
529 }
530 oldaddr = ia->ia_dstaddr;
531 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
532 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFDSTADDR, ia);
533 if (error == EOPNOTSUPP) {
534 error = 0;
535 }
536 if (error) {
537 ia->ia_dstaddr = oldaddr;
538 break;
539 }
540
541 ev_msg.vendor_code = KEV_VENDOR_APPLE;
542 ev_msg.kev_class = KEV_NETWORK_CLASS;
543 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
544
545 ev_msg.event_code = KEV_INET_SIFDSTADDR;
546
547 if (ia->ia_ifa.ifa_dstaddr)
548 in_event_data.ia_dstaddr =
549 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
550 else
551 in_event_data.ia_dstaddr.s_addr = 0;
552
553 in_event_data.ia_addr = ia->ia_addr.sin_addr;
554 in_event_data.ia_net = ia->ia_net;
555 in_event_data.ia_netmask = ia->ia_netmask;
556 in_event_data.ia_subnet = ia->ia_subnet;
557 in_event_data.ia_subnetmask = ia->ia_subnetmask;
558 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
559 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
560 in_event_data.link_data.if_family = ifp->if_family;
561 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
562
563 ev_msg.dv[0].data_ptr = &in_event_data;
564 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
565 ev_msg.dv[1].data_length = 0;
566
567 kev_post_msg(&ev_msg);
568
569
570 if (ia->ia_flags & IFA_ROUTE) {
571 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
572 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
573 ia->ia_ifa.ifa_dstaddr =
574 (struct sockaddr *)&ia->ia_dstaddr;
575 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
576 }
577 break;
578
579 case SIOCSIFBRDADDR:
580 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
581 error = EINVAL;
582 break;
583 }
584 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
585
586 ev_msg.vendor_code = KEV_VENDOR_APPLE;
587 ev_msg.kev_class = KEV_NETWORK_CLASS;
588 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
589
590 ev_msg.event_code = KEV_INET_SIFBRDADDR;
591
592 if (ia->ia_ifa.ifa_dstaddr)
593 in_event_data.ia_dstaddr =
594 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
595 else
596 in_event_data.ia_dstaddr.s_addr = 0;
597
598 in_event_data.ia_addr = ia->ia_addr.sin_addr;
599 in_event_data.ia_net = ia->ia_net;
600 in_event_data.ia_netmask = ia->ia_netmask;
601 in_event_data.ia_subnet = ia->ia_subnet;
602 in_event_data.ia_subnetmask = ia->ia_subnetmask;
603 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
604 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
605 in_event_data.link_data.if_family = ifp->if_family;
606 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
607
608 ev_msg.dv[0].data_ptr = &in_event_data;
609 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
610 ev_msg.dv[1].data_length = 0;
611
612 kev_post_msg(&ev_msg);
613
614 break;
615
616 case SIOCSIFADDR:
617 error = in_ifinit(ifp, ia, (struct sockaddr_in *) &ifr->ifr_addr, 1);
618 break;
619
620 case SIOCPROTOATTACH:
621 error = proto_plumb(PF_INET, ifp);
622 break;
623
624 case SIOCPROTODETACH:
625 // if an ip address is still present, refuse to detach
626 ifnet_lock_shared(ifp);
627 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
628 if (ifa->ifa_addr->sa_family == AF_INET)
629 break;
630 ifnet_lock_done(ifp);
631 if (ifa != 0) {
632 error = EBUSY;
633 break;
634 }
635
636 error = proto_unplumb(PF_INET, ifp);
637 break;
638
639
640 case SIOCSIFNETMASK: {
641 u_long i;
642
643 i = ifra->ifra_addr.sin_addr.s_addr;
644 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
645 ev_msg.vendor_code = KEV_VENDOR_APPLE;
646 ev_msg.kev_class = KEV_NETWORK_CLASS;
647 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
648
649 ev_msg.event_code = KEV_INET_SIFNETMASK;
650
651 if (ia->ia_ifa.ifa_dstaddr)
652 in_event_data.ia_dstaddr =
653 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
654 else
655 in_event_data.ia_dstaddr.s_addr = 0;
656
657 in_event_data.ia_addr = ia->ia_addr.sin_addr;
658 in_event_data.ia_net = ia->ia_net;
659 in_event_data.ia_netmask = ia->ia_netmask;
660 in_event_data.ia_subnet = ia->ia_subnet;
661 in_event_data.ia_subnetmask = ia->ia_subnetmask;
662 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
663 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
664 in_event_data.link_data.if_family = ifp->if_family;
665 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
666
667 ev_msg.dv[0].data_ptr = &in_event_data;
668 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
669 ev_msg.dv[1].data_length = 0;
670
671 kev_post_msg(&ev_msg);
672
673 break;
674 }
675 case SIOCAIFADDR:
676 maskIsNew = 0;
677 hostIsNew = 1;
678 error = 0;
679 if (ia->ia_addr.sin_family == AF_INET) {
680 if (ifra->ifra_addr.sin_len == 0) {
681 ifra->ifra_addr = ia->ia_addr;
682 hostIsNew = 0;
683 } else if (ifra->ifra_addr.sin_addr.s_addr ==
684 ia->ia_addr.sin_addr.s_addr)
685 hostIsNew = 0;
686 }
687 if (ifra->ifra_mask.sin_len) {
688 in_ifscrub(ifp, ia, 0);
689 ia->ia_sockmask = ifra->ifra_mask;
690 ia->ia_subnetmask =
691 ntohl(ia->ia_sockmask.sin_addr.s_addr);
692 maskIsNew = 1;
693 }
694 if ((ifp->if_flags & IFF_POINTOPOINT) &&
695 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
696 in_ifscrub(ifp, ia, 0);
697 ia->ia_dstaddr = ifra->ifra_dstaddr;
698 maskIsNew = 1; /* We lie; but the effect's the same */
699 }
700 if (ifra->ifra_addr.sin_family == AF_INET &&
701 (hostIsNew || maskIsNew)) {
702 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
703 }
704 if ((ifp->if_flags & IFF_BROADCAST) &&
705 (ifra->ifra_broadaddr.sin_family == AF_INET))
706 ia->ia_broadaddr = ifra->ifra_broadaddr;
707
708 /*
709 * Report event.
710 */
711
712 if ((error == 0) || (error == EEXIST)) {
713 ev_msg.vendor_code = KEV_VENDOR_APPLE;
714 ev_msg.kev_class = KEV_NETWORK_CLASS;
715 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
716
717 if (hostIsNew)
718 ev_msg.event_code = KEV_INET_NEW_ADDR;
719 else
720 ev_msg.event_code = KEV_INET_CHANGED_ADDR;
721
722 if (ia->ia_ifa.ifa_dstaddr)
723 in_event_data.ia_dstaddr =
724 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
725 else
726 in_event_data.ia_dstaddr.s_addr = 0;
727
728 in_event_data.ia_addr = ia->ia_addr.sin_addr;
729 in_event_data.ia_net = ia->ia_net;
730 in_event_data.ia_netmask = ia->ia_netmask;
731 in_event_data.ia_subnet = ia->ia_subnet;
732 in_event_data.ia_subnetmask = ia->ia_subnetmask;
733 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
734 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
735 in_event_data.link_data.if_family = ifp->if_family;
736 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
737
738 ev_msg.dv[0].data_ptr = &in_event_data;
739 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
740 ev_msg.dv[1].data_length = 0;
741
742 kev_post_msg(&ev_msg);
743 }
744 break;
745
746 case SIOCDIFADDR:
747 error = ifnet_ioctl(ifp, PF_INET, SIOCDIFADDR, ia);
748 if (error == EOPNOTSUPP)
749 error = 0;
750 if (error != 0) {
751 break;
752 }
753
754 /* Fill out the kernel event information */
755 ev_msg.vendor_code = KEV_VENDOR_APPLE;
756 ev_msg.kev_class = KEV_NETWORK_CLASS;
757 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
758
759 ev_msg.event_code = KEV_INET_ADDR_DELETED;
760
761 if (ia->ia_ifa.ifa_dstaddr)
762 in_event_data.ia_dstaddr =
763 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
764 else
765 in_event_data.ia_dstaddr.s_addr = 0;
766
767 in_event_data.ia_addr = ia->ia_addr.sin_addr;
768 in_event_data.ia_net = ia->ia_net;
769 in_event_data.ia_netmask = ia->ia_netmask;
770 in_event_data.ia_subnet = ia->ia_subnet;
771 in_event_data.ia_subnetmask = ia->ia_subnetmask;
772 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
773 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
774 in_event_data.link_data.if_family = ifp->if_family;
775 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
776
777 ev_msg.dv[0].data_ptr = &in_event_data;
778 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
779 ev_msg.dv[1].data_length = 0;
780
781 lck_mtx_lock(rt_mtx);
782 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
783 /*
784 * in_ifscrub kills the interface route.
785 */
786 in_ifscrub(ifp, ia, 1);
787 ifa = &ia->ia_ifa;
788 lck_mtx_unlock(rt_mtx);
789 ifnet_lock_exclusive(ifp);
790 if_detach_ifa(ifp, ifa);
791
792 #ifdef __APPLE__
793 /*
794 * If the interface supports multicast, and no address is left,
795 * remove the "all hosts" multicast group from that interface.
796 */
797 if (ifp->if_flags & IFF_MULTICAST) {
798 struct in_addr addr;
799 struct in_multi *inm = NULL;
800
801 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
802 if (ifa->ifa_addr->sa_family == AF_INET)
803 break;
804
805 if (ifa == 0) {
806 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
807 IN_LOOKUP_MULTI(addr, ifp, inm);
808 }
809 ifnet_lock_done(ifp);
810 if (inm)
811 in_delmulti(&inm);
812 } else
813 ifnet_lock_done(ifp);
814 #endif
815
816 /* Post the kernel event */
817 kev_post_msg(&ev_msg);
818
819 /*
820 * See if there is any IPV4 address left and if so,
821 * reconfigure KDP to use current primary address.
822 */
823 ifa = ifa_ifpgetprimary(ifp, AF_INET);
824 if (ifa != NULL) {
825 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa);
826 if (error == EOPNOTSUPP)
827 error = 0;
828
829 /* Release reference from ifa_ifpgetprimary() */
830 ifafree(ifa);
831 }
832 break;
833
834 #ifdef __APPLE__
835 case SIOCSETOT: {
836 /*
837 * Inspiration from tcp_ctloutput() and ip_ctloutput()
838 * Special ioctl for OpenTransport sockets
839 */
840 struct inpcb *inp, *cloned_inp;
841 int error2 = 0;
842 int cloned_fd = *(int *)data;
843
844 inp = sotoinpcb(so);
845 if (inp == NULL) {
846 break;
847 }
848
849 /* let's make sure it's either -1 or a valid file descriptor */
850 if (cloned_fd != -1) {
851 struct socket *cloned_so;
852 error2 = file_socket(cloned_fd, &cloned_so);
853 if (error2){
854 break;
855 }
856 cloned_inp = sotoinpcb(cloned_so);
857 file_drop(cloned_fd);
858 } else {
859 cloned_inp = NULL;
860 }
861
862 if (cloned_inp == NULL) {
863 /* OT always uses IP_PORTRANGE_HIGH */
864 inp->inp_flags &= ~(INP_LOWPORT);
865 inp->inp_flags |= INP_HIGHPORT;
866 /* For UDP, OT allows broadcast by default */
867 if (so->so_type == SOCK_DGRAM)
868 so->so_options |= SO_BROADCAST;
869 /* For TCP we want to see MSG_OOB when receive urgent data */
870 else if (so->so_type == SOCK_STREAM)
871 so->so_options |= SO_WANTOOBFLAG;
872 } else {
873 inp->inp_ip_tos = cloned_inp->inp_ip_tos;
874 inp->inp_ip_ttl = cloned_inp->inp_ip_ttl;
875 inp->inp_flags = cloned_inp->inp_flags;
876
877 /* Multicast options */
878 if (cloned_inp->inp_moptions != NULL) {
879 int i;
880 struct ip_moptions *cloned_imo = cloned_inp->inp_moptions;
881 struct ip_moptions *imo = inp->inp_moptions;
882
883 if (imo == NULL) {
884 /*
885 * No multicast option buffer attached to the pcb;
886 * allocate one.
887 */
888 imo = (struct ip_moptions*)
889 _MALLOC(sizeof(*imo), M_IPMOPTS, M_WAITOK);
890 if (imo == NULL) {
891 error2 = ENOBUFS;
892 break;
893 }
894 inp->inp_moptions = imo;
895 }
896 imo->imo_multicast_ifp = cloned_imo->imo_multicast_ifp;
897 imo->imo_multicast_vif = cloned_imo->imo_multicast_vif;
898 imo->imo_multicast_ttl = cloned_imo->imo_multicast_ttl;
899 imo->imo_multicast_loop = cloned_imo->imo_multicast_loop;
900 imo->imo_num_memberships = cloned_imo->imo_num_memberships;
901 for (i = 0; i < cloned_imo->imo_num_memberships; i++) {
902 imo->imo_membership[i] =
903 in_addmulti(&cloned_imo->imo_membership[i]->inm_addr,
904 cloned_imo->imo_membership[i]->inm_ifp);
905 if (imo->imo_membership[i] == NULL) {
906 error2 = ENOBUFS;
907 break;
908 }
909 }
910 if (i < cloned_imo->imo_num_memberships) {
911 /* Failed, perform cleanup */
912 for (i--; i >= 0; i--)
913 in_delmulti(&imo->imo_membership[i]);
914 imo->imo_num_memberships = 0;
915 break;
916 }
917 }
918 }
919 break;
920 }
921 #endif /* __APPLE__ */
922
923 default:
924 error = EOPNOTSUPP;
925 }
926 done:
927 if (ia != NULL) {
928 ifafree(&ia->ia_ifa);
929 }
930 return (error);
931 }
932
933 /*
934 * SIOC[GAD]LIFADDR.
935 * SIOCGLIFADDR: get first address. (?!?)
936 * SIOCGLIFADDR with IFLR_PREFIX:
937 * get first address that matches the specified prefix.
938 * SIOCALIFADDR: add the specified address.
939 * SIOCALIFADDR with IFLR_PREFIX:
940 * EINVAL since we can't deduce hostid part of the address.
941 * SIOCDLIFADDR: delete the specified address.
942 * SIOCDLIFADDR with IFLR_PREFIX:
943 * delete the first address that matches the specified prefix.
944 * return values:
945 * EINVAL on invalid parameters
946 * EADDRNOTAVAIL on prefix match failed/specified address not found
947 * other values may be returned from in_ioctl()
948 */
949 static int
950 in_lifaddr_ioctl(
951 struct socket *so,
952 u_long cmd,
953 caddr_t data,
954 struct ifnet *ifp,
955 struct proc *p)
956 {
957 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
958 struct ifaddr *ifa;
959
960 /* sanity checks */
961 if (!data || !ifp) {
962 panic("invalid argument to in_lifaddr_ioctl");
963 /*NOTRECHED*/
964 }
965
966 switch (cmd) {
967 case SIOCGLIFADDR:
968 /* address must be specified on GET with IFLR_PREFIX */
969 if ((iflr->flags & IFLR_PREFIX) == 0)
970 break;
971 /*FALLTHROUGH*/
972 case SIOCALIFADDR:
973 case SIOCDLIFADDR:
974 /* address must be specified on ADD and DELETE */
975 if (iflr->addr.ss_family != AF_INET)
976 return EINVAL;
977 if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
978 return EINVAL;
979 /* XXX need improvement */
980 if (iflr->dstaddr.ss_family
981 && iflr->dstaddr.ss_family != AF_INET)
982 return EINVAL;
983 if (iflr->dstaddr.ss_family
984 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
985 return EINVAL;
986 break;
987 default: /*shouldn't happen*/
988 return EOPNOTSUPP;
989 }
990 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
991 return EINVAL;
992
993 switch (cmd) {
994 case SIOCALIFADDR:
995 {
996 struct in_aliasreq ifra;
997
998 if (iflr->flags & IFLR_PREFIX)
999 return EINVAL;
1000
1001 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1002 bzero(&ifra, sizeof(ifra));
1003 bcopy(iflr->iflr_name, ifra.ifra_name,
1004 sizeof(ifra.ifra_name));
1005
1006 bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
1007
1008 if (iflr->dstaddr.ss_family) { /*XXX*/
1009 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1010 iflr->dstaddr.ss_len);
1011 }
1012
1013 ifra.ifra_mask.sin_family = AF_INET;
1014 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
1015 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
1016
1017 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p);
1018 }
1019 case SIOCGLIFADDR:
1020 case SIOCDLIFADDR:
1021 {
1022 struct in_ifaddr *ia;
1023 struct in_addr mask, candidate;
1024 struct in_addr match = { 0 };
1025 struct sockaddr_in *sin;
1026 int cmp;
1027
1028 bzero(&mask, sizeof(mask));
1029 if (iflr->flags & IFLR_PREFIX) {
1030 /* lookup a prefix rather than address. */
1031 in_len2mask(&mask, iflr->prefixlen);
1032
1033 sin = (struct sockaddr_in *)&iflr->addr;
1034 match.s_addr = sin->sin_addr.s_addr;
1035 match.s_addr &= mask.s_addr;
1036
1037 /* if you set extra bits, that's wrong */
1038 if (match.s_addr != sin->sin_addr.s_addr)
1039 return EINVAL;
1040
1041 cmp = 1;
1042 } else {
1043 if (cmd == SIOCGLIFADDR) {
1044 /* on getting an address, take the 1st match */
1045 cmp = 0; /*XXX*/
1046 } else {
1047 /* on deleting an address, do exact match */
1048 in_len2mask(&mask, 32);
1049 sin = (struct sockaddr_in *)&iflr->addr;
1050 match.s_addr = sin->sin_addr.s_addr;
1051
1052 cmp = 1;
1053 }
1054 }
1055
1056 ifnet_lock_shared(ifp);
1057 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1058 if (ifa->ifa_addr->sa_family != AF_INET6)
1059 continue;
1060 if (!cmp)
1061 break;
1062 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
1063 candidate.s_addr &= mask.s_addr;
1064 if (candidate.s_addr == match.s_addr)
1065 break;
1066 }
1067 ifnet_lock_done(ifp);
1068 if (!ifa)
1069 return EADDRNOTAVAIL;
1070 ia = (struct in_ifaddr *)ifa;
1071
1072 if (cmd == SIOCGLIFADDR) {
1073 /* fill in the if_laddrreq structure */
1074 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
1075
1076 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1077 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1078 ia->ia_dstaddr.sin_len);
1079 } else
1080 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
1081
1082 iflr->prefixlen =
1083 in_mask2len(&ia->ia_sockmask.sin_addr);
1084
1085 iflr->flags = 0; /*XXX*/
1086
1087 return 0;
1088 } else {
1089 struct in_aliasreq ifra;
1090
1091 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1092 bzero(&ifra, sizeof(ifra));
1093 bcopy(iflr->iflr_name, ifra.ifra_name,
1094 sizeof(ifra.ifra_name));
1095
1096 bcopy(&ia->ia_addr, &ifra.ifra_addr,
1097 ia->ia_addr.sin_len);
1098 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1099 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1100 ia->ia_dstaddr.sin_len);
1101 }
1102 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
1103 ia->ia_sockmask.sin_len);
1104
1105 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
1106 ifp, p);
1107 }
1108 }
1109 }
1110
1111 return EOPNOTSUPP; /*just for safety*/
1112 }
1113
1114 /*
1115 * Delete any existing route for an interface.
1116 */
1117 void
1118 in_ifscrub(
1119 struct ifnet *ifp,
1120 struct in_ifaddr *ia,
1121 int locked)
1122 {
1123
1124 if ((ia->ia_flags & IFA_ROUTE) == 0)
1125 return;
1126 if (!locked)
1127 lck_mtx_lock(rt_mtx);
1128 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
1129 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
1130 else
1131 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1132 ia->ia_flags &= ~IFA_ROUTE;
1133 if (!locked)
1134 lck_mtx_unlock(rt_mtx);
1135 }
1136
1137 /*
1138 * Initialize an interface's internet address
1139 * and routing table entry.
1140 */
1141 static int
1142 in_ifinit(
1143 struct ifnet *ifp,
1144 struct in_ifaddr *ia,
1145 struct sockaddr_in *sin,
1146 int scrub)
1147 {
1148 u_long i = ntohl(sin->sin_addr.s_addr);
1149 struct sockaddr_in oldaddr;
1150 int flags = RTF_UP, error;
1151 struct ifaddr *ifa0;
1152 unsigned int cmd;
1153
1154 oldaddr = ia->ia_addr;
1155 ia->ia_addr = *sin;
1156
1157 /*
1158 * Give the interface a chance to initialize if this is its first
1159 * address, and to validate the address if necessary. Send down
1160 * SIOCSIFADDR for first address, and SIOCAIFADDR for alias(es).
1161 * We find the first IPV4 address assigned to it and check if this
1162 * is the same as the one passed into this routine.
1163 */
1164 ifa0 = ifa_ifpgetprimary(ifp, AF_INET);
1165 cmd = (&ia->ia_ifa == ifa0) ? SIOCSIFADDR : SIOCAIFADDR;
1166 error = ifnet_ioctl(ifp, PF_INET, cmd, ia);
1167 if (error == EOPNOTSUPP)
1168 error = 0;
1169 /*
1170 * If we've just sent down SIOCAIFADDR, send another ioctl down
1171 * for SIOCSIFADDR for the first IPV4 address of the interface,
1172 * because an address change on one of the addresses will result
1173 * in the removal of the previous first IPV4 address. KDP needs
1174 * be reconfigured with the current primary IPV4 address.
1175 */
1176 if (error == 0 && cmd == SIOCAIFADDR) {
1177 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa0);
1178 if (error == EOPNOTSUPP)
1179 error = 0;
1180 }
1181
1182 /* Release reference from ifa_ifpgetprimary() */
1183 ifafree(ifa0);
1184
1185 if (error) {
1186 ia->ia_addr = oldaddr;
1187 return (error);
1188 }
1189 if (scrub) {
1190 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
1191 in_ifscrub(ifp, ia, 0);
1192 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1193 }
1194 if (IN_CLASSA(i))
1195 ia->ia_netmask = IN_CLASSA_NET;
1196 else if (IN_CLASSB(i))
1197 ia->ia_netmask = IN_CLASSB_NET;
1198 else
1199 ia->ia_netmask = IN_CLASSC_NET;
1200 /*
1201 * The subnet mask usually includes at least the standard network part,
1202 * but may may be smaller in the case of supernetting.
1203 * If it is set, we believe it.
1204 */
1205 if (ia->ia_subnetmask == 0) {
1206 ia->ia_subnetmask = ia->ia_netmask;
1207 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
1208 } else
1209 ia->ia_netmask &= ia->ia_subnetmask;
1210 ia->ia_net = i & ia->ia_netmask;
1211 ia->ia_subnet = i & ia->ia_subnetmask;
1212 in_socktrim(&ia->ia_sockmask);
1213 /*
1214 * Add route for the network.
1215 */
1216 ia->ia_ifa.ifa_metric = ifp->if_metric;
1217 if (ifp->if_flags & IFF_BROADCAST) {
1218 ia->ia_broadaddr.sin_addr.s_addr =
1219 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
1220 ia->ia_netbroadcast.s_addr =
1221 htonl(ia->ia_net | ~ ia->ia_netmask);
1222 } else if (ifp->if_flags & IFF_LOOPBACK) {
1223 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1224 flags |= RTF_HOST;
1225 } else if (ifp->if_flags & IFF_POINTOPOINT) {
1226 if (ia->ia_dstaddr.sin_family != AF_INET)
1227 return (0);
1228 flags |= RTF_HOST;
1229 }
1230 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
1231 ia->ia_flags |= IFA_ROUTE;
1232 /* XXX check if the subnet route points to the same interface */
1233 if (error == EEXIST)
1234 error = 0;
1235
1236 /*
1237 * If the interface supports multicast, join the "all hosts"
1238 * multicast group on that interface.
1239 */
1240 if (ifp->if_flags & IFF_MULTICAST) {
1241 struct in_multi *inm;
1242 struct in_addr addr;
1243
1244 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
1245 ifnet_lock_shared(ifp);
1246 IN_LOOKUP_MULTI(addr, ifp, inm);
1247 ifnet_lock_done(ifp);
1248 if (inm == 0)
1249 in_addmulti(&addr, ifp);
1250 }
1251 return (error);
1252 }
1253
1254
1255 /*
1256 * Return 1 if the address might be a local broadcast address.
1257 */
1258 int
1259 in_broadcast(
1260 struct in_addr in,
1261 struct ifnet *ifp)
1262 {
1263 struct ifaddr *ifa;
1264 u_long t;
1265
1266 if (in.s_addr == INADDR_BROADCAST ||
1267 in.s_addr == INADDR_ANY)
1268 return 1;
1269 if ((ifp->if_flags & IFF_BROADCAST) == 0)
1270 return 0;
1271 t = ntohl(in.s_addr);
1272 /*
1273 * Look through the list of addresses for a match
1274 * with a broadcast address.
1275 */
1276 #define ia ((struct in_ifaddr *)ifa)
1277 ifnet_lock_shared(ifp);
1278 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1279 if (ifa->ifa_addr == NULL) {
1280 ifnet_lock_done(ifp);
1281 return (0);
1282 }
1283 if (ifa->ifa_addr->sa_family == AF_INET &&
1284 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
1285 in.s_addr == ia->ia_netbroadcast.s_addr ||
1286 /*
1287 * Check for old-style (host 0) broadcast.
1288 */
1289 t == ia->ia_subnet || t == ia->ia_net) &&
1290 /*
1291 * Check for an all one subnetmask. These
1292 * only exist when an interface gets a secondary
1293 * address.
1294 */
1295 ia->ia_subnetmask != (u_long)0xffffffff) {
1296 ifnet_lock_done(ifp);
1297 return 1;
1298 }
1299 }
1300 ifnet_lock_done(ifp);
1301 return (0);
1302 #undef ia
1303 }
1304
1305 static void
1306 in_free_inm(
1307 void* ifma_protospec)
1308 {
1309 struct in_multi *inm = ifma_protospec;
1310
1311 /*
1312 * No remaining claims to this record; let IGMP know that
1313 * we are leaving the multicast group.
1314 */
1315 igmp_leavegroup(inm);
1316 lck_mtx_lock(rt_mtx);
1317 LIST_REMOVE(inm, inm_link);
1318 lck_mtx_unlock(rt_mtx);
1319 FREE(inm, M_IPMADDR);
1320 }
1321
1322 /*
1323 * Add an address to the list of IP multicast addresses for a given interface.
1324 */
1325 struct in_multi *
1326 in_addmulti(
1327 struct in_addr *ap,
1328 struct ifnet *ifp)
1329 {
1330 struct in_multi *inm;
1331 int error;
1332 struct sockaddr_in sin;
1333 struct ifmultiaddr *ifma;
1334
1335 /*
1336 * Call generic routine to add membership or increment
1337 * refcount. It wants addresses in the form of a sockaddr,
1338 * so we build one here (being careful to zero the unused bytes).
1339 */
1340 bzero(&sin, sizeof sin);
1341 sin.sin_family = AF_INET;
1342 sin.sin_len = sizeof sin;
1343 sin.sin_addr = *ap;
1344 error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
1345 if (error) {
1346 return 0;
1347 }
1348
1349 /*
1350 * If ifma->ifma_protospec is null, then if_addmulti() created
1351 * a new record. Otherwise, we are done.
1352 */
1353 if (ifma->ifma_protospec != 0) {
1354 return ifma->ifma_protospec;
1355 }
1356
1357 inm = (struct in_multi *) _MALLOC(sizeof(*inm), M_IPMADDR, M_WAITOK);
1358 if (inm == NULL) {
1359 return (NULL);
1360 }
1361
1362 bzero(inm, sizeof *inm);
1363 inm->inm_addr = *ap;
1364 inm->inm_ifp = ifp;
1365 inm->inm_ifma = ifma;
1366 lck_mtx_lock(rt_mtx);
1367 if (ifma->ifma_protospec == NULL) {
1368 ifma->ifma_protospec = inm;
1369 ifma->ifma_free = in_free_inm;
1370 LIST_INSERT_HEAD(&in_multihead, inm, inm_link);
1371 }
1372 lck_mtx_unlock(rt_mtx);
1373
1374 if (ifma->ifma_protospec != inm) {
1375 _FREE(inm, M_IPMADDR);
1376 return ifma->ifma_protospec;
1377 }
1378
1379 /*
1380 * Let IGMP know that we have joined a new IP multicast group.
1381 */
1382 error = igmp_joingroup(inm);
1383 if (error) {
1384 char addrbuf[16];
1385
1386 /*
1387 * We can't free the inm because someone else may already be
1388 * using it. Once we put it in to ifma->ifma_protospec, it
1389 * must exist as long as the ifma does. Might be nice to flag
1390 * the error so we can try igmp_joingroup the next time through.
1391 */
1392 log(LOG_ERR, "igmp_joingroup error %d joining multicast %s on %s%d\n",
1393 error, inet_ntop(AF_INET, &sin.sin_addr, addrbuf, sizeof(addrbuf)),
1394 ifp->if_name, ifp->if_unit);
1395 }
1396
1397 return (inm);
1398 }
1399
1400 /*
1401 * Delete a multicast address record.
1402 */
1403 void
1404 in_delmulti(
1405 struct in_multi **inm)
1406 {
1407 struct in_multi *inm2;
1408
1409 lck_mtx_lock(rt_mtx);
1410 LIST_FOREACH(inm2, &in_multihead, inm_link) {
1411 if (inm2 == *inm)
1412 break;
1413 }
1414 if (inm2 != *inm) {
1415 lck_mtx_unlock(rt_mtx);
1416 printf("in_delmulti - ignoring invalid inm (%p)\n", *inm);
1417 return;
1418 }
1419 lck_mtx_unlock(rt_mtx);
1420
1421 /* We intentionally do this a bit differently than BSD */
1422 if ((*inm)->inm_ifma) {
1423 if_delmultiaddr((*inm)->inm_ifma, 0);
1424 ifma_release((*inm)->inm_ifma);
1425 }
1426 *inm = NULL;
1427 }
1428
1429 #if !NFSCLIENT
1430 int inet_aton(char *cp, struct in_addr *pin);
1431 int
1432 inet_aton(char * cp, struct in_addr * pin)
1433 {
1434 u_char * b = (unsigned char *)pin;
1435 int i;
1436 char * p;
1437
1438 for (p = cp, i = 0; i < 4; i++) {
1439 u_long l = strtoul(p, 0, 0);
1440 if (l > 255)
1441 return (FALSE);
1442 b[i] = l;
1443 p = strchr(p, '.');
1444 if (i < 3 && p == NULL)
1445 return (FALSE);
1446 p++;
1447 }
1448 return (TRUE);
1449 }
1450 #endif