1/*
2 * Copyright (c) 2000-2021 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 */
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/sockio.h>
66#include <sys/socketvar.h>
67#include <sys/malloc.h>
68#include <sys/proc.h>
69#include <sys/socket.h>
70#include <sys/kernel.h>
71#include <sys/sysctl.h>
72#include <sys/kern_event.h>
73#include <sys/syslog.h>
74#include <sys/mcache.h>
75#include <sys/protosw.h>
76#include <sys/file.h>
77
78#include <kern/zalloc.h>
79#include <pexpert/pexpert.h>
80#include <os/log.h>
81
82#include <net/if.h>
83#include <net/if_types.h>
84#include <net/route.h>
85#include <net/kpi_protocol.h>
86#include <net/dlil.h>
87#if PF
88#include <net/pfvar.h>
89#endif /* PF */
90
91#include <netinet/in.h>
92#include <netinet/in_var.h>
93#include <netinet/in_pcb.h>
94#include <netinet/igmp_var.h>
95#include <netinet/ip_var.h>
96#include <netinet/tcp.h>
97#include <netinet/tcp_timer.h>
98#include <netinet/tcp_var.h>
99
100#include <net/sockaddr_utils.h>
101
102static int inctl_associd(struct socket *, u_long, caddr_t);
103static int inctl_connid(struct socket *, u_long, caddr_t);
104static int inctl_conninfo(struct socket *, u_long, caddr_t);
105static int inctl_autoaddr(struct ifnet *, struct ifreq *);
106static int inctl_arpipll(struct ifnet *, struct ifreq *);
107static int inctl_setrouter(struct ifnet *, struct ifreq *);
108static int inctl_ifaddr(struct ifnet *, struct in_ifaddr *, u_long,
109 struct ifreq *);
110static int inctl_ifdstaddr(struct ifnet *, struct in_ifaddr *, u_long,
111 struct ifreq *);
112static int inctl_ifbrdaddr(struct ifnet *, struct in_ifaddr *, u_long,
113 struct ifreq *);
114static int inctl_ifnetmask(struct ifnet *, struct in_ifaddr *, u_long,
115 struct ifreq *);
116
117static void in_socktrim(struct sockaddr_in *);
118static int in_ifinit(struct ifnet *, struct in_ifaddr *,
119 struct sockaddr_in *, int);
120
121#define IA_HASH_INIT(ia) { \
122 (ia)->ia_hash.tqe_next = (void *)(uintptr_t)-1; \
123 (ia)->ia_hash.tqe_prev = (void *)(uintptr_t)-1; \
124}
125
126#define IA_IS_HASHED(ia) \
127 (!((ia)->ia_hash.tqe_next == (void *)(uintptr_t)-1 || \
128 (ia)->ia_hash.tqe_prev == (void *)(uintptr_t)-1))
129
130static void in_iahash_remove(struct in_ifaddr *);
131static void in_iahash_insert(struct in_ifaddr *);
132static void in_iahash_insert_ptp(struct in_ifaddr *);
133static struct in_ifaddr *in_ifaddr_alloc(void);
134static void in_ifaddr_free(struct ifaddr *);
135
136static int in_getassocids(struct socket *, uint32_t *, user_addr_t);
137static int in_getconnids(struct socket *, sae_associd_t, uint32_t *, user_addr_t);
138
139static int subnetsarelocal = 0;
140SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local,
141 CTLFLAG_RW | CTLFLAG_LOCKED, &subnetsarelocal, 0, "");
142
143/* Track whether or not the SIOCARPIPLL ioctl has been called */
144u_int32_t ipv4_ll_arp_aware = 0;
145
146/*
147 * Return 1 if the address is
148 * - loopback
149 * - unicast or multicast link local
150 * - routed via a link level gateway
151 * - belongs to a directly connected (sub)net
152 */
153int
154inaddr_local(struct in_addr in)
155{
156 struct rtentry *rt;
157 struct sockaddr_in sin;
158 int local = 0;
159
160 if (ntohl(in.s_addr) == INADDR_LOOPBACK ||
161 IN_LINKLOCAL(ntohl(in.s_addr))) {
162 local = 1;
163 } else if (ntohl(in.s_addr) >= INADDR_UNSPEC_GROUP &&
164 ntohl(in.s_addr) <= INADDR_MAX_LOCAL_GROUP) {
165 local = 1;
166 } else {
167 sin.sin_family = AF_INET;
168 sin.sin_len = sizeof(sin);
169 sin.sin_addr = in;
170 rt = rtalloc1(SA(&sin), 0, 0);
171
172 if (rt != NULL) {
173 RT_LOCK_SPIN(rt);
174 if (rt->rt_gateway->sa_family == AF_LINK ||
175 (rt->rt_ifp->if_flags & IFF_LOOPBACK)) {
176 local = 1;
177 }
178 RT_UNLOCK(rt);
179 rtfree(rt);
180 } else {
181 local = in_localaddr(in);
182 }
183 }
184 return local;
185}
186
187/*
188 * Return 1 if an internet address is for a ``local'' host
189 * (one to which we have a connection). If subnetsarelocal
190 * is true, this includes other subnets of the local net,
191 * otherwise, it includes the directly-connected (sub)nets.
192 * The IPv4 link local prefix 169.254/16 is also included.
193 */
194int
195in_localaddr(struct in_addr in)
196{
197 u_int32_t i = ntohl(in.s_addr);
198 struct in_ifaddr *ia;
199
200 if (IN_LINKLOCAL(i)) {
201 return 1;
202 }
203
204 if (subnetsarelocal) {
205 lck_rw_lock_shared(lck: &in_ifaddr_rwlock);
206 for (ia = in_ifaddrhead.tqh_first; ia != NULL;
207 ia = ia->ia_link.tqe_next) {
208 IFA_LOCK(&ia->ia_ifa);
209 if ((i & ia->ia_netmask) == ia->ia_net) {
210 IFA_UNLOCK(&ia->ia_ifa);
211 lck_rw_done(lck: &in_ifaddr_rwlock);
212 return 1;
213 }
214 IFA_UNLOCK(&ia->ia_ifa);
215 }
216 lck_rw_done(lck: &in_ifaddr_rwlock);
217 } else {
218 lck_rw_lock_shared(lck: &in_ifaddr_rwlock);
219 for (ia = in_ifaddrhead.tqh_first; ia != NULL;
220 ia = ia->ia_link.tqe_next) {
221 IFA_LOCK(&ia->ia_ifa);
222 if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
223 IFA_UNLOCK(&ia->ia_ifa);
224 lck_rw_done(lck: &in_ifaddr_rwlock);
225 return 1;
226 }
227 IFA_UNLOCK(&ia->ia_ifa);
228 }
229 lck_rw_done(lck: &in_ifaddr_rwlock);
230 }
231 return 0;
232}
233
234/*
235 * Determine whether an IP address is in a reserved set of addresses
236 * that may not be forwarded, or whether datagrams to that destination
237 * may be forwarded.
238 */
239boolean_t
240in_canforward(struct in_addr in)
241{
242 u_int32_t i = ntohl(in.s_addr);
243 u_int32_t net;
244
245 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i)) {
246 return FALSE;
247 }
248 if (IN_CLASSA(i)) {
249 net = i & IN_CLASSA_NET;
250 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) {
251 return FALSE;
252 }
253 }
254 return TRUE;
255}
256
257/*
258 * Trim a mask in a sockaddr
259 */
260static void
261in_socktrim(struct sockaddr_in *ap)
262{
263 char *cplim = (char *)&ap->sin_addr;
264 char *cp = (char *)(&ap->sin_addr + 1);
265
266 ap->sin_len = 0;
267 while (--cp >= cplim) {
268 if (*cp) {
269 (ap)->sin_len = (uint8_t)(cp - (char *)(ap) + 1);
270 break;
271 }
272 }
273}
274
275static int in_interfaces; /* number of external internet interfaces */
276
277static int
278in_domifattach(struct ifnet *ifp)
279{
280 int error = 0;
281
282 VERIFY(ifp != NULL);
283
284 if ((error = proto_plumb(PF_INET, ifp)) && error != EEXIST) {
285 log(LOG_ERR, "%s: proto_plumb returned %d if=%s\n",
286 __func__, error, if_name(ifp));
287 return error;
288 }
289
290 if (ifp->if_inetdata == NULL) {
291 ifp->if_inetdata = zalloc_permanent_type(struct in_ifextra);
292 error = 0;
293 } else if (error != EEXIST) {
294 /*
295 * Since the structure is never freed, we need to
296 * zero out its contents to avoid reusing stale data.
297 * A little redundant with allocation above, but it
298 * keeps the code simpler for all cases.
299 */
300 IN_IFEXTRA(ifp)->netsig_len = 0;
301 bzero(IN_IFEXTRA(ifp)->netsig, n: sizeof(IN_IFEXTRA(ifp)->netsig));
302 }
303 return error;
304}
305
306static __attribute__((noinline)) int
307inctl_associd(struct socket *so, u_long cmd, caddr_t data)
308{
309 int error = 0;
310 union {
311 struct so_aidreq32 a32;
312 struct so_aidreq64 a64;
313 } u;
314
315 VERIFY(so != NULL);
316
317 switch (cmd) {
318 case SIOCGASSOCIDS32: /* struct so_aidreq32 */
319 bcopy(src: data, dst: &u.a32, n: sizeof(u.a32));
320 error = in_getassocids(so, &u.a32.sar_cnt, u.a32.sar_aidp);
321 if (error == 0) {
322 bcopy(src: &u.a32, dst: data, n: sizeof(u.a32));
323 }
324 break;
325
326 case SIOCGASSOCIDS64: /* struct so_aidreq64 */
327 bcopy(src: data, dst: &u.a64, n: sizeof(u.a64));
328 error = in_getassocids(so, &u.a64.sar_cnt, (user_addr_t)u.a64.sar_aidp);
329 if (error == 0) {
330 bcopy(src: &u.a64, dst: data, n: sizeof(u.a64));
331 }
332 break;
333
334 default:
335 VERIFY(0);
336 /* NOTREACHED */
337 }
338
339 return error;
340}
341
342static __attribute__((noinline)) int
343inctl_connid(struct socket *so, u_long cmd, caddr_t data)
344{
345 int error = 0;
346 union {
347 struct so_cidreq32 c32;
348 struct so_cidreq64 c64;
349 } u;
350
351 VERIFY(so != NULL);
352
353 switch (cmd) {
354 case SIOCGCONNIDS32: /* struct so_cidreq32 */
355 bcopy(src: data, dst: &u.c32, n: sizeof(u.c32));
356 error = in_getconnids(so, u.c32.scr_aid, &u.c32.scr_cnt,
357 u.c32.scr_cidp);
358 if (error == 0) {
359 bcopy(src: &u.c32, dst: data, n: sizeof(u.c32));
360 }
361 break;
362
363 case SIOCGCONNIDS64: /* struct so_cidreq64 */
364 bcopy(src: data, dst: &u.c64, n: sizeof(u.c64));
365 error = in_getconnids(so, u.c64.scr_aid, &u.c64.scr_cnt,
366 (user_addr_t)u.c64.scr_cidp);
367 if (error == 0) {
368 bcopy(src: &u.c64, dst: data, n: sizeof(u.c64));
369 }
370 break;
371
372 default:
373 VERIFY(0);
374 /* NOTREACHED */
375 }
376
377 return error;
378}
379
380static __attribute__((noinline)) int
381inctl_conninfo(struct socket *so, u_long cmd, caddr_t data)
382{
383 int error = 0;
384 union {
385 struct so_cinforeq32 ci32;
386 struct so_cinforeq64 ci64;
387 } u;
388
389 VERIFY(so != NULL);
390
391 switch (cmd) {
392 case SIOCGCONNINFO32: /* struct so_cinforeq32 */
393 bcopy(src: data, dst: &u.ci32, n: sizeof(u.ci32));
394 error = in_getconninfo(so, u.ci32.scir_cid, &u.ci32.scir_flags,
395 &u.ci32.scir_ifindex, &u.ci32.scir_error, u.ci32.scir_src,
396 &u.ci32.scir_src_len, u.ci32.scir_dst, &u.ci32.scir_dst_len,
397 &u.ci32.scir_aux_type, u.ci32.scir_aux_data,
398 &u.ci32.scir_aux_len);
399 if (error == 0) {
400 bcopy(src: &u.ci32, dst: data, n: sizeof(u.ci32));
401 }
402 break;
403
404 case SIOCGCONNINFO64: /* struct so_cinforeq64 */
405 bcopy(src: data, dst: &u.ci64, n: sizeof(u.ci64));
406 error = in_getconninfo(so, u.ci64.scir_cid, &u.ci64.scir_flags,
407 &u.ci64.scir_ifindex, &u.ci64.scir_error, (user_addr_t)u.ci64.scir_src,
408 &u.ci64.scir_src_len, (user_addr_t)u.ci64.scir_dst, &u.ci64.scir_dst_len,
409 &u.ci64.scir_aux_type, (user_addr_t)u.ci64.scir_aux_data,
410 &u.ci64.scir_aux_len);
411 if (error == 0) {
412 bcopy(src: &u.ci64, dst: data, n: sizeof(u.ci64));
413 }
414 break;
415
416 default:
417 VERIFY(0);
418 /* NOTREACHED */
419 }
420
421 return error;
422}
423
424/*
425 * Caller passes in the ioctl data pointer directly via "ifr", with the
426 * expectation that this routine always uses bcopy() or other byte-aligned
427 * memory accesses.
428 */
429static __attribute__((noinline)) int
430inctl_autoaddr(struct ifnet *ifp, struct ifreq *ifr)
431{
432 int error = 0, intval;
433
434 VERIFY(ifp != NULL);
435
436 bcopy(src: &ifr->ifr_intval, dst: &intval, n: sizeof(intval));
437
438 ifnet_lock_exclusive(ifp);
439 if (intval) {
440 /*
441 * An interface in IPv4 router mode implies that it
442 * is configured with a static IP address and should
443 * not act as a DHCP client; prevent SIOCAUTOADDR from
444 * being set in that mode.
445 */
446 if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
447 intval = 0; /* be safe; clear flag if set */
448 error = EBUSY;
449 } else {
450 if_set_eflags(ifp, IFEF_AUTOCONFIGURING);
451 }
452 }
453 if (!intval) {
454 if_clear_eflags(ifp, IFEF_AUTOCONFIGURING);
455 }
456 ifnet_lock_done(ifp);
457
458 return error;
459}
460
461/*
462 * Caller passes in the ioctl data pointer directly via "ifr", with the
463 * expectation that this routine always uses bcopy() or other byte-aligned
464 * memory accesses.
465 */
466static __attribute__((noinline)) int
467inctl_arpipll(struct ifnet *ifp, struct ifreq *ifr)
468{
469 int error = 0, intval;
470
471 VERIFY(ifp != NULL);
472
473 bcopy(src: &ifr->ifr_intval, dst: &intval, n: sizeof(intval));
474 ipv4_ll_arp_aware = 1;
475
476 ifnet_lock_exclusive(ifp);
477 if (intval) {
478 /*
479 * An interface in IPv4 router mode implies that it
480 * is configured with a static IP address and should
481 * not have to deal with IPv4 Link-Local Address;
482 * prevent SIOCARPIPLL from being set in that mode.
483 */
484 if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
485 intval = 0; /* be safe; clear flag if set */
486 error = EBUSY;
487 } else {
488 if_set_eflags(ifp, IFEF_ARPLL);
489 }
490 }
491 if (!intval) {
492 if_clear_eflags(ifp, IFEF_ARPLL);
493 }
494 ifnet_lock_done(ifp);
495
496 return error;
497}
498
499/*
500 * Handle SIOCSETROUTERMODE to set or clear the IPv4 router mode flag on
501 * the interface. When in this mode, IPv4 Link-Local Address support is
502 * disabled in ARP, and DHCP client support is disabled in IP input; turning
503 * any of them on would cause an error to be returned. Entering or exiting
504 * this mode will result in the removal of IPv4 addresses currently configured
505 * on the interface.
506 *
507 * Caller passes in the ioctl data pointer directly via "ifr", with the
508 * expectation that this routine always uses bcopy() or other byte-aligned
509 * memory accesses.
510 */
511static __attribute__((noinline)) int
512inctl_setrouter(struct ifnet *ifp, struct ifreq *ifr)
513{
514 int error = 0, intval;
515
516 VERIFY(ifp != NULL);
517
518 /* Router mode isn't valid for loopback */
519 if (ifp->if_flags & IFF_LOOPBACK) {
520 return ENODEV;
521 }
522
523 bcopy(src: &ifr->ifr_intval, dst: &intval, n: sizeof(intval));
524 switch (intval) {
525 case 0:
526 case 1:
527 break;
528 default:
529 return EINVAL;
530 }
531 ifnet_lock_exclusive(ifp);
532 if (intval != 0) {
533 if_set_eflags(ifp, IFEF_IPV4_ROUTER);
534 if_clear_eflags(ifp, (IFEF_ARPLL | IFEF_AUTOCONFIGURING));
535 } else {
536 if_clear_eflags(ifp, IFEF_IPV4_ROUTER);
537 }
538 ifnet_lock_done(ifp);
539
540 /* purge all IPv4 addresses configured on this interface */
541 in_purgeaddrs(ifp);
542
543 return error;
544}
545
546/*
547 * Caller passes in the ioctl data pointer directly via "ifr", with the
548 * expectation that this routine always uses bcopy() or other byte-aligned
549 * memory accesses.
550 */
551static __attribute__((noinline)) int
552inctl_ifaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
553 struct ifreq *ifr)
554{
555 struct kev_in_data in_event_data;
556 struct kev_msg ev_msg;
557 struct sockaddr_in addr;
558 struct ifaddr *ifa;
559 int error = 0;
560
561 VERIFY(ifp != NULL);
562
563 bzero(s: &in_event_data, n: sizeof(struct kev_in_data));
564 bzero(s: &ev_msg, n: sizeof(struct kev_msg));
565
566 switch (cmd) {
567 case SIOCGIFADDR: /* struct ifreq */
568 if (ia == NULL) {
569 error = EADDRNOTAVAIL;
570 break;
571 }
572 IFA_LOCK(&ia->ia_ifa);
573 SOCKADDR_COPY(&ia->ia_addr, &ifr->ifr_addr, sizeof(addr));
574 IFA_UNLOCK(&ia->ia_ifa);
575 break;
576
577 case SIOCSIFADDR: /* struct ifreq */
578 VERIFY(ia != NULL);
579 SOCKADDR_COPY(&ifr->ifr_addr, &addr, sizeof(addr));
580 /*
581 * If this is a new address, the reference count for the
582 * hash table has been taken at creation time above.
583 */
584 error = in_ifinit(ifp, ia, &addr, 1);
585 if (error == 0) {
586 (void) ifnet_notify_address(ifp, AF_INET);
587 }
588 break;
589
590 case SIOCAIFADDR: { /* struct {if,in_}aliasreq */
591 struct in_aliasreq *ifra = (struct in_aliasreq *)ifr;
592 struct sockaddr_in broadaddr, mask;
593 int hostIsNew, maskIsNew;
594
595 VERIFY(ia != NULL);
596 SOCKADDR_COPY(&ifra->ifra_addr, &addr, sizeof(addr));
597 SOCKADDR_COPY(&ifra->ifra_broadaddr, &broadaddr, sizeof(broadaddr));
598 SOCKADDR_COPY(&ifra->ifra_mask, &mask, sizeof(mask));
599
600 maskIsNew = 0;
601 hostIsNew = 1;
602 error = 0;
603
604 IFA_LOCK(&ia->ia_ifa);
605 if (ia->ia_addr.sin_family == AF_INET) {
606 if (addr.sin_len == 0) {
607 addr = ia->ia_addr;
608 hostIsNew = 0;
609 } else if (addr.sin_addr.s_addr ==
610 ia->ia_addr.sin_addr.s_addr) {
611 hostIsNew = 0;
612 }
613 }
614 if (mask.sin_len != 0) {
615 IFA_UNLOCK(&ia->ia_ifa);
616 in_ifscrub(ifp, ia, 0);
617 IFA_LOCK(&ia->ia_ifa);
618 ia->ia_sockmask.sin_len = sizeof(struct sockaddr_in);
619 ia->ia_sockmask.sin_family = AF_INET;
620 ia->ia_sockmask.sin_port = 0;
621 ia->ia_sockmask.sin_addr = mask.sin_addr;
622 bzero(s: &ia->ia_sockmask.sin_zero, n: sizeof(ia->ia_dstaddr.sin_zero));
623 ia->ia_subnetmask =
624 ntohl(ia->ia_sockmask.sin_addr.s_addr);
625 maskIsNew = 1;
626 }
627 if ((ifp->if_flags & IFF_POINTOPOINT) &&
628 (broadaddr.sin_family == AF_INET)) {
629 IFA_UNLOCK(&ia->ia_ifa);
630 in_ifscrub(ifp, ia, 0);
631 IFA_LOCK(&ia->ia_ifa);
632 ia->ia_dstaddr.sin_family = AF_INET;
633 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
634 ia->ia_dstaddr.sin_port = 0;
635 ia->ia_dstaddr.sin_addr = broadaddr.sin_addr;
636 bzero(s: &ia->ia_dstaddr.sin_zero, n: sizeof(ia->ia_dstaddr.sin_zero));
637 maskIsNew = 1; /* We lie; but the effect's the same */
638 }
639 if (addr.sin_family == AF_INET && (hostIsNew || maskIsNew)) {
640 IFA_UNLOCK(&ia->ia_ifa);
641 error = in_ifinit(ifp, ia, &addr, 0);
642 } else {
643 IFA_UNLOCK(&ia->ia_ifa);
644 }
645 if (error == 0) {
646 (void) ifnet_notify_address(ifp, AF_INET);
647 }
648 IFA_LOCK(&ia->ia_ifa);
649 if ((ifp->if_flags & IFF_BROADCAST) &&
650 (broadaddr.sin_family == AF_INET)) {
651 ia->ia_broadaddr.sin_family = AF_INET;
652 ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
653 ia->ia_broadaddr.sin_port = 0;
654 ia->ia_broadaddr.sin_addr = broadaddr.sin_addr;
655 bzero(s: &ia->ia_broadaddr.sin_zero, n: sizeof(ia->ia_broadaddr.sin_zero));
656 }
657
658 /*
659 * Report event.
660 */
661 if ((error == 0) || (error == EEXIST)) {
662 ev_msg.vendor_code = KEV_VENDOR_APPLE;
663 ev_msg.kev_class = KEV_NETWORK_CLASS;
664 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
665
666 if (hostIsNew) {
667 ev_msg.event_code = KEV_INET_NEW_ADDR;
668 } else {
669 ev_msg.event_code = KEV_INET_CHANGED_ADDR;
670 }
671
672 if (ia->ia_ifa.ifa_dstaddr) {
673 in_event_data.ia_dstaddr = SIN(ia->ia_ifa.ifa_dstaddr)->sin_addr;
674 } else {
675 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
676 }
677 in_event_data.ia_addr = ia->ia_addr.sin_addr;
678 in_event_data.ia_net = ia->ia_net;
679 in_event_data.ia_netmask = ia->ia_netmask;
680 in_event_data.ia_subnet = ia->ia_subnet;
681 in_event_data.ia_subnetmask = ia->ia_subnetmask;
682 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
683 IFA_UNLOCK(&ia->ia_ifa);
684 (void) strlcpy(dst: &in_event_data.link_data.if_name[0],
685 src: ifp->if_name, IFNAMSIZ);
686 in_event_data.link_data.if_family = ifp->if_family;
687 in_event_data.link_data.if_unit = ifp->if_unit;
688
689 ev_msg.dv[0].data_ptr = &in_event_data;
690 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
691 ev_msg.dv[1].data_length = 0;
692
693 dlil_post_complete_msg(ifp, &ev_msg);
694 } else {
695 IFA_UNLOCK(&ia->ia_ifa);
696 }
697 break;
698 }
699
700 case SIOCDIFADDR: /* struct ifreq */
701 VERIFY(ia != NULL);
702 error = ifnet_ioctl(interface: ifp, PF_INET, SIOCDIFADDR, ioctl_arg: ia);
703 if (error == EOPNOTSUPP) {
704 error = 0;
705 }
706 if (error != 0) {
707 break;
708 }
709
710 /* Fill out the kernel event information */
711 ev_msg.vendor_code = KEV_VENDOR_APPLE;
712 ev_msg.kev_class = KEV_NETWORK_CLASS;
713 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
714
715 ev_msg.event_code = KEV_INET_ADDR_DELETED;
716
717 IFA_LOCK(&ia->ia_ifa);
718 if (ia->ia_ifa.ifa_dstaddr) {
719 in_event_data.ia_dstaddr = SIN(ia->ia_ifa.ifa_dstaddr)->sin_addr;
720 } else {
721 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
722 }
723 in_event_data.ia_addr = ia->ia_addr.sin_addr;
724 in_event_data.ia_net = ia->ia_net;
725 in_event_data.ia_netmask = ia->ia_netmask;
726 in_event_data.ia_subnet = ia->ia_subnet;
727 in_event_data.ia_subnetmask = ia->ia_subnetmask;
728 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
729 IFA_UNLOCK(&ia->ia_ifa);
730 (void) strlcpy(dst: &in_event_data.link_data.if_name[0],
731 src: ifp->if_name, IFNAMSIZ);
732 in_event_data.link_data.if_family = ifp->if_family;
733 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
734
735 ev_msg.dv[0].data_ptr = &in_event_data;
736 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
737 ev_msg.dv[1].data_length = 0;
738
739 ifa = &ia->ia_ifa;
740 lck_rw_lock_exclusive(lck: &in_ifaddr_rwlock);
741 /* Release ia_link reference */
742 ifa_remref(ifa);
743 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
744 IFA_LOCK(ifa);
745 if (IA_IS_HASHED(ia)) {
746 in_iahash_remove(ia);
747 }
748 IFA_UNLOCK(ifa);
749 lck_rw_done(lck: &in_ifaddr_rwlock);
750
751 /*
752 * in_ifscrub kills the interface route.
753 */
754 in_ifscrub(ifp, ia, 0);
755 ifnet_lock_exclusive(ifp);
756 IFA_LOCK(ifa);
757 /* if_detach_ifa() releases ifa_link reference */
758 if_detach_ifa(ifp, ifa);
759 /* Our reference to this address is dropped at the bottom */
760 IFA_UNLOCK(ifa);
761
762 /* invalidate route caches */
763 routegenid_inet_update();
764
765 /*
766 * If the interface supports multicast, and no address is left,
767 * remove the "all hosts" multicast group from that interface.
768 */
769 if ((ifp->if_flags & IFF_MULTICAST) ||
770 ifp->if_allhostsinm != NULL) {
771 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
772 IFA_LOCK(ifa);
773 if (ifa->ifa_addr->sa_family == AF_INET) {
774 IFA_UNLOCK(ifa);
775 break;
776 }
777 IFA_UNLOCK(ifa);
778 }
779 ifnet_lock_done(ifp);
780
781 lck_mtx_lock(lck: &ifp->if_addrconfig_lock);
782 if (ifa == NULL && ifp->if_allhostsinm != NULL) {
783 struct in_multi *inm = ifp->if_allhostsinm;
784 ifp->if_allhostsinm = NULL;
785
786 in_delmulti(inm);
787 /* release the reference for allhostsinm */
788 INM_REMREF(inm);
789 }
790 lck_mtx_unlock(lck: &ifp->if_addrconfig_lock);
791 } else {
792 ifnet_lock_done(ifp);
793 }
794
795 /* Post the kernel event */
796 dlil_post_complete_msg(ifp, &ev_msg);
797
798 /*
799 * See if there is any IPV4 address left and if so,
800 * reconfigure KDP to use current primary address.
801 */
802 ifa = ifa_ifpgetprimary(ifp, AF_INET);
803 if (ifa != NULL) {
804 /*
805 * NOTE: SIOCSIFADDR is defined with struct ifreq
806 * as parameter, but here we are sending it down
807 * to the interface with a pointer to struct ifaddr,
808 * for legacy reasons.
809 */
810 error = ifnet_ioctl(interface: ifp, PF_INET, SIOCSIFADDR, ioctl_arg: ifa);
811 if (error == EOPNOTSUPP) {
812 error = 0;
813 }
814
815 /* Release reference from ifa_ifpgetprimary() */
816 ifa_remref(ifa);
817 }
818 (void) ifnet_notify_address(ifp, AF_INET);
819 break;
820
821 default:
822 VERIFY(0);
823 /* NOTREACHED */
824 }
825
826 return error;
827}
828
829/*
830 * Caller passes in the ioctl data pointer directly via "ifr", with the
831 * expectation that this routine always uses bcopy() or other byte-aligned
832 * memory accesses.
833 */
834static __attribute__((noinline)) int
835inctl_ifdstaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
836 struct ifreq *ifr)
837{
838 struct kev_in_data in_event_data;
839 struct kev_msg ev_msg;
840 struct sockaddr_in dstaddr;
841 int error = 0;
842
843 VERIFY(ifp != NULL);
844
845 if (!(ifp->if_flags & IFF_POINTOPOINT)) {
846 return EINVAL;
847 }
848
849 bzero(s: &in_event_data, n: sizeof(struct kev_in_data));
850 bzero(s: &ev_msg, n: sizeof(struct kev_msg));
851
852 switch (cmd) {
853 case SIOCGIFDSTADDR: /* struct ifreq */
854 if (ia == NULL) {
855 error = EADDRNOTAVAIL;
856 break;
857 }
858 IFA_LOCK(&ia->ia_ifa);
859 SOCKADDR_COPY(&ia->ia_dstaddr, &ifr->ifr_dstaddr, sizeof(dstaddr));
860 IFA_UNLOCK(&ia->ia_ifa);
861 break;
862
863 case SIOCSIFDSTADDR: /* struct ifreq */
864 VERIFY(ia != NULL);
865 IFA_LOCK(&ia->ia_ifa);
866 dstaddr = ia->ia_dstaddr;
867
868 ia->ia_dstaddr.sin_family = AF_INET;
869 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
870 ia->ia_dstaddr.sin_port = 0;
871 bcopy(src: &SIN(&ifr->ifr_dstaddr)->sin_addr,
872 dst: &ia->ia_dstaddr.sin_addr, n: sizeof(ia->ia_dstaddr.sin_addr));
873 bzero(s: &ia->ia_dstaddr.sin_zero, n: sizeof(ia->ia_dstaddr.sin_zero));
874
875 IFA_UNLOCK(&ia->ia_ifa);
876 /*
877 * NOTE: SIOCSIFDSTADDR is defined with struct ifreq
878 * as parameter, but here we are sending it down
879 * to the interface with a pointer to struct ifaddr,
880 * for legacy reasons.
881 */
882 error = ifnet_ioctl(interface: ifp, PF_INET, SIOCSIFDSTADDR, ioctl_arg: ia);
883 IFA_LOCK(&ia->ia_ifa);
884 if (error == EOPNOTSUPP) {
885 error = 0;
886 }
887 if (error != 0) {
888 ia->ia_dstaddr = dstaddr;
889 IFA_UNLOCK(&ia->ia_ifa);
890 break;
891 }
892 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
893
894 ev_msg.vendor_code = KEV_VENDOR_APPLE;
895 ev_msg.kev_class = KEV_NETWORK_CLASS;
896 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
897
898 ev_msg.event_code = KEV_INET_SIFDSTADDR;
899
900 if (ia->ia_ifa.ifa_dstaddr) {
901 in_event_data.ia_dstaddr = SIN(ia->ia_ifa.ifa_dstaddr)->sin_addr;
902 } else {
903 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
904 }
905
906 in_event_data.ia_addr = ia->ia_addr.sin_addr;
907 in_event_data.ia_net = ia->ia_net;
908 in_event_data.ia_netmask = ia->ia_netmask;
909 in_event_data.ia_subnet = ia->ia_subnet;
910 in_event_data.ia_subnetmask = ia->ia_subnetmask;
911 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
912 IFA_UNLOCK(&ia->ia_ifa);
913 (void) strlcpy(dst: &in_event_data.link_data.if_name[0],
914 src: ifp->if_name, IFNAMSIZ);
915 in_event_data.link_data.if_family = ifp->if_family;
916 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
917
918 ev_msg.dv[0].data_ptr = &in_event_data;
919 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
920 ev_msg.dv[1].data_length = 0;
921
922 dlil_post_complete_msg(ifp, &ev_msg);
923
924 lck_mtx_lock(rnh_lock);
925 IFA_LOCK(&ia->ia_ifa);
926 if (ia->ia_flags & IFA_ROUTE) {
927 ia->ia_ifa.ifa_dstaddr = SA(&dstaddr);
928 IFA_UNLOCK(&ia->ia_ifa);
929 rtinit_locked(&(ia->ia_ifa), RTM_DELETE, RTF_HOST);
930 IFA_LOCK(&ia->ia_ifa);
931 ia->ia_ifa.ifa_dstaddr =
932 SA(&ia->ia_dstaddr);
933 IFA_UNLOCK(&ia->ia_ifa);
934 rtinit_locked(&(ia->ia_ifa), RTM_ADD,
935 RTF_HOST | RTF_UP);
936 } else {
937 IFA_UNLOCK(&ia->ia_ifa);
938 }
939 lck_mtx_unlock(rnh_lock);
940 break;
941
942
943
944 default:
945 VERIFY(0);
946 /* NOTREACHED */
947 }
948
949 return error;
950}
951
952/*
953 * Caller passes in the ioctl data pointer directly via "ifr", with the
954 * expectation that this routine always uses bcopy() or other byte-aligned
955 * memory accesses.
956 */
957static __attribute__((noinline)) int
958inctl_ifbrdaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
959 struct ifreq *ifr)
960{
961 struct kev_in_data in_event_data;
962 struct kev_msg ev_msg;
963 int error = 0;
964
965 VERIFY(ifp != NULL);
966
967 if (ia == NULL) {
968 return EADDRNOTAVAIL;
969 }
970
971 if (!(ifp->if_flags & IFF_BROADCAST)) {
972 return EINVAL;
973 }
974
975 bzero(s: &in_event_data, n: sizeof(struct kev_in_data));
976 bzero(s: &ev_msg, n: sizeof(struct kev_msg));
977
978 switch (cmd) {
979 case SIOCGIFBRDADDR: /* struct ifreq */
980 IFA_LOCK(&ia->ia_ifa);
981 SOCKADDR_COPY(&ia->ia_broadaddr, &ifr->ifr_broadaddr,
982 sizeof(struct sockaddr_in));
983 IFA_UNLOCK(&ia->ia_ifa);
984 break;
985
986 case SIOCSIFBRDADDR: /* struct ifreq */
987 IFA_LOCK(&ia->ia_ifa);
988
989 ia->ia_broadaddr.sin_family = AF_INET;
990 ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
991 ia->ia_broadaddr.sin_port = 0;
992 bcopy(src: &SIN(&ifr->ifr_broadaddr)->sin_addr,
993 dst: &ia->ia_broadaddr.sin_addr, n: sizeof(ia->ia_broadaddr.sin_addr));
994 bzero(s: &ia->ia_broadaddr.sin_zero, n: sizeof(ia->ia_broadaddr.sin_zero));
995
996 ev_msg.vendor_code = KEV_VENDOR_APPLE;
997 ev_msg.kev_class = KEV_NETWORK_CLASS;
998 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
999
1000 ev_msg.event_code = KEV_INET_SIFBRDADDR;
1001
1002 if (ia->ia_ifa.ifa_dstaddr) {
1003 in_event_data.ia_dstaddr = SIN(ia->ia_ifa.ifa_dstaddr)->sin_addr;
1004 } else {
1005 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1006 }
1007 in_event_data.ia_addr = ia->ia_addr.sin_addr;
1008 in_event_data.ia_net = ia->ia_net;
1009 in_event_data.ia_netmask = ia->ia_netmask;
1010 in_event_data.ia_subnet = ia->ia_subnet;
1011 in_event_data.ia_subnetmask = ia->ia_subnetmask;
1012 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
1013 IFA_UNLOCK(&ia->ia_ifa);
1014 (void) strlcpy(dst: &in_event_data.link_data.if_name[0],
1015 src: ifp->if_name, IFNAMSIZ);
1016 in_event_data.link_data.if_family = ifp->if_family;
1017 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
1018
1019 ev_msg.dv[0].data_ptr = &in_event_data;
1020 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1021 ev_msg.dv[1].data_length = 0;
1022
1023 dlil_post_complete_msg(ifp, &ev_msg);
1024 break;
1025
1026 default:
1027 VERIFY(0);
1028 /* NOTREACHED */
1029 }
1030
1031 return error;
1032}
1033
1034/*
1035 * Caller passes in the ioctl data pointer directly via "ifr", with the
1036 * expectation that this routine always uses bcopy() or other byte-aligned
1037 * memory accesses.
1038 */
1039static __attribute__((noinline)) int
1040inctl_ifnetmask(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
1041 struct ifreq *ifr)
1042{
1043 struct kev_in_data in_event_data;
1044 struct kev_msg ev_msg;
1045 struct sockaddr_in mask;
1046 int error = 0;
1047
1048 VERIFY(ifp != NULL);
1049
1050 bzero(s: &in_event_data, n: sizeof(struct kev_in_data));
1051 bzero(s: &ev_msg, n: sizeof(struct kev_msg));
1052
1053 switch (cmd) {
1054 case SIOCGIFNETMASK: /* struct ifreq */
1055 if (ia == NULL) {
1056 error = EADDRNOTAVAIL;
1057 break;
1058 }
1059 IFA_LOCK(&ia->ia_ifa);
1060 SOCKADDR_COPY(&ia->ia_sockmask, &ifr->ifr_addr, sizeof(mask));
1061 IFA_UNLOCK(&ia->ia_ifa);
1062 break;
1063
1064 case SIOCSIFNETMASK: { /* struct ifreq */
1065 in_addr_t i;
1066
1067 SOCKADDR_COPY(&ifr->ifr_addr, &mask, sizeof(mask));
1068 i = mask.sin_addr.s_addr;
1069
1070 VERIFY(ia != NULL);
1071 IFA_LOCK(&ia->ia_ifa);
1072 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
1073 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1074 ev_msg.kev_class = KEV_NETWORK_CLASS;
1075 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1076
1077 ev_msg.event_code = KEV_INET_SIFNETMASK;
1078
1079 if (ia->ia_ifa.ifa_dstaddr) {
1080 in_event_data.ia_dstaddr = SIN(ia->ia_ifa.ifa_dstaddr)->sin_addr;
1081 } else {
1082 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1083 }
1084 in_event_data.ia_addr = ia->ia_addr.sin_addr;
1085 in_event_data.ia_net = ia->ia_net;
1086 in_event_data.ia_netmask = ia->ia_netmask;
1087 in_event_data.ia_subnet = ia->ia_subnet;
1088 in_event_data.ia_subnetmask = ia->ia_subnetmask;
1089 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
1090 IFA_UNLOCK(&ia->ia_ifa);
1091 (void) strlcpy(dst: &in_event_data.link_data.if_name[0],
1092 src: ifp->if_name, IFNAMSIZ);
1093 in_event_data.link_data.if_family = ifp->if_family;
1094 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
1095
1096 ev_msg.dv[0].data_ptr = &in_event_data;
1097 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1098 ev_msg.dv[1].data_length = 0;
1099
1100 dlil_post_complete_msg(ifp, &ev_msg);
1101 break;
1102 }
1103
1104 default:
1105 VERIFY(0);
1106 /* NOTREACHED */
1107 }
1108
1109 return error;
1110}
1111
1112/*
1113 * Generic INET control operations (ioctl's).
1114 *
1115 * ifp is NULL if not an interface-specific ioctl.
1116 *
1117 * Most of the routines called to handle the ioctls would end up being
1118 * tail-call optimized, which unfortunately causes this routine to
1119 * consume too much stack space; this is the reason for the "noinline"
1120 * attribute used on those routines.
1121 *
1122 * If called directly from within the networking stack (as opposed to via
1123 * pru_control), the socket parameter may be NULL.
1124 */
1125int
1126in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
1127 struct proc *p)
1128{
1129 struct ifreq *ifr = (struct ifreq *)(void *)data;
1130 struct sockaddr_in addr, dstaddr;
1131 struct sockaddr_in sin, *sa = NULL;
1132 boolean_t privileged = (proc_suser(p) == 0);
1133 boolean_t so_unlocked = FALSE;
1134 struct in_ifaddr *ia = NULL;
1135 struct ifaddr *ifa;
1136 int error = 0;
1137 int intval;
1138
1139 /* In case it's NULL, make sure it came from the kernel */
1140 VERIFY(so != NULL || p == kernproc);
1141
1142 /*
1143 * ioctls which don't require ifp, but require socket.
1144 */
1145 switch (cmd) {
1146 case SIOCGASSOCIDS32: /* struct so_aidreq32 */
1147 case SIOCGASSOCIDS64: /* struct so_aidreq64 */
1148 return inctl_associd(so, cmd, data);
1149 /* NOTREACHED */
1150
1151 case SIOCGCONNIDS32: /* struct so_cidreq32 */
1152 case SIOCGCONNIDS64: /* struct so_cidreq64 */
1153 return inctl_connid(so, cmd, data);
1154 /* NOTREACHED */
1155
1156 case SIOCGCONNINFO32: /* struct so_cinforeq32 */
1157 case SIOCGCONNINFO64: /* struct so_cinforeq64 */
1158 return inctl_conninfo(so, cmd, data);
1159 /* NOTREACHED */
1160 }
1161
1162 /*
1163 * The rest of ioctls require ifp; reject if we don't have one;
1164 * return ENXIO to be consistent with ifioctl().
1165 */
1166 if (ifp == NULL) {
1167 return ENXIO;
1168 }
1169
1170 /*
1171 * ioctls which require ifp but not interface address.
1172 */
1173 switch (cmd) {
1174 case SIOCAUTOADDR: /* struct ifreq */
1175 if (!privileged) {
1176 return EPERM;
1177 }
1178 return inctl_autoaddr(ifp, ifr);
1179 /* NOTREACHED */
1180
1181 case SIOCARPIPLL: /* struct ifreq */
1182 if (!privileged) {
1183 return EPERM;
1184 }
1185 return inctl_arpipll(ifp, ifr);
1186 /* NOTREACHED */
1187
1188 case SIOCGETROUTERMODE: /* struct ifreq */
1189 intval = (ifp->if_eflags & IFEF_IPV4_ROUTER) != 0 ? 1 : 0;
1190 bcopy(src: &intval, dst: &ifr->ifr_intval, n: sizeof(intval));
1191 return 0;
1192 /* NOTREACHED */
1193
1194 case SIOCSETROUTERMODE: /* struct ifreq */
1195 if (!privileged) {
1196 return EPERM;
1197 }
1198 return inctl_setrouter(ifp, ifr);
1199 /* NOTREACHED */
1200
1201 case SIOCPROTOATTACH: /* struct ifreq */
1202 if (!privileged) {
1203 return EPERM;
1204 }
1205 return in_domifattach(ifp);
1206 /* NOTREACHED */
1207
1208 case SIOCPROTODETACH: /* struct ifreq */
1209 if (!privileged) {
1210 return EPERM;
1211 }
1212
1213 /*
1214 * If an IPv4 address is still present, refuse to detach.
1215 */
1216 ifnet_lock_shared(ifp);
1217 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1218 IFA_LOCK(ifa);
1219 if (ifa->ifa_addr->sa_family == AF_INET) {
1220 IFA_UNLOCK(ifa);
1221 break;
1222 }
1223 IFA_UNLOCK(ifa);
1224 }
1225 ifnet_lock_done(ifp);
1226 return (ifa == NULL) ? proto_unplumb(PF_INET, ifp) : EBUSY;
1227 /* NOTREACHED */
1228 }
1229
1230 /*
1231 * ioctls which require interface address; obtain sockaddr_in.
1232 */
1233 switch (cmd) {
1234 case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1235 if (!privileged) {
1236 return EPERM;
1237 }
1238 SOCKADDR_COPY(&((struct in_aliasreq *)(void *)data)->ifra_addr,
1239 &sin, sizeof(sin));
1240 sa = &sin;
1241 break;
1242
1243 case SIOCDIFADDR: /* struct ifreq */
1244 case SIOCSIFADDR: /* struct ifreq */
1245 case SIOCSIFDSTADDR: /* struct ifreq */
1246 case SIOCSIFNETMASK: /* struct ifreq */
1247 case SIOCSIFBRDADDR: /* struct ifreq */
1248 if (!privileged) {
1249 return EPERM;
1250 }
1251 OS_FALLTHROUGH;
1252 case SIOCGIFADDR: /* struct ifreq */
1253 case SIOCGIFDSTADDR: /* struct ifreq */
1254 case SIOCGIFNETMASK: /* struct ifreq */
1255 case SIOCGIFBRDADDR: /* struct ifreq */
1256 SOCKADDR_COPY(&ifr->ifr_addr, &sin, sizeof(sin));
1257 sa = &sin;
1258 break;
1259 }
1260
1261 /*
1262 * Find address for this interface, if it exists.
1263 *
1264 * If an alias address was specified, find that one instead of
1265 * the first one on the interface, if possible.
1266 */
1267 VERIFY(ia == NULL);
1268 if (sa != NULL) {
1269 struct in_ifaddr *iap;
1270
1271 /*
1272 * Any failures from this point on must take into account
1273 * a non-NULL "ia" with an outstanding reference count, and
1274 * therefore requires ifa_remref. Jump to "done" label
1275 * instead of calling return if "ia" is valid.
1276 */
1277 lck_rw_lock_shared(lck: &in_ifaddr_rwlock);
1278 TAILQ_FOREACH(iap, INADDR_HASH(sa->sin_addr.s_addr), ia_hash) {
1279 IFA_LOCK(&iap->ia_ifa);
1280 if (iap->ia_ifp == ifp &&
1281 iap->ia_addr.sin_addr.s_addr ==
1282 sa->sin_addr.s_addr) {
1283 ia = iap;
1284 ifa_addref(ifa: &iap->ia_ifa);
1285 IFA_UNLOCK(&iap->ia_ifa);
1286 break;
1287 }
1288 IFA_UNLOCK(&iap->ia_ifa);
1289 }
1290 lck_rw_done(lck: &in_ifaddr_rwlock);
1291
1292 if (ia == NULL) {
1293 ifnet_lock_shared(ifp);
1294 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1295 iap = ifatoia(ifa);
1296 IFA_LOCK(&iap->ia_ifa);
1297 if (iap->ia_addr.sin_family == AF_INET) {
1298 ia = iap;
1299 ifa_addref(ifa: &iap->ia_ifa);
1300 IFA_UNLOCK(&iap->ia_ifa);
1301 break;
1302 }
1303 IFA_UNLOCK(&iap->ia_ifa);
1304 }
1305 ifnet_lock_done(ifp);
1306 }
1307 }
1308
1309 /*
1310 * Unlock the socket since ifnet_ioctl() may be invoked by
1311 * one of the ioctl handlers below. Socket will be re-locked
1312 * prior to returning.
1313 */
1314 if (so != NULL) {
1315 socket_unlock(so, refcount: 0);
1316 so_unlocked = TRUE;
1317 }
1318
1319 switch (cmd) {
1320 case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1321 case SIOCDIFADDR: /* struct ifreq */
1322 if (cmd == SIOCAIFADDR) {
1323 SOCKADDR_COPY(&((struct in_aliasreq *)(void *)data)->
1324 ifra_addr, &addr, sizeof(addr));
1325 SOCKADDR_COPY(&((struct in_aliasreq *)(void *)data)->
1326 ifra_dstaddr, &dstaddr, sizeof(dstaddr));
1327 } else {
1328 VERIFY(cmd == SIOCDIFADDR);
1329 SOCKADDR_COPY(&((struct ifreq *)(void *)data)->ifr_addr,
1330 &addr, sizeof(addr));
1331 SOCKADDR_ZERO(&dstaddr, sizeof(dstaddr));
1332 }
1333
1334 if (addr.sin_family == AF_INET) {
1335 struct in_ifaddr *oia;
1336
1337 lck_rw_lock_shared(lck: &in_ifaddr_rwlock);
1338 for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
1339 IFA_LOCK(&ia->ia_ifa);
1340 if (ia->ia_ifp == ifp &&
1341 ia->ia_addr.sin_addr.s_addr ==
1342 addr.sin_addr.s_addr) {
1343 ifa_addref(ifa: &ia->ia_ifa);
1344 IFA_UNLOCK(&ia->ia_ifa);
1345 break;
1346 }
1347 IFA_UNLOCK(&ia->ia_ifa);
1348 }
1349 lck_rw_done(lck: &in_ifaddr_rwlock);
1350 if (oia != NULL) {
1351 ifa_remref(ifa: &oia->ia_ifa);
1352 }
1353 if ((ifp->if_flags & IFF_POINTOPOINT) &&
1354 (cmd == SIOCAIFADDR) &&
1355 (dstaddr.sin_addr.s_addr == INADDR_ANY)) {
1356 error = EDESTADDRREQ;
1357 goto done;
1358 }
1359 } else if (cmd == SIOCAIFADDR) {
1360 error = EINVAL;
1361 goto done;
1362 }
1363 if (cmd == SIOCDIFADDR) {
1364 if (ia == NULL) {
1365 error = EADDRNOTAVAIL;
1366 goto done;
1367 }
1368
1369 IFA_LOCK(&ia->ia_ifa);
1370 /*
1371 * Avoid the race condition seen when two
1372 * threads process SIOCDIFADDR command
1373 * at the same time.
1374 */
1375 while (ia->ia_ifa.ifa_debug & IFD_DETACHING) {
1376 os_log(OS_LOG_DEFAULT,
1377 "Another thread is already attempting to "
1378 "delete IPv4 address: %s on interface %s. "
1379 "Go to sleep and check again after the operation is done",
1380 inet_ntoa(sa->sin_addr), ia->ia_ifp->if_xname);
1381 ia->ia_ifa.ifa_del_waiters++;
1382 (void) msleep(chan: ia->ia_ifa.ifa_del_wc, mtx: &ia->ia_ifa.ifa_lock, pri: (PZERO - 1),
1383 wmesg: __func__, NULL);
1384 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1385 }
1386
1387 if ((ia->ia_ifa.ifa_debug & IFD_ATTACHED) == 0) {
1388 error = EADDRNOTAVAIL;
1389 IFA_UNLOCK(&ia->ia_ifa);
1390 goto done;
1391 }
1392
1393 ia->ia_ifa.ifa_debug |= IFD_DETACHING;
1394 IFA_UNLOCK(&ia->ia_ifa);
1395 }
1396
1397 OS_FALLTHROUGH;
1398 case SIOCSIFADDR: /* struct ifreq */
1399 case SIOCSIFDSTADDR: /* struct ifreq */
1400 case SIOCSIFNETMASK: /* struct ifreq */
1401 if (cmd == SIOCAIFADDR) {
1402 /* fell thru from above; just repeat it */
1403 SOCKADDR_COPY(&((struct in_aliasreq *)(void *)data)->
1404 ifra_addr, &addr, sizeof(addr));
1405 } else {
1406 VERIFY(cmd == SIOCDIFADDR || cmd == SIOCSIFADDR ||
1407 cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR);
1408 SOCKADDR_COPY(&((struct ifreq *)(void *)data)->ifr_addr,
1409 &addr, sizeof(addr));
1410 }
1411
1412 if (addr.sin_family != AF_INET && cmd == SIOCSIFADDR) {
1413 error = EINVAL;
1414 goto done;
1415 }
1416
1417 if ((cmd == SIOCAIFADDR || cmd == SIOCSIFADDR) &&
1418 (IN_MULTICAST(ntohl(addr.sin_addr.s_addr)) ||
1419 addr.sin_addr.s_addr == INADDR_BROADCAST ||
1420 addr.sin_addr.s_addr == INADDR_ANY)) {
1421 error = EINVAL;
1422 goto done;
1423 }
1424
1425 if (ia == NULL) {
1426 ia = in_ifaddr_alloc();
1427 if (ia == NULL) {
1428 error = ENOBUFS;
1429 goto done;
1430 }
1431 ifnet_lock_exclusive(ifp);
1432 ifa = &ia->ia_ifa;
1433 IFA_LOCK(ifa);
1434 IA_HASH_INIT(ia);
1435 ifa->ifa_addr = SA(&ia->ia_addr);
1436 ifa->ifa_dstaddr = SA(&ia->ia_dstaddr);
1437 ifa->ifa_netmask = SA(&ia->ia_sockmask);
1438 ia->ia_sockmask.sin_len = offsetof(struct sockaddr_in, sin_zero);
1439 if (ifp->if_flags & IFF_BROADCAST) {
1440 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
1441 ia->ia_broadaddr.sin_family = AF_INET;
1442 }
1443 ia->ia_ifp = ifp;
1444 if (!(ifp->if_flags & IFF_LOOPBACK)) {
1445 in_interfaces++;
1446 }
1447 /* if_attach_ifa() holds a reference for ifa_link */
1448 if_attach_ifa(ifp, ifa);
1449 /*
1450 * If we have to go through in_ifinit(), make sure
1451 * to avoid installing route(s) based on this address
1452 * via PFC_IFUP event, before the link resolver (ARP)
1453 * initializes it.
1454 */
1455 if (cmd == SIOCAIFADDR || cmd == SIOCSIFADDR) {
1456 ifa->ifa_debug |= IFD_NOTREADY;
1457 }
1458 IFA_UNLOCK(ifa);
1459 ifnet_lock_done(ifp);
1460 lck_rw_lock_exclusive(lck: &in_ifaddr_rwlock);
1461 /* Hold a reference for ia_link */
1462 ifa_addref(ifa);
1463 TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
1464 lck_rw_done(lck: &in_ifaddr_rwlock);
1465 /* discard error */
1466 (void) in_domifattach(ifp);
1467 error = 0;
1468 }
1469 break;
1470 }
1471
1472 switch (cmd) {
1473 case SIOCGIFDSTADDR: /* struct ifreq */
1474 case SIOCSIFDSTADDR: /* struct ifreq */
1475 error = inctl_ifdstaddr(ifp, ia, cmd, ifr);
1476 break;
1477
1478 case SIOCGIFBRDADDR: /* struct ifreq */
1479 case SIOCSIFBRDADDR: /* struct ifreq */
1480 error = inctl_ifbrdaddr(ifp, ia, cmd, ifr);
1481 break;
1482
1483 case SIOCGIFNETMASK: /* struct ifreq */
1484 case SIOCSIFNETMASK: /* struct ifreq */
1485 error = inctl_ifnetmask(ifp, ia, cmd, ifr);
1486 break;
1487
1488 case SIOCGIFADDR: /* struct ifreq */
1489 case SIOCSIFADDR: /* struct ifreq */
1490 case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1491 case SIOCDIFADDR: /* struct ifreq */
1492 error = inctl_ifaddr(ifp, ia, cmd, ifr);
1493 break;
1494
1495 default:
1496 error = EOPNOTSUPP;
1497 break;
1498 }
1499
1500done:
1501 if (ia != NULL) {
1502 if (cmd == SIOCDIFADDR) {
1503 IFA_LOCK(&ia->ia_ifa);
1504 ia->ia_ifa.ifa_debug &= ~IFD_DETACHING;
1505 if (ia->ia_ifa.ifa_del_waiters > 0) {
1506 ia->ia_ifa.ifa_del_waiters = 0;
1507 wakeup(chan: ia->ia_ifa.ifa_del_wc);
1508 }
1509 IFA_UNLOCK(&ia->ia_ifa);
1510 }
1511 ifa_remref(ifa: &ia->ia_ifa);
1512 }
1513 if (so_unlocked) {
1514 socket_lock(so, refcount: 0);
1515 }
1516
1517 return error;
1518}
1519
1520/*
1521 * Delete any existing route for an interface.
1522 */
1523void
1524in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, int locked)
1525{
1526 IFA_LOCK(&ia->ia_ifa);
1527 if ((ia->ia_flags & IFA_ROUTE) == 0) {
1528 IFA_UNLOCK(&ia->ia_ifa);
1529 return;
1530 }
1531 IFA_UNLOCK(&ia->ia_ifa);
1532 if (!locked) {
1533 lck_mtx_lock(rnh_lock);
1534 }
1535 if (ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) {
1536 rtinit_locked(&(ia->ia_ifa), RTM_DELETE, RTF_HOST);
1537 } else {
1538 rtinit_locked(&(ia->ia_ifa), RTM_DELETE, 0);
1539 }
1540 IFA_LOCK(&ia->ia_ifa);
1541 ia->ia_flags &= ~IFA_ROUTE;
1542 IFA_UNLOCK(&ia->ia_ifa);
1543 if (!locked) {
1544 lck_mtx_unlock(rnh_lock);
1545 }
1546}
1547
1548/*
1549 * Caller must hold in_ifaddr_rwlock as writer.
1550 */
1551static void
1552in_iahash_remove(struct in_ifaddr *ia)
1553{
1554 LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1555 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1556
1557 if (!IA_IS_HASHED(ia)) {
1558 panic("attempt to remove wrong ia %p from hash table", ia);
1559 /* NOTREACHED */
1560 }
1561 TAILQ_REMOVE(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
1562 IA_HASH_INIT(ia);
1563 ifa_remref(ifa: &ia->ia_ifa);
1564}
1565
1566/*
1567 * Caller must hold in_ifaddr_rwlock as writer.
1568 */
1569static void
1570in_iahash_insert(struct in_ifaddr *ia)
1571{
1572 LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1573 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1574
1575 if (ia->ia_addr.sin_family != AF_INET) {
1576 panic("attempt to insert wrong ia %p into hash table", ia);
1577 /* NOTREACHED */
1578 } else if (IA_IS_HASHED(ia)) {
1579 panic("attempt to double-insert ia %p into hash table", ia);
1580 /* NOTREACHED */
1581 }
1582 TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1583 ia, ia_hash);
1584 ifa_addref(ifa: &ia->ia_ifa);
1585}
1586
1587/*
1588 * Some point to point interfaces that are tunnels borrow the address from
1589 * an underlying interface (e.g. VPN server). In order for source address
1590 * selection logic to find the underlying interface first, we add the address
1591 * of borrowing point to point interfaces at the end of the list.
1592 * (see rdar://6733789)
1593 *
1594 * Caller must hold in_ifaddr_rwlock as writer.
1595 */
1596static void
1597in_iahash_insert_ptp(struct in_ifaddr *ia)
1598{
1599 struct in_ifaddr *tmp_ifa;
1600 struct ifnet *tmp_ifp;
1601
1602 LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1603 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1604
1605 if (ia->ia_addr.sin_family != AF_INET) {
1606 panic("attempt to insert wrong ia %p into hash table", ia);
1607 /* NOTREACHED */
1608 } else if (IA_IS_HASHED(ia)) {
1609 panic("attempt to double-insert ia %p into hash table", ia);
1610 /* NOTREACHED */
1611 }
1612 IFA_UNLOCK(&ia->ia_ifa);
1613 TAILQ_FOREACH(tmp_ifa, INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1614 ia_hash) {
1615 IFA_LOCK(&tmp_ifa->ia_ifa);
1616 /* ia->ia_addr won't change, so check without lock */
1617 if (IA_SIN(tmp_ifa)->sin_addr.s_addr ==
1618 ia->ia_addr.sin_addr.s_addr) {
1619 IFA_UNLOCK(&tmp_ifa->ia_ifa);
1620 break;
1621 }
1622 IFA_UNLOCK(&tmp_ifa->ia_ifa);
1623 }
1624 tmp_ifp = (tmp_ifa == NULL) ? NULL : tmp_ifa->ia_ifp;
1625
1626 IFA_LOCK(&ia->ia_ifa);
1627 if (tmp_ifp == NULL) {
1628 TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1629 ia, ia_hash);
1630 } else {
1631 TAILQ_INSERT_TAIL(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1632 ia, ia_hash);
1633 }
1634 ifa_addref(ifa: &ia->ia_ifa);
1635}
1636
1637/*
1638 * Initialize an interface's internet address
1639 * and routing table entry.
1640 */
1641static int
1642in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
1643 int scrub)
1644{
1645 u_int32_t i = ntohl(sin->sin_addr.s_addr);
1646 struct sockaddr_in oldaddr;
1647 int flags = RTF_UP, error;
1648 struct ifaddr *ifa0;
1649 unsigned int cmd;
1650 int oldremoved = 0;
1651
1652 /* Take an extra reference for this routine */
1653 ifa_addref(ifa: &ia->ia_ifa);
1654
1655 lck_rw_lock_exclusive(lck: &in_ifaddr_rwlock);
1656 IFA_LOCK(&ia->ia_ifa);
1657 oldaddr = ia->ia_addr;
1658 if (IA_IS_HASHED(ia)) {
1659 oldremoved = 1;
1660 in_iahash_remove(ia);
1661 }
1662 ia->ia_addr = *sin;
1663 /*
1664 * Interface addresses should not contain port or sin_zero information.
1665 */
1666 SIN(&ia->ia_addr)->sin_family = AF_INET;
1667 SIN(&ia->ia_addr)->sin_len = sizeof(struct sockaddr_in);
1668 SIN(&ia->ia_addr)->sin_port = 0;
1669 bzero(s: &SIN(&ia->ia_addr)->sin_zero, n: sizeof(sin->sin_zero));
1670 if ((ifp->if_flags & IFF_POINTOPOINT)) {
1671 in_iahash_insert_ptp(ia);
1672 } else {
1673 in_iahash_insert(ia);
1674 }
1675 IFA_UNLOCK(&ia->ia_ifa);
1676 lck_rw_done(lck: &in_ifaddr_rwlock);
1677
1678 /*
1679 * Give the interface a chance to initialize if this is its first
1680 * address, and to validate the address if necessary. Send down
1681 * SIOCSIFADDR for first address, and SIOCAIFADDR for alias(es).
1682 * We find the first IPV4 address assigned to it and check if this
1683 * is the same as the one passed into this routine.
1684 */
1685 ifa0 = ifa_ifpgetprimary(ifp, AF_INET);
1686 cmd = (&ia->ia_ifa == ifa0) ? SIOCSIFADDR : SIOCAIFADDR;
1687 error = ifnet_ioctl(interface: ifp, PF_INET, ioctl_code: cmd, ioctl_arg: ia);
1688 if (error == EOPNOTSUPP) {
1689 error = 0;
1690 }
1691 /*
1692 * If we've just sent down SIOCAIFADDR, send another ioctl down
1693 * for SIOCSIFADDR for the first IPV4 address of the interface,
1694 * because an address change on one of the addresses will result
1695 * in the removal of the previous first IPV4 address. KDP needs
1696 * be reconfigured with the current primary IPV4 address.
1697 */
1698 if (error == 0 && cmd == SIOCAIFADDR) {
1699 /*
1700 * NOTE: SIOCSIFADDR is defined with struct ifreq
1701 * as parameter, but here we are sending it down
1702 * to the interface with a pointer to struct ifaddr,
1703 * for legacy reasons.
1704 */
1705 error = ifnet_ioctl(interface: ifp, PF_INET, SIOCSIFADDR, ioctl_arg: ifa0);
1706 if (error == EOPNOTSUPP) {
1707 error = 0;
1708 }
1709 }
1710
1711 /* Release reference from ifa_ifpgetprimary() */
1712 ifa_remref(ifa: ifa0);
1713
1714 if (error) {
1715 lck_rw_lock_exclusive(lck: &in_ifaddr_rwlock);
1716 IFA_LOCK(&ia->ia_ifa);
1717 if (IA_IS_HASHED(ia)) {
1718 in_iahash_remove(ia);
1719 }
1720 ia->ia_addr = oldaddr;
1721 if (oldremoved) {
1722 if ((ifp->if_flags & IFF_POINTOPOINT)) {
1723 in_iahash_insert_ptp(ia);
1724 } else {
1725 in_iahash_insert(ia);
1726 }
1727 }
1728 IFA_UNLOCK(&ia->ia_ifa);
1729 lck_rw_done(lck: &in_ifaddr_rwlock);
1730 /* Release extra reference taken above */
1731 ifa_remref(ifa: &ia->ia_ifa);
1732 return error;
1733 }
1734 lck_mtx_lock(rnh_lock);
1735 IFA_LOCK(&ia->ia_ifa);
1736 /*
1737 * Address has been initialized by the link resolver (ARP)
1738 * via ifnet_ioctl() above; it may now generate route(s).
1739 */
1740 ia->ia_ifa.ifa_debug &= ~IFD_NOTREADY;
1741 if (scrub) {
1742 ia->ia_ifa.ifa_addr = SA(&oldaddr);
1743 IFA_UNLOCK(&ia->ia_ifa);
1744 in_ifscrub(ifp, ia, locked: 1);
1745 IFA_LOCK(&ia->ia_ifa);
1746 ia->ia_ifa.ifa_addr = SA(&ia->ia_addr);
1747 }
1748 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1749 if (IN_CLASSA(i)) {
1750 ia->ia_netmask = IN_CLASSA_NET;
1751 } else if (IN_CLASSB(i)) {
1752 ia->ia_netmask = IN_CLASSB_NET;
1753 } else {
1754 ia->ia_netmask = IN_CLASSC_NET;
1755 }
1756 /*
1757 * The subnet mask usually includes at least the standard network part,
1758 * but may may be smaller in the case of supernetting.
1759 * If it is set, we believe it.
1760 */
1761 if (ia->ia_subnetmask == 0) {
1762 ia->ia_subnetmask = ia->ia_netmask;
1763 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
1764 } else {
1765 ia->ia_netmask &= ia->ia_subnetmask;
1766 }
1767 ia->ia_net = i & ia->ia_netmask;
1768 ia->ia_subnet = i & ia->ia_subnetmask;
1769 in_socktrim(ap: &ia->ia_sockmask);
1770 /*
1771 * Add route for the network.
1772 */
1773 ia->ia_ifa.ifa_metric = ifp->if_metric;
1774 if (ifp->if_flags & IFF_BROADCAST) {
1775 ia->ia_broadaddr.sin_addr.s_addr =
1776 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
1777 ia->ia_netbroadcast.s_addr =
1778 htonl(ia->ia_net | ~ia->ia_netmask);
1779 } else if (ifp->if_flags & IFF_LOOPBACK) {
1780 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1781 flags |= RTF_HOST;
1782 } else if (ifp->if_flags & IFF_POINTOPOINT) {
1783 if (ia->ia_dstaddr.sin_family != AF_INET) {
1784 IFA_UNLOCK(&ia->ia_ifa);
1785 lck_mtx_unlock(rnh_lock);
1786 /* Release extra reference taken above */
1787 ifa_remref(ifa: &ia->ia_ifa);
1788 return 0;
1789 }
1790 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
1791 flags |= RTF_HOST;
1792 }
1793 IFA_UNLOCK(&ia->ia_ifa);
1794
1795 if ((error = rtinit_locked(&(ia->ia_ifa), RTM_ADD, flags)) == 0) {
1796 IFA_LOCK(&ia->ia_ifa);
1797 ia->ia_flags |= IFA_ROUTE;
1798 IFA_UNLOCK(&ia->ia_ifa);
1799 }
1800 lck_mtx_unlock(rnh_lock);
1801
1802 /* XXX check if the subnet route points to the same interface */
1803 if (error == EEXIST) {
1804 error = 0;
1805 }
1806
1807 /*
1808 * If the interface supports multicast, join the "all hosts"
1809 * multicast group on that interface.
1810 */
1811 if (ifp->if_flags & IFF_MULTICAST) {
1812 struct in_addr addr;
1813
1814 lck_mtx_lock(lck: &ifp->if_addrconfig_lock);
1815 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
1816 if (ifp->if_allhostsinm == NULL) {
1817 struct in_multi *inm;
1818 inm = in_addmulti(&addr, ifp);
1819
1820 if (inm != NULL) {
1821 /*
1822 * Keep the reference on inm added by
1823 * in_addmulti above for storing the
1824 * pointer in allhostsinm.
1825 */
1826 ifp->if_allhostsinm = inm;
1827 } else {
1828 printf("%s: failed to add membership to "
1829 "all-hosts multicast address on %s\n",
1830 __func__, if_name(ifp));
1831 }
1832 }
1833 lck_mtx_unlock(lck: &ifp->if_addrconfig_lock);
1834 }
1835
1836 /* Release extra reference taken above */
1837 ifa_remref(ifa: &ia->ia_ifa);
1838
1839 if (error == 0) {
1840 /* invalidate route caches */
1841 routegenid_inet_update();
1842 }
1843
1844 return error;
1845}
1846
1847/*
1848 * Return TRUE if the address might be a local broadcast address.
1849 */
1850boolean_t
1851in_broadcast(struct in_addr in, struct ifnet *ifp)
1852{
1853 struct ifaddr *ifa;
1854 u_int32_t t;
1855
1856 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) {
1857 return TRUE;
1858 }
1859 if (!(ifp->if_flags & IFF_BROADCAST)) {
1860 return FALSE;
1861 }
1862 t = ntohl(in.s_addr);
1863
1864 /*
1865 * Look through the list of addresses for a match
1866 * with a broadcast address.
1867 */
1868#define ia ((struct in_ifaddr *)ifa)
1869 ifnet_lock_shared(ifp);
1870 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1871 IFA_LOCK(ifa);
1872 if (ifa->ifa_addr->sa_family == AF_INET &&
1873 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
1874 in.s_addr == ia->ia_netbroadcast.s_addr ||
1875 /*
1876 * Check for old-style (host 0) broadcast.
1877 */
1878 t == ia->ia_subnet || t == ia->ia_net) &&
1879 /*
1880 * Check for an all one subnetmask. These
1881 * only exist when an interface gets a secondary
1882 * address.
1883 */
1884 ia->ia_subnetmask != (u_int32_t)0xffffffff) {
1885 IFA_UNLOCK(ifa);
1886 ifnet_lock_done(ifp);
1887 return TRUE;
1888 }
1889 IFA_UNLOCK(ifa);
1890 }
1891 ifnet_lock_done(ifp);
1892 return FALSE;
1893#undef ia
1894}
1895
1896void
1897in_purgeaddrs(struct ifnet *ifp)
1898{
1899 struct ifaddr **ifap;
1900 int err, i;
1901
1902 VERIFY(ifp != NULL);
1903
1904 /*
1905 * Be nice, and try the civilized way first. If we can't get
1906 * rid of them this way, then do it the rough way. We must
1907 * only get here during detach time, after the ifnet has been
1908 * removed from the global list and arrays.
1909 */
1910 err = ifnet_get_address_list_family_internal(ifp, &ifap, AF_INET, 1,
1911 M_WAITOK, 0);
1912 if (err == 0 && ifap != NULL) {
1913 struct ifreq ifr;
1914
1915 bzero(s: &ifr, n: sizeof(ifr));
1916 (void) snprintf(ifr.ifr_name, count: sizeof(ifr.ifr_name),
1917 "%s", if_name(ifp));
1918
1919 for (i = 0; ifap[i] != NULL; i++) {
1920 struct ifaddr *ifa;
1921
1922 ifa = ifap[i];
1923 IFA_LOCK(ifa);
1924 SOCKADDR_COPY(ifa->ifa_addr, &ifr.ifr_addr,
1925 sizeof(struct sockaddr_in));
1926 IFA_UNLOCK(ifa);
1927 err = in_control(NULL, SIOCDIFADDR, data: (caddr_t)&ifr, ifp,
1928 p: kernproc);
1929 /* if we lost the race, ignore it */
1930 if (err == EADDRNOTAVAIL) {
1931 err = 0;
1932 }
1933 if (err != 0) {
1934 char s_addr[MAX_IPv4_STR_LEN];
1935 char s_dstaddr[MAX_IPv4_STR_LEN];
1936 struct in_addr *s, *d;
1937
1938 IFA_LOCK(ifa);
1939 s = &SIN(ifa->ifa_addr)->sin_addr;
1940 d = &SIN(ifa->ifa_dstaddr)->sin_addr;
1941 (void) inet_ntop(AF_INET, &s->s_addr, s_addr,
1942 sizeof(s_addr));
1943 (void) inet_ntop(AF_INET, &d->s_addr, s_dstaddr,
1944 sizeof(s_dstaddr));
1945 IFA_UNLOCK(ifa);
1946
1947 printf("%s: SIOCDIFADDR ifp=%s ifa_addr=%s "
1948 "ifa_dstaddr=%s (err=%d)\n", __func__,
1949 ifp->if_xname, s_addr, s_dstaddr, err);
1950 }
1951 }
1952 ifnet_free_address_list(addresses: ifap);
1953 } else if (err != 0 && err != ENXIO) {
1954 printf("%s: error retrieving list of AF_INET addresses for "
1955 "ifp=%s (err=%d)\n", __func__, ifp->if_xname, err);
1956 }
1957}
1958
1959static struct in_ifaddr *
1960in_ifaddr_alloc(void)
1961{
1962 struct in_ifaddr *inifa;
1963
1964 inifa = kalloc_type(struct in_ifaddr, Z_ZERO | Z_WAITOK);
1965 if (inifa == NULL) {
1966 return NULL;
1967 }
1968
1969 inifa->ia_ifa.ifa_free = in_ifaddr_free;
1970 inifa->ia_ifa.ifa_debug |= IFD_ALLOC;
1971 inifa->ia_ifa.ifa_del_wc = &inifa->ia_ifa.ifa_debug;
1972 inifa->ia_ifa.ifa_del_waiters = 0;
1973 ifa_lock_init(&inifa->ia_ifa);
1974 ifa_initref(&inifa->ia_ifa);
1975
1976 return inifa;
1977}
1978
1979static void
1980in_ifaddr_free(struct ifaddr *ifa)
1981{
1982 struct in_ifaddr *inifa = (struct in_ifaddr *)ifa;
1983
1984 IFA_LOCK_ASSERT_HELD(ifa);
1985
1986 if (__improbable(!(ifa->ifa_debug & IFD_ALLOC))) {
1987 panic("%s: ifa %p cannot be freed", __func__, ifa);
1988 /* NOTREACHED */
1989 }
1990 IFA_UNLOCK(ifa);
1991 ifa_lock_destroy(ifa);
1992
1993 kfree_type(struct in_ifaddr, inifa);
1994}
1995
1996/*
1997 * Handle SIOCGASSOCIDS ioctl for PF_INET domain.
1998 */
1999static int
2000in_getassocids(struct socket *so, uint32_t *cnt, user_addr_t aidp)
2001{
2002 struct inpcb *inp = sotoinpcb(so);
2003 sae_associd_t aid;
2004
2005 if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) {
2006 return EINVAL;
2007 }
2008
2009 /* INPCB has no concept of association */
2010 aid = SAE_ASSOCID_ANY;
2011 *cnt = 0;
2012
2013 /* just asking how many there are? */
2014 if (aidp == USER_ADDR_NULL) {
2015 return 0;
2016 }
2017
2018 return copyout(&aid, aidp, sizeof(aid));
2019}
2020
2021/*
2022 * Handle SIOCGCONNIDS ioctl for PF_INET domain.
2023 */
2024static int
2025in_getconnids(struct socket *so, sae_associd_t aid, uint32_t *cnt,
2026 user_addr_t cidp)
2027{
2028 struct inpcb *inp = sotoinpcb(so);
2029 sae_connid_t cid;
2030
2031 if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) {
2032 return EINVAL;
2033 }
2034
2035 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL) {
2036 return EINVAL;
2037 }
2038
2039 /* if connected, return 1 connection count */
2040 *cnt = ((so->so_state & SS_ISCONNECTED) ? 1 : 0);
2041
2042 /* just asking how many there are? */
2043 if (cidp == USER_ADDR_NULL) {
2044 return 0;
2045 }
2046
2047 /* if INPCB is connected, assign it connid 1 */
2048 cid = ((*cnt != 0) ? 1 : SAE_CONNID_ANY);
2049
2050 return copyout(&cid, cidp, sizeof(cid));
2051}
2052
2053/*
2054 * Handle SIOCGCONNINFO ioctl for PF_INET domain.
2055 */
2056int
2057in_getconninfo(struct socket *so, sae_connid_t cid, uint32_t *flags,
2058 uint32_t *ifindex, int32_t *soerror, user_addr_t src, socklen_t *src_len,
2059 user_addr_t dst, socklen_t *dst_len, uint32_t *aux_type,
2060 user_addr_t aux_data, uint32_t *aux_len)
2061{
2062 struct inpcb *inp = sotoinpcb(so);
2063 struct sockaddr_in sin;
2064 struct ifnet *ifp = NULL;
2065 int error = 0;
2066 u_int32_t copy_len = 0;
2067
2068 /*
2069 * Don't test for INPCB_STATE_DEAD since this may be called
2070 * after SOF_PCBCLEARING is set, e.g. after tcp_close().
2071 */
2072 if (inp == NULL) {
2073 error = EINVAL;
2074 goto out;
2075 }
2076
2077 if (cid != SAE_CONNID_ANY && cid != SAE_CONNID_ALL && cid != 1) {
2078 error = EINVAL;
2079 goto out;
2080 }
2081
2082 ifp = inp->inp_last_outifp;
2083 *ifindex = ((ifp != NULL) ? ifp->if_index : 0);
2084 *soerror = so->so_error;
2085 *flags = 0;
2086 if (so->so_state & SS_ISCONNECTED) {
2087 *flags |= (CIF_CONNECTED | CIF_PREFERRED);
2088 }
2089 if (inp->inp_flags & INP_BOUND_IF) {
2090 *flags |= CIF_BOUND_IF;
2091 }
2092 if (!(inp->inp_flags & INP_INADDR_ANY)) {
2093 *flags |= CIF_BOUND_IP;
2094 }
2095 if (!(inp->inp_flags & INP_ANONPORT)) {
2096 *flags |= CIF_BOUND_PORT;
2097 }
2098
2099 SOCKADDR_ZERO(&sin, sizeof(sin));
2100 sin.sin_len = sizeof(sin);
2101 sin.sin_family = AF_INET;
2102
2103 /* source address and port */
2104 sin.sin_port = inp->inp_lport;
2105 sin.sin_addr.s_addr = inp->inp_laddr.s_addr;
2106 if (*src_len == 0) {
2107 *src_len = sin.sin_len;
2108 } else {
2109 if (src != USER_ADDR_NULL) {
2110 copy_len = min(a: *src_len, b: sizeof(sin));
2111 error = copyout(&sin, src, copy_len);
2112 if (error != 0) {
2113 goto out;
2114 }
2115 *src_len = copy_len;
2116 }
2117 }
2118
2119 /* destination address and port */
2120 sin.sin_port = inp->inp_fport;
2121 sin.sin_addr.s_addr = inp->inp_faddr.s_addr;
2122 if (*dst_len == 0) {
2123 *dst_len = sin.sin_len;
2124 } else {
2125 if (dst != USER_ADDR_NULL) {
2126 copy_len = min(a: *dst_len, b: sizeof(sin));
2127 error = copyout(&sin, dst, copy_len);
2128 if (error != 0) {
2129 goto out;
2130 }
2131 *dst_len = copy_len;
2132 }
2133 }
2134
2135 if (SOCK_PROTO(so) == IPPROTO_TCP) {
2136 struct conninfo_tcp tcp_ci;
2137
2138 *aux_type = CIAUX_TCP;
2139 if (*aux_len == 0) {
2140 *aux_len = sizeof(tcp_ci);
2141 } else {
2142 if (aux_data != USER_ADDR_NULL) {
2143 copy_len = min(a: *aux_len, b: sizeof(tcp_ci));
2144 bzero(s: &tcp_ci, n: sizeof(tcp_ci));
2145 tcp_getconninfo(so, &tcp_ci);
2146 error = copyout(&tcp_ci, aux_data, copy_len);
2147 if (error != 0) {
2148 goto out;
2149 }
2150 *aux_len = copy_len;
2151 }
2152 }
2153 } else {
2154 *aux_type = 0;
2155 *aux_len = 0;
2156 }
2157
2158out:
2159 return error;
2160}
2161
2162struct in_ifaddr*
2163inifa_ifpwithflag(struct ifnet * ifp, uint32_t flag)
2164{
2165 struct ifaddr *ifa;
2166
2167 ifnet_lock_shared(ifp);
2168 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_link)
2169 {
2170 IFA_LOCK_SPIN(ifa);
2171 if (ifa->ifa_addr->sa_family != AF_INET) {
2172 IFA_UNLOCK(ifa);
2173 continue;
2174 }
2175 if ((((struct in_ifaddr *)ifa)->ia_flags & flag) == flag) {
2176 ifa_addref(ifa);
2177 IFA_UNLOCK(ifa);
2178 break;
2179 }
2180 IFA_UNLOCK(ifa);
2181 }
2182 ifnet_lock_done(ifp);
2183
2184 return (struct in_ifaddr *)ifa;
2185}
2186
2187struct in_ifaddr *
2188inifa_ifpclatv4(struct ifnet * ifp)
2189{
2190 struct ifaddr *ifa;
2191
2192 ifnet_lock_shared(ifp);
2193 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_link)
2194 {
2195 uint32_t addr = 0;
2196 IFA_LOCK_SPIN(ifa);
2197 if (ifa->ifa_addr->sa_family != AF_INET) {
2198 IFA_UNLOCK(ifa);
2199 continue;
2200 }
2201
2202 addr = ntohl(SIN(ifa->ifa_addr)->sin_addr.s_addr);
2203 if (!IN_LINKLOCAL(addr) &&
2204 !IN_LOOPBACK(addr)) {
2205 ifa_addref(ifa);
2206 IFA_UNLOCK(ifa);
2207 break;
2208 }
2209 IFA_UNLOCK(ifa);
2210 }
2211 ifnet_lock_done(ifp);
2212
2213 return (struct in_ifaddr *)ifa;
2214}
2215
2216/*
2217 * IPPROTO_xxx.
2218 *
2219 * The switch statement below does nothing at runtime, as it serves as a
2220 * compile time check to ensure that all of the IPPROTO_xxx constants are
2221 * unique. This works as long as this routine gets updated each time a
2222 * new IPPROTO_xxx constant gets added.
2223 *
2224 * Any failures at compile time indicates duplicated IPPROTO_xxx values.
2225 */
2226static __attribute__((unused)) void
2227ipproto_cassert(void)
2228{
2229 /*
2230 * This is equivalent to _CASSERT() and the compiler wouldn't
2231 * generate any instructions, thus for compile time only.
2232 */
2233 switch ((u_int16_t)0) {
2234 /* bsd/netinet/in.h */
2235 case IPPROTO_IP:
2236// case IPPROTO_HOPOPTS: // same value as IPPROTO_IP
2237 case IPPROTO_ICMP:
2238 case IPPROTO_IGMP:
2239 case IPPROTO_GGP:
2240 case IPPROTO_IPV4:
2241 // #define IPPROTO_IPIP IPPROTO_IPV4
2242 case IPPROTO_TCP:
2243 case IPPROTO_ST:
2244 case IPPROTO_EGP:
2245 case IPPROTO_PIGP:
2246 case IPPROTO_RCCMON:
2247 case IPPROTO_NVPII:
2248 case IPPROTO_PUP:
2249 case IPPROTO_ARGUS:
2250 case IPPROTO_EMCON:
2251 case IPPROTO_XNET:
2252 case IPPROTO_CHAOS:
2253 case IPPROTO_UDP:
2254 case IPPROTO_MUX:
2255 case IPPROTO_MEAS:
2256 case IPPROTO_HMP:
2257 case IPPROTO_PRM:
2258 case IPPROTO_IDP:
2259 case IPPROTO_TRUNK1:
2260 case IPPROTO_TRUNK2:
2261 case IPPROTO_LEAF1:
2262 case IPPROTO_LEAF2:
2263 case IPPROTO_RDP:
2264 case IPPROTO_IRTP:
2265 case IPPROTO_TP:
2266 case IPPROTO_BLT:
2267 case IPPROTO_NSP:
2268 case IPPROTO_INP:
2269 case IPPROTO_SEP:
2270 case IPPROTO_3PC:
2271 case IPPROTO_IDPR:
2272 case IPPROTO_XTP:
2273 case IPPROTO_DDP:
2274 case IPPROTO_CMTP:
2275 case IPPROTO_TPXX:
2276 case IPPROTO_IL:
2277 case IPPROTO_IPV6:
2278 case IPPROTO_SDRP:
2279 case IPPROTO_ROUTING:
2280 case IPPROTO_FRAGMENT:
2281 case IPPROTO_IDRP:
2282 case IPPROTO_RSVP:
2283 case IPPROTO_GRE:
2284 case IPPROTO_MHRP:
2285 case IPPROTO_BHA:
2286 case IPPROTO_ESP:
2287 case IPPROTO_AH:
2288 case IPPROTO_INLSP:
2289 case IPPROTO_SWIPE:
2290 case IPPROTO_NHRP:
2291 case IPPROTO_ICMPV6:
2292 case IPPROTO_NONE:
2293 case IPPROTO_DSTOPTS:
2294 case IPPROTO_AHIP:
2295 case IPPROTO_CFTP:
2296 case IPPROTO_HELLO:
2297 case IPPROTO_SATEXPAK:
2298 case IPPROTO_KRYPTOLAN:
2299 case IPPROTO_RVD:
2300 case IPPROTO_IPPC:
2301 case IPPROTO_ADFS:
2302 case IPPROTO_SATMON:
2303 case IPPROTO_VISA:
2304 case IPPROTO_IPCV:
2305 case IPPROTO_CPNX:
2306 case IPPROTO_CPHB:
2307 case IPPROTO_WSN:
2308 case IPPROTO_PVP:
2309 case IPPROTO_BRSATMON:
2310 case IPPROTO_ND:
2311 case IPPROTO_WBMON:
2312 case IPPROTO_WBEXPAK:
2313 case IPPROTO_EON:
2314 case IPPROTO_VMTP:
2315 case IPPROTO_SVMTP:
2316 case IPPROTO_VINES:
2317 case IPPROTO_TTP:
2318 case IPPROTO_IGP:
2319 case IPPROTO_DGP:
2320 case IPPROTO_TCF:
2321 case IPPROTO_IGRP:
2322 case IPPROTO_OSPFIGP:
2323 case IPPROTO_SRPC:
2324 case IPPROTO_LARP:
2325 case IPPROTO_MTP:
2326 case IPPROTO_AX25:
2327 case IPPROTO_IPEIP:
2328 case IPPROTO_MICP:
2329 case IPPROTO_SCCSP:
2330 case IPPROTO_ETHERIP:
2331 case IPPROTO_ENCAP:
2332 case IPPROTO_APES:
2333 case IPPROTO_GMTP:
2334 case IPPROTO_PIM:
2335 case IPPROTO_IPCOMP:
2336 case IPPROTO_PGM:
2337 case IPPROTO_SCTP:
2338 case IPPROTO_DIVERT:
2339 case IPPROTO_RAW:
2340 case IPPROTO_MAX:
2341 case IPPROTO_DONE:
2342
2343 /* bsd/netinet/in_private.h */
2344 case IPPROTO_QUIC:
2345 ;
2346 }
2347}
2348
2349static __attribute__((unused)) void
2350ipsockopt_cassert(void)
2351{
2352 switch ((int)0) {
2353 case 0:
2354
2355 /* bsd/netinet/in.h */
2356 case IP_OPTIONS:
2357 case IP_HDRINCL:
2358 case IP_TOS:
2359 case IP_TTL:
2360 case IP_RECVOPTS:
2361 case IP_RECVRETOPTS:
2362 case IP_RECVDSTADDR:
2363 case IP_RETOPTS:
2364 case IP_MULTICAST_IF:
2365 case IP_MULTICAST_TTL:
2366 case IP_MULTICAST_LOOP:
2367 case IP_ADD_MEMBERSHIP:
2368 case IP_DROP_MEMBERSHIP:
2369 case IP_MULTICAST_VIF:
2370 case IP_RSVP_ON:
2371 case IP_RSVP_OFF:
2372 case IP_RSVP_VIF_ON:
2373 case IP_RSVP_VIF_OFF:
2374 case IP_PORTRANGE:
2375 case IP_RECVIF:
2376 case IP_IPSEC_POLICY:
2377 case IP_FAITH:
2378#ifdef __APPLE__
2379 case IP_STRIPHDR:
2380#endif
2381 case IP_RECVTTL:
2382 case IP_BOUND_IF:
2383 case IP_PKTINFO:
2384// #define IP_RECVPKTINFO IP_PKTINFO
2385 case IP_RECVTOS:
2386 case IP_DONTFRAG:
2387 case IP_FW_ADD:
2388 case IP_FW_DEL:
2389 case IP_FW_FLUSH:
2390 case IP_FW_ZERO:
2391 case IP_FW_GET:
2392 case IP_FW_RESETLOG:
2393 case IP_OLD_FW_ADD:
2394 case IP_OLD_FW_DEL:
2395 case IP_OLD_FW_FLUSH:
2396 case IP_OLD_FW_ZERO:
2397 case IP_OLD_FW_GET:
2398 case IP_NAT__XXX:
2399 case IP_OLD_FW_RESETLOG:
2400 case IP_DUMMYNET_CONFIGURE:
2401 case IP_DUMMYNET_DEL:
2402 case IP_DUMMYNET_FLUSH:
2403 case IP_DUMMYNET_GET:
2404 case IP_TRAFFIC_MGT_BACKGROUND:
2405 case IP_MULTICAST_IFINDEX:
2406 case IP_ADD_SOURCE_MEMBERSHIP:
2407 case IP_DROP_SOURCE_MEMBERSHIP:
2408 case IP_BLOCK_SOURCE:
2409 case IP_UNBLOCK_SOURCE:
2410 case IP_MSFILTER:
2411 case MCAST_JOIN_GROUP:
2412 case MCAST_LEAVE_GROUP:
2413 case MCAST_JOIN_SOURCE_GROUP:
2414 case MCAST_LEAVE_SOURCE_GROUP:
2415 case MCAST_BLOCK_SOURCE:
2416 case MCAST_UNBLOCK_SOURCE:
2417
2418 /* bsd/netinet/in_private.h */
2419 case IP_NO_IFT_CELLULAR:
2420// #define IP_NO_IFT_PDP IP_NO_IFT_CELLULAR /* deprecated */
2421 case IP_OUT_IF:
2422 ;
2423 }
2424}
2425