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 #include <net/if_llatbl.h>
88 #include <net/if_arp.h>
89 #if PF
90 #include <net/pfvar.h>
91 #endif /* PF */
92
93 #include <netinet/in.h>
94 #include <netinet/in_var.h>
95 #include <netinet/in_pcb.h>
96 #include <netinet/igmp_var.h>
97 #include <netinet/ip_var.h>
98 #include <netinet/tcp.h>
99 #include <netinet/tcp_timer.h>
100 #include <netinet/tcp_var.h>
101 #include <netinet/if_ether.h>
102
103 static int inctl_associd(struct socket *, u_long, caddr_t);
104 static int inctl_connid(struct socket *, u_long, caddr_t);
105 static int inctl_conninfo(struct socket *, u_long, caddr_t);
106 static int inctl_autoaddr(struct ifnet *, struct ifreq *);
107 static int inctl_arpipll(struct ifnet *, struct ifreq *);
108 static int inctl_setrouter(struct ifnet *, struct ifreq *);
109 static int inctl_ifaddr(struct ifnet *, struct in_ifaddr *, u_long,
110 struct ifreq *);
111 static int inctl_ifdstaddr(struct ifnet *, struct in_ifaddr *, u_long,
112 struct ifreq *);
113 static int inctl_ifbrdaddr(struct ifnet *, struct in_ifaddr *, u_long,
114 struct ifreq *);
115 static int inctl_ifnetmask(struct ifnet *, struct in_ifaddr *, u_long,
116 struct ifreq *);
117
118 static void in_socktrim(struct sockaddr_in *);
119 static int in_ifinit(struct ifnet *, struct in_ifaddr *,
120 struct sockaddr_in *, int);
121
122 #define IA_HASH_INIT(ia) { \
123 (ia)->ia_hash.tqe_next = (void *)(uintptr_t)-1; \
124 (ia)->ia_hash.tqe_prev = (void *)(uintptr_t)-1; \
125 }
126
127 #define IA_IS_HASHED(ia) \
128 (!((ia)->ia_hash.tqe_next == (void *)(uintptr_t)-1 || \
129 (ia)->ia_hash.tqe_prev == (void *)(uintptr_t)-1))
130
131 static void in_iahash_remove(struct in_ifaddr *);
132 static void in_iahash_insert(struct in_ifaddr *);
133 static void in_iahash_insert_ptp(struct in_ifaddr *);
134 static struct in_ifaddr *in_ifaddr_alloc(zalloc_flags_t);
135 static void in_ifaddr_attached(struct ifaddr *);
136 static void in_ifaddr_detached(struct ifaddr *);
137 static void in_ifaddr_free(struct ifaddr *);
138 static void in_ifaddr_trace(struct ifaddr *, int);
139
140 static int in_getassocids(struct socket *, uint32_t *, user_addr_t);
141 static int in_getconnids(struct socket *, sae_associd_t, uint32_t *, user_addr_t);
142
143 /* IPv4 Layer 2 neighbor cache management routines */
144 static void in_lltable_destroy_lle_unlocked(struct llentry *lle);
145 static void in_lltable_destroy_lle(struct llentry *lle);
146 static struct llentry *in_lltable_new(struct in_addr addr4, uint16_t flags);
147 static int in_lltable_match_prefix(const struct sockaddr *saddr,
148 const struct sockaddr *smask, uint16_t flags, struct llentry *lle);
149 static void in_lltable_free_entry(struct lltable *llt, struct llentry *lle);
150 static int in_lltable_rtcheck(struct ifnet *ifp, uint16_t flags, const struct sockaddr *l3addr);
151 static inline uint32_t in_lltable_hash_dst(const struct in_addr dst, uint32_t hsize);
152 static uint32_t in_lltable_hash(const struct llentry *lle, uint32_t hsize);
153 static void in_lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa);
154 static inline struct llentry * in_lltable_find_dst(struct lltable *llt, struct in_addr dst);
155 static void in_lltable_delete_entry(struct lltable *llt, struct llentry *lle);
156 static struct llentry * in_lltable_alloc(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr);
157 static struct llentry * in_lltable_lookup(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr);
158 static int in_lltable_dump_entry(struct lltable *llt, struct llentry *lle, struct sysctl_req *wr);
159 static struct lltable * in_lltattach(struct ifnet *ifp);
160
161 static int subnetsarelocal = 0;
162 SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local,
163 CTLFLAG_RW | CTLFLAG_LOCKED, &subnetsarelocal, 0, "");
164
165 /* Track whether or not the SIOCARPIPLL ioctl has been called */
166 u_int32_t ipv4_ll_arp_aware = 0;
167
168 #define INIFA_TRACE_HIST_SIZE 32 /* size of trace history */
169
170 /* For gdb */
171 __private_extern__ unsigned int inifa_trace_hist_size = INIFA_TRACE_HIST_SIZE;
172
173 struct in_ifaddr_dbg {
174 struct in_ifaddr inifa; /* in_ifaddr */
175 struct in_ifaddr inifa_old; /* saved in_ifaddr */
176 u_int16_t inifa_refhold_cnt; /* # of IFA_ADDREF */
177 u_int16_t inifa_refrele_cnt; /* # of IFA_REMREF */
178 /*
179 * Alloc and free callers.
180 */
181 ctrace_t inifa_alloc;
182 ctrace_t inifa_free;
183 /*
184 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
185 */
186 ctrace_t inifa_refhold[INIFA_TRACE_HIST_SIZE];
187 ctrace_t inifa_refrele[INIFA_TRACE_HIST_SIZE];
188 /*
189 * Trash list linkage
190 */
191 TAILQ_ENTRY(in_ifaddr_dbg) inifa_trash_link;
192 };
193
194 /* List of trash in_ifaddr entries protected by inifa_trash_lock */
195 static TAILQ_HEAD(, in_ifaddr_dbg) inifa_trash_head;
196 static LCK_MTX_DECLARE_ATTR(inifa_trash_lock, &ifa_mtx_grp, &ifa_mtx_attr);
197
198 #if DEBUG
199 static TUNABLE(bool, inifa_debug, "ifa_debug", true); /* debugging (enabled) */
200 #else
201 static TUNABLE(bool, inifa_debug, "ifa_debug", false); /* debugging (disabled) */
202 #endif /* !DEBUG */
203 static struct zone *inifa_zone; /* zone for in_ifaddr */
204
205 #define INIFA_ZONE_NAME "in_ifaddr" /* zone name */
206
207 /*
208 * Return 1 if the address is
209 * - loopback
210 * - unicast or multicast link local
211 * - routed via a link level gateway
212 * - belongs to a directly connected (sub)net
213 */
214 int
inaddr_local(struct in_addr in)215 inaddr_local(struct in_addr in)
216 {
217 struct rtentry *rt;
218 struct sockaddr_in sin;
219 int local = 0;
220
221 if (ntohl(in.s_addr) == INADDR_LOOPBACK ||
222 IN_LINKLOCAL(ntohl(in.s_addr))) {
223 local = 1;
224 } else if (ntohl(in.s_addr) >= INADDR_UNSPEC_GROUP &&
225 ntohl(in.s_addr) <= INADDR_MAX_LOCAL_GROUP) {
226 local = 1;
227 } else {
228 sin.sin_family = AF_INET;
229 sin.sin_len = sizeof(sin);
230 sin.sin_addr = in;
231 rt = rtalloc1((struct sockaddr *)&sin, 0, 0);
232
233 if (rt != NULL) {
234 RT_LOCK_SPIN(rt);
235 if (rt->rt_gateway->sa_family == AF_LINK ||
236 (rt->rt_ifp->if_flags & IFF_LOOPBACK)) {
237 local = 1;
238 }
239 RT_UNLOCK(rt);
240 rtfree(rt);
241 } else {
242 local = in_localaddr(in);
243 }
244 }
245 return local;
246 }
247
248 /*
249 * Return 1 if an internet address is for a ``local'' host
250 * (one to which we have a connection). If subnetsarelocal
251 * is true, this includes other subnets of the local net,
252 * otherwise, it includes the directly-connected (sub)nets.
253 * The IPv4 link local prefix 169.254/16 is also included.
254 */
255 int
in_localaddr(struct in_addr in)256 in_localaddr(struct in_addr in)
257 {
258 u_int32_t i = ntohl(in.s_addr);
259 struct in_ifaddr *ia;
260
261 if (IN_LINKLOCAL(i)) {
262 return 1;
263 }
264
265 if (subnetsarelocal) {
266 lck_rw_lock_shared(&in_ifaddr_rwlock);
267 for (ia = in_ifaddrhead.tqh_first; ia != NULL;
268 ia = ia->ia_link.tqe_next) {
269 IFA_LOCK(&ia->ia_ifa);
270 if ((i & ia->ia_netmask) == ia->ia_net) {
271 IFA_UNLOCK(&ia->ia_ifa);
272 lck_rw_done(&in_ifaddr_rwlock);
273 return 1;
274 }
275 IFA_UNLOCK(&ia->ia_ifa);
276 }
277 lck_rw_done(&in_ifaddr_rwlock);
278 } else {
279 lck_rw_lock_shared(&in_ifaddr_rwlock);
280 for (ia = in_ifaddrhead.tqh_first; ia != NULL;
281 ia = ia->ia_link.tqe_next) {
282 IFA_LOCK(&ia->ia_ifa);
283 if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
284 IFA_UNLOCK(&ia->ia_ifa);
285 lck_rw_done(&in_ifaddr_rwlock);
286 return 1;
287 }
288 IFA_UNLOCK(&ia->ia_ifa);
289 }
290 lck_rw_done(&in_ifaddr_rwlock);
291 }
292 return 0;
293 }
294
295 /*
296 * Determine whether an IP address is in a reserved set of addresses
297 * that may not be forwarded, or whether datagrams to that destination
298 * may be forwarded.
299 */
300 boolean_t
in_canforward(struct in_addr in)301 in_canforward(struct in_addr in)
302 {
303 u_int32_t i = ntohl(in.s_addr);
304 u_int32_t net;
305
306 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i)) {
307 return FALSE;
308 }
309 if (IN_CLASSA(i)) {
310 net = i & IN_CLASSA_NET;
311 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) {
312 return FALSE;
313 }
314 }
315 return TRUE;
316 }
317
318 /*
319 * Trim a mask in a sockaddr
320 */
321 static void
in_socktrim(struct sockaddr_in * ap)322 in_socktrim(struct sockaddr_in *ap)
323 {
324 char *cplim = (char *)&ap->sin_addr;
325 char *cp = (char *)(&ap->sin_addr + 1);
326
327 ap->sin_len = 0;
328 while (--cp >= cplim) {
329 if (*cp) {
330 (ap)->sin_len = (uint8_t)(cp - (char *)(ap) + 1);
331 break;
332 }
333 }
334 }
335
336 static int in_interfaces; /* number of external internet interfaces */
337
338 static int
in_domifattach(struct ifnet * ifp)339 in_domifattach(struct ifnet *ifp)
340 {
341 int error = 0;
342
343 VERIFY(ifp != NULL);
344
345 if ((error = proto_plumb(PF_INET, ifp)) && error != EEXIST) {
346 log(LOG_ERR, "%s: proto_plumb returned %d if=%s\n",
347 __func__, error, if_name(ifp));
348 return error;
349 }
350
351 if (ifp->if_inetdata == NULL) {
352 ifp->if_inetdata = zalloc_permanent_type(struct in_ifextra);
353 IN_IFEXTRA(ifp)->ii_llt = in_lltattach(ifp);
354 error = 0;
355 } else if (error != EEXIST) {
356 /*
357 * Since the structure is never freed, we need to
358 * zero out its contents to avoid reusing stale data.
359 * A little redundant with allocation above, but it
360 * keeps the code simpler for all cases.
361 */
362 IN_IFEXTRA(ifp)->netsig_len = 0;
363 bzero(IN_IFEXTRA(ifp)->netsig, sizeof(IN_IFEXTRA(ifp)->netsig));
364 if (LLTABLE(ifp)) {
365 lltable_purge(LLTABLE(ifp));
366 }
367 }
368 return error;
369 }
370
371 static __attribute__((noinline)) int
inctl_associd(struct socket * so,u_long cmd,caddr_t data)372 inctl_associd(struct socket *so, u_long cmd, caddr_t data)
373 {
374 int error = 0;
375 union {
376 struct so_aidreq32 a32;
377 struct so_aidreq64 a64;
378 } u;
379
380 VERIFY(so != NULL);
381
382 switch (cmd) {
383 case SIOCGASSOCIDS32: /* struct so_aidreq32 */
384 bcopy(data, &u.a32, sizeof(u.a32));
385 error = in_getassocids(so, &u.a32.sar_cnt, u.a32.sar_aidp);
386 if (error == 0) {
387 bcopy(&u.a32, data, sizeof(u.a32));
388 }
389 break;
390
391 case SIOCGASSOCIDS64: /* struct so_aidreq64 */
392 bcopy(data, &u.a64, sizeof(u.a64));
393 error = in_getassocids(so, &u.a64.sar_cnt, (user_addr_t)u.a64.sar_aidp);
394 if (error == 0) {
395 bcopy(&u.a64, data, sizeof(u.a64));
396 }
397 break;
398
399 default:
400 VERIFY(0);
401 /* NOTREACHED */
402 }
403
404 return error;
405 }
406
407 static __attribute__((noinline)) int
inctl_connid(struct socket * so,u_long cmd,caddr_t data)408 inctl_connid(struct socket *so, u_long cmd, caddr_t data)
409 {
410 int error = 0;
411 union {
412 struct so_cidreq32 c32;
413 struct so_cidreq64 c64;
414 } u;
415
416 VERIFY(so != NULL);
417
418 switch (cmd) {
419 case SIOCGCONNIDS32: /* struct so_cidreq32 */
420 bcopy(data, &u.c32, sizeof(u.c32));
421 error = in_getconnids(so, u.c32.scr_aid, &u.c32.scr_cnt,
422 u.c32.scr_cidp);
423 if (error == 0) {
424 bcopy(&u.c32, data, sizeof(u.c32));
425 }
426 break;
427
428 case SIOCGCONNIDS64: /* struct so_cidreq64 */
429 bcopy(data, &u.c64, sizeof(u.c64));
430 error = in_getconnids(so, u.c64.scr_aid, &u.c64.scr_cnt,
431 (user_addr_t)u.c64.scr_cidp);
432 if (error == 0) {
433 bcopy(&u.c64, data, sizeof(u.c64));
434 }
435 break;
436
437 default:
438 VERIFY(0);
439 /* NOTREACHED */
440 }
441
442 return error;
443 }
444
445 static __attribute__((noinline)) int
inctl_conninfo(struct socket * so,u_long cmd,caddr_t data)446 inctl_conninfo(struct socket *so, u_long cmd, caddr_t data)
447 {
448 int error = 0;
449 union {
450 struct so_cinforeq32 ci32;
451 struct so_cinforeq64 ci64;
452 } u;
453
454 VERIFY(so != NULL);
455
456 switch (cmd) {
457 case SIOCGCONNINFO32: /* struct so_cinforeq32 */
458 bcopy(data, &u.ci32, sizeof(u.ci32));
459 error = in_getconninfo(so, u.ci32.scir_cid, &u.ci32.scir_flags,
460 &u.ci32.scir_ifindex, &u.ci32.scir_error, u.ci32.scir_src,
461 &u.ci32.scir_src_len, u.ci32.scir_dst, &u.ci32.scir_dst_len,
462 &u.ci32.scir_aux_type, u.ci32.scir_aux_data,
463 &u.ci32.scir_aux_len);
464 if (error == 0) {
465 bcopy(&u.ci32, data, sizeof(u.ci32));
466 }
467 break;
468
469 case SIOCGCONNINFO64: /* struct so_cinforeq64 */
470 bcopy(data, &u.ci64, sizeof(u.ci64));
471 error = in_getconninfo(so, u.ci64.scir_cid, &u.ci64.scir_flags,
472 &u.ci64.scir_ifindex, &u.ci64.scir_error, (user_addr_t)u.ci64.scir_src,
473 &u.ci64.scir_src_len, (user_addr_t)u.ci64.scir_dst, &u.ci64.scir_dst_len,
474 &u.ci64.scir_aux_type, (user_addr_t)u.ci64.scir_aux_data,
475 &u.ci64.scir_aux_len);
476 if (error == 0) {
477 bcopy(&u.ci64, data, sizeof(u.ci64));
478 }
479 break;
480
481 default:
482 VERIFY(0);
483 /* NOTREACHED */
484 }
485
486 return error;
487 }
488
489 /*
490 * Caller passes in the ioctl data pointer directly via "ifr", with the
491 * expectation that this routine always uses bcopy() or other byte-aligned
492 * memory accesses.
493 */
494 static __attribute__((noinline)) int
inctl_autoaddr(struct ifnet * ifp,struct ifreq * ifr)495 inctl_autoaddr(struct ifnet *ifp, struct ifreq *ifr)
496 {
497 int error = 0, intval;
498
499 VERIFY(ifp != NULL);
500
501 bcopy(&ifr->ifr_intval, &intval, sizeof(intval));
502
503 ifnet_lock_exclusive(ifp);
504 if (intval) {
505 /*
506 * An interface in IPv4 router mode implies that it
507 * is configured with a static IP address and should
508 * not act as a DHCP client; prevent SIOCAUTOADDR from
509 * being set in that mode.
510 */
511 if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
512 intval = 0; /* be safe; clear flag if set */
513 error = EBUSY;
514 } else {
515 if_set_eflags(ifp, IFEF_AUTOCONFIGURING);
516 }
517 }
518 if (!intval) {
519 if_clear_eflags(ifp, IFEF_AUTOCONFIGURING);
520 }
521 ifnet_lock_done(ifp);
522
523 return error;
524 }
525
526 /*
527 * Caller passes in the ioctl data pointer directly via "ifr", with the
528 * expectation that this routine always uses bcopy() or other byte-aligned
529 * memory accesses.
530 */
531 static __attribute__((noinline)) int
inctl_arpipll(struct ifnet * ifp,struct ifreq * ifr)532 inctl_arpipll(struct ifnet *ifp, struct ifreq *ifr)
533 {
534 int error = 0, intval;
535
536 VERIFY(ifp != NULL);
537
538 bcopy(&ifr->ifr_intval, &intval, sizeof(intval));
539 ipv4_ll_arp_aware = 1;
540
541 ifnet_lock_exclusive(ifp);
542 if (intval) {
543 /*
544 * An interface in IPv4 router mode implies that it
545 * is configured with a static IP address and should
546 * not have to deal with IPv4 Link-Local Address;
547 * prevent SIOCARPIPLL from being set in that mode.
548 */
549 if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
550 intval = 0; /* be safe; clear flag if set */
551 error = EBUSY;
552 } else {
553 if_set_eflags(ifp, IFEF_ARPLL);
554 }
555 }
556 if (!intval) {
557 if_clear_eflags(ifp, IFEF_ARPLL);
558 }
559 ifnet_lock_done(ifp);
560
561 return error;
562 }
563
564 /*
565 * Handle SIOCSETROUTERMODE to set or clear the IPv4 router mode flag on
566 * the interface. When in this mode, IPv4 Link-Local Address support is
567 * disabled in ARP, and DHCP client support is disabled in IP input; turning
568 * any of them on would cause an error to be returned. Entering or exiting
569 * this mode will result in the removal of IPv4 addresses currently configured
570 * on the interface.
571 *
572 * Caller passes in the ioctl data pointer directly via "ifr", with the
573 * expectation that this routine always uses bcopy() or other byte-aligned
574 * memory accesses.
575 */
576 static __attribute__((noinline)) int
inctl_setrouter(struct ifnet * ifp,struct ifreq * ifr)577 inctl_setrouter(struct ifnet *ifp, struct ifreq *ifr)
578 {
579 int error = 0, intval;
580
581 VERIFY(ifp != NULL);
582
583 /* Router mode isn't valid for loopback */
584 if (ifp->if_flags & IFF_LOOPBACK) {
585 return ENODEV;
586 }
587
588 bcopy(&ifr->ifr_intval, &intval, sizeof(intval));
589 switch (intval) {
590 case 0:
591 case 1:
592 break;
593 default:
594 return EINVAL;
595 }
596 ifnet_lock_exclusive(ifp);
597 if (intval != 0) {
598 if_set_eflags(ifp, IFEF_IPV4_ROUTER);
599 if_clear_eflags(ifp, (IFEF_ARPLL | IFEF_AUTOCONFIGURING));
600 } else {
601 if_clear_eflags(ifp, IFEF_IPV4_ROUTER);
602 }
603 ifnet_lock_done(ifp);
604
605 /* purge all IPv4 addresses configured on this interface */
606 in_purgeaddrs(ifp);
607
608 return error;
609 }
610
611 /*
612 * Caller passes in the ioctl data pointer directly via "ifr", with the
613 * expectation that this routine always uses bcopy() or other byte-aligned
614 * memory accesses.
615 */
616 static __attribute__((noinline)) int
inctl_ifaddr(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)617 inctl_ifaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
618 struct ifreq *ifr)
619 {
620 struct kev_in_data in_event_data;
621 struct kev_msg ev_msg;
622 struct sockaddr_in addr;
623 struct ifaddr *ifa;
624 int error = 0;
625
626 VERIFY(ifp != NULL);
627
628 bzero(&in_event_data, sizeof(struct kev_in_data));
629 bzero(&ev_msg, sizeof(struct kev_msg));
630
631 switch (cmd) {
632 case SIOCGIFADDR: /* struct ifreq */
633 if (ia == NULL) {
634 error = EADDRNOTAVAIL;
635 break;
636 }
637 IFA_LOCK(&ia->ia_ifa);
638 bcopy(&ia->ia_addr, &ifr->ifr_addr, sizeof(addr));
639 IFA_UNLOCK(&ia->ia_ifa);
640 break;
641
642 case SIOCSIFADDR: /* struct ifreq */
643 VERIFY(ia != NULL);
644 bcopy(&ifr->ifr_addr, &addr, sizeof(addr));
645 /*
646 * If this is a new address, the reference count for the
647 * hash table has been taken at creation time above.
648 */
649 error = in_ifinit(ifp, ia, &addr, 1);
650 if (error == 0) {
651 (void) ifnet_notify_address(ifp, AF_INET);
652 }
653 break;
654
655 case SIOCAIFADDR: { /* struct {if,in_}aliasreq */
656 struct in_aliasreq *ifra = (struct in_aliasreq *)ifr;
657 struct sockaddr_in broadaddr, mask;
658 int hostIsNew, maskIsNew;
659
660 VERIFY(ia != NULL);
661 bcopy(&ifra->ifra_addr, &addr, sizeof(addr));
662 bcopy(&ifra->ifra_broadaddr, &broadaddr, sizeof(broadaddr));
663 bcopy(&ifra->ifra_mask, &mask, sizeof(mask));
664
665 maskIsNew = 0;
666 hostIsNew = 1;
667 error = 0;
668
669 IFA_LOCK(&ia->ia_ifa);
670 if (ia->ia_addr.sin_family == AF_INET) {
671 if (addr.sin_len == 0) {
672 addr = ia->ia_addr;
673 hostIsNew = 0;
674 } else if (addr.sin_addr.s_addr ==
675 ia->ia_addr.sin_addr.s_addr) {
676 hostIsNew = 0;
677 }
678 }
679 if (mask.sin_len != 0) {
680 IFA_UNLOCK(&ia->ia_ifa);
681 in_ifscrub(ifp, ia, 0);
682 IFA_LOCK(&ia->ia_ifa);
683 ia->ia_sockmask.sin_len = sizeof(struct sockaddr_in);
684 ia->ia_sockmask.sin_family = AF_INET;
685 ia->ia_sockmask.sin_port = 0;
686 ia->ia_sockmask.sin_addr = mask.sin_addr;
687 bzero(&ia->ia_sockmask.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
688 ia->ia_subnetmask =
689 ntohl(ia->ia_sockmask.sin_addr.s_addr);
690 maskIsNew = 1;
691 }
692 if ((ifp->if_flags & IFF_POINTOPOINT) &&
693 (broadaddr.sin_family == AF_INET)) {
694 IFA_UNLOCK(&ia->ia_ifa);
695 in_ifscrub(ifp, ia, 0);
696 IFA_LOCK(&ia->ia_ifa);
697 ia->ia_dstaddr.sin_family = AF_INET;
698 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
699 ia->ia_dstaddr.sin_port = 0;
700 ia->ia_dstaddr.sin_addr = broadaddr.sin_addr;
701 bzero(&ia->ia_dstaddr.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
702 maskIsNew = 1; /* We lie; but the effect's the same */
703 }
704 if (addr.sin_family == AF_INET && (hostIsNew || maskIsNew)) {
705 IFA_UNLOCK(&ia->ia_ifa);
706 error = in_ifinit(ifp, ia, &addr, 0);
707 } else {
708 IFA_UNLOCK(&ia->ia_ifa);
709 }
710 if (error == 0) {
711 (void) ifnet_notify_address(ifp, AF_INET);
712 }
713 IFA_LOCK(&ia->ia_ifa);
714 if ((ifp->if_flags & IFF_BROADCAST) &&
715 (broadaddr.sin_family == AF_INET)) {
716 ia->ia_broadaddr.sin_family = AF_INET;
717 ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
718 ia->ia_broadaddr.sin_port = 0;
719 ia->ia_broadaddr.sin_addr = broadaddr.sin_addr;
720 bzero(&ia->ia_broadaddr.sin_zero, sizeof(ia->ia_broadaddr.sin_zero));
721 }
722
723 /*
724 * Report event.
725 */
726 if ((error == 0) || (error == EEXIST)) {
727 ev_msg.vendor_code = KEV_VENDOR_APPLE;
728 ev_msg.kev_class = KEV_NETWORK_CLASS;
729 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
730
731 if (hostIsNew) {
732 ev_msg.event_code = KEV_INET_NEW_ADDR;
733 } else {
734 ev_msg.event_code = KEV_INET_CHANGED_ADDR;
735 }
736
737 if (ia->ia_ifa.ifa_dstaddr) {
738 in_event_data.ia_dstaddr =
739 ((struct sockaddr_in *)(void *)ia->
740 ia_ifa.ifa_dstaddr)->sin_addr;
741 } else {
742 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
743 }
744 in_event_data.ia_addr = ia->ia_addr.sin_addr;
745 in_event_data.ia_net = ia->ia_net;
746 in_event_data.ia_netmask = ia->ia_netmask;
747 in_event_data.ia_subnet = ia->ia_subnet;
748 in_event_data.ia_subnetmask = ia->ia_subnetmask;
749 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
750 IFA_UNLOCK(&ia->ia_ifa);
751 (void) strlcpy(&in_event_data.link_data.if_name[0],
752 ifp->if_name, IFNAMSIZ);
753 in_event_data.link_data.if_family = ifp->if_family;
754 in_event_data.link_data.if_unit = ifp->if_unit;
755
756 ev_msg.dv[0].data_ptr = &in_event_data;
757 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
758 ev_msg.dv[1].data_length = 0;
759
760 dlil_post_complete_msg(ifp, &ev_msg);
761 } else {
762 IFA_UNLOCK(&ia->ia_ifa);
763 }
764 break;
765 }
766
767 case SIOCDIFADDR: /* struct ifreq */
768 VERIFY(ia != NULL);
769 error = ifnet_ioctl(ifp, PF_INET, SIOCDIFADDR, ia);
770 if (error == EOPNOTSUPP) {
771 error = 0;
772 }
773 if (error != 0) {
774 break;
775 }
776
777 /* Fill out the kernel event information */
778 ev_msg.vendor_code = KEV_VENDOR_APPLE;
779 ev_msg.kev_class = KEV_NETWORK_CLASS;
780 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
781
782 ev_msg.event_code = KEV_INET_ADDR_DELETED;
783
784 IFA_LOCK(&ia->ia_ifa);
785 if (ia->ia_ifa.ifa_dstaddr) {
786 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
787 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
788 } else {
789 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
790 }
791 in_event_data.ia_addr = ia->ia_addr.sin_addr;
792 in_event_data.ia_net = ia->ia_net;
793 in_event_data.ia_netmask = ia->ia_netmask;
794 in_event_data.ia_subnet = ia->ia_subnet;
795 in_event_data.ia_subnetmask = ia->ia_subnetmask;
796 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
797 IFA_UNLOCK(&ia->ia_ifa);
798 (void) strlcpy(&in_event_data.link_data.if_name[0],
799 ifp->if_name, IFNAMSIZ);
800 in_event_data.link_data.if_family = ifp->if_family;
801 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
802
803 ev_msg.dv[0].data_ptr = &in_event_data;
804 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
805 ev_msg.dv[1].data_length = 0;
806
807 ifa = &ia->ia_ifa;
808 lck_rw_lock_exclusive(&in_ifaddr_rwlock);
809 /* Release ia_link reference */
810 IFA_REMREF(ifa);
811 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
812 IFA_LOCK(ifa);
813 if (IA_IS_HASHED(ia)) {
814 in_iahash_remove(ia);
815 }
816 IFA_UNLOCK(ifa);
817 lck_rw_done(&in_ifaddr_rwlock);
818
819 /*
820 * in_ifscrub kills the interface route.
821 */
822 in_ifscrub(ifp, ia, 0);
823 ifnet_lock_exclusive(ifp);
824 IFA_LOCK(ifa);
825 /* if_detach_ifa() releases ifa_link reference */
826 if_detach_ifa(ifp, ifa);
827 /* Our reference to this address is dropped at the bottom */
828 IFA_UNLOCK(ifa);
829
830 /* invalidate route caches */
831 routegenid_inet_update();
832
833 /*
834 * If the interface supports multicast, and no address is left,
835 * remove the "all hosts" multicast group from that interface.
836 */
837 if ((ifp->if_flags & IFF_MULTICAST) ||
838 ifp->if_allhostsinm != NULL) {
839 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
840 IFA_LOCK(ifa);
841 if (ifa->ifa_addr->sa_family == AF_INET) {
842 IFA_UNLOCK(ifa);
843 break;
844 }
845 IFA_UNLOCK(ifa);
846 }
847 ifnet_lock_done(ifp);
848
849 lck_mtx_lock(&ifp->if_addrconfig_lock);
850 if (ifa == NULL && ifp->if_allhostsinm != NULL) {
851 struct in_multi *inm = ifp->if_allhostsinm;
852 ifp->if_allhostsinm = NULL;
853
854 in_delmulti(inm);
855 /* release the reference for allhostsinm */
856 INM_REMREF(inm);
857 }
858 lck_mtx_unlock(&ifp->if_addrconfig_lock);
859 } else {
860 ifnet_lock_done(ifp);
861 }
862
863 /* Post the kernel event */
864 dlil_post_complete_msg(ifp, &ev_msg);
865
866 /*
867 * See if there is any IPV4 address left and if so,
868 * reconfigure KDP to use current primary address.
869 */
870 ifa = ifa_ifpgetprimary(ifp, AF_INET);
871 if (ifa != NULL) {
872 /*
873 * NOTE: SIOCSIFADDR is defined with struct ifreq
874 * as parameter, but here we are sending it down
875 * to the interface with a pointer to struct ifaddr,
876 * for legacy reasons.
877 */
878 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa);
879 if (error == EOPNOTSUPP) {
880 error = 0;
881 }
882
883 /* Release reference from ifa_ifpgetprimary() */
884 IFA_REMREF(ifa);
885 }
886 (void) ifnet_notify_address(ifp, AF_INET);
887 break;
888
889 default:
890 VERIFY(0);
891 /* NOTREACHED */
892 }
893
894 return error;
895 }
896
897 /*
898 * Caller passes in the ioctl data pointer directly via "ifr", with the
899 * expectation that this routine always uses bcopy() or other byte-aligned
900 * memory accesses.
901 */
902 static __attribute__((noinline)) int
inctl_ifdstaddr(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)903 inctl_ifdstaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
904 struct ifreq *ifr)
905 {
906 struct kev_in_data in_event_data;
907 struct kev_msg ev_msg;
908 struct sockaddr_in dstaddr;
909 int error = 0;
910
911 VERIFY(ifp != NULL);
912
913 if (!(ifp->if_flags & IFF_POINTOPOINT)) {
914 return EINVAL;
915 }
916
917 bzero(&in_event_data, sizeof(struct kev_in_data));
918 bzero(&ev_msg, sizeof(struct kev_msg));
919
920 switch (cmd) {
921 case SIOCGIFDSTADDR: /* struct ifreq */
922 if (ia == NULL) {
923 error = EADDRNOTAVAIL;
924 break;
925 }
926 IFA_LOCK(&ia->ia_ifa);
927 bcopy(&ia->ia_dstaddr, &ifr->ifr_dstaddr, sizeof(dstaddr));
928 IFA_UNLOCK(&ia->ia_ifa);
929 break;
930
931 case SIOCSIFDSTADDR: /* struct ifreq */
932 VERIFY(ia != NULL);
933 IFA_LOCK(&ia->ia_ifa);
934 dstaddr = ia->ia_dstaddr;
935
936 ia->ia_dstaddr.sin_family = AF_INET;
937 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
938 ia->ia_dstaddr.sin_port = 0;
939 bcopy(&(SIN(&ifr->ifr_dstaddr)->sin_addr),
940 &ia->ia_dstaddr.sin_addr, sizeof(ia->ia_dstaddr.sin_addr));
941 bzero(&ia->ia_dstaddr.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
942
943 IFA_UNLOCK(&ia->ia_ifa);
944 /*
945 * NOTE: SIOCSIFDSTADDR is defined with struct ifreq
946 * as parameter, but here we are sending it down
947 * to the interface with a pointer to struct ifaddr,
948 * for legacy reasons.
949 */
950 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFDSTADDR, ia);
951 IFA_LOCK(&ia->ia_ifa);
952 if (error == EOPNOTSUPP) {
953 error = 0;
954 }
955 if (error != 0) {
956 ia->ia_dstaddr = dstaddr;
957 IFA_UNLOCK(&ia->ia_ifa);
958 break;
959 }
960 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
961
962 ev_msg.vendor_code = KEV_VENDOR_APPLE;
963 ev_msg.kev_class = KEV_NETWORK_CLASS;
964 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
965
966 ev_msg.event_code = KEV_INET_SIFDSTADDR;
967
968 if (ia->ia_ifa.ifa_dstaddr) {
969 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
970 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
971 } else {
972 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
973 }
974
975 in_event_data.ia_addr = ia->ia_addr.sin_addr;
976 in_event_data.ia_net = ia->ia_net;
977 in_event_data.ia_netmask = ia->ia_netmask;
978 in_event_data.ia_subnet = ia->ia_subnet;
979 in_event_data.ia_subnetmask = ia->ia_subnetmask;
980 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
981 IFA_UNLOCK(&ia->ia_ifa);
982 (void) strlcpy(&in_event_data.link_data.if_name[0],
983 ifp->if_name, IFNAMSIZ);
984 in_event_data.link_data.if_family = ifp->if_family;
985 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
986
987 ev_msg.dv[0].data_ptr = &in_event_data;
988 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
989 ev_msg.dv[1].data_length = 0;
990
991 dlil_post_complete_msg(ifp, &ev_msg);
992
993 lck_mtx_lock(rnh_lock);
994 IFA_LOCK(&ia->ia_ifa);
995 if (ia->ia_flags & IFA_ROUTE) {
996 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&dstaddr;
997 IFA_UNLOCK(&ia->ia_ifa);
998 rtinit_locked(&(ia->ia_ifa), RTM_DELETE, RTF_HOST);
999 IFA_LOCK(&ia->ia_ifa);
1000 ia->ia_ifa.ifa_dstaddr =
1001 (struct sockaddr *)&ia->ia_dstaddr;
1002 IFA_UNLOCK(&ia->ia_ifa);
1003 rtinit_locked(&(ia->ia_ifa), RTM_ADD,
1004 RTF_HOST | RTF_UP);
1005 } else {
1006 IFA_UNLOCK(&ia->ia_ifa);
1007 }
1008 lck_mtx_unlock(rnh_lock);
1009 break;
1010
1011
1012
1013 default:
1014 VERIFY(0);
1015 /* NOTREACHED */
1016 }
1017
1018 return error;
1019 }
1020
1021 /*
1022 * Caller passes in the ioctl data pointer directly via "ifr", with the
1023 * expectation that this routine always uses bcopy() or other byte-aligned
1024 * memory accesses.
1025 */
1026 static __attribute__((noinline)) int
inctl_ifbrdaddr(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)1027 inctl_ifbrdaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
1028 struct ifreq *ifr)
1029 {
1030 struct kev_in_data in_event_data;
1031 struct kev_msg ev_msg;
1032 int error = 0;
1033
1034 VERIFY(ifp != NULL);
1035
1036 if (ia == NULL) {
1037 return EADDRNOTAVAIL;
1038 }
1039
1040 if (!(ifp->if_flags & IFF_BROADCAST)) {
1041 return EINVAL;
1042 }
1043
1044 bzero(&in_event_data, sizeof(struct kev_in_data));
1045 bzero(&ev_msg, sizeof(struct kev_msg));
1046
1047 switch (cmd) {
1048 case SIOCGIFBRDADDR: /* struct ifreq */
1049 IFA_LOCK(&ia->ia_ifa);
1050 bcopy(&ia->ia_broadaddr, &ifr->ifr_broadaddr,
1051 sizeof(struct sockaddr_in));
1052 IFA_UNLOCK(&ia->ia_ifa);
1053 break;
1054
1055 case SIOCSIFBRDADDR: /* struct ifreq */
1056 IFA_LOCK(&ia->ia_ifa);
1057
1058 ia->ia_broadaddr.sin_family = AF_INET;
1059 ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
1060 ia->ia_broadaddr.sin_port = 0;
1061 bcopy(&(SIN(&ifr->ifr_broadaddr)->sin_addr),
1062 &ia->ia_broadaddr.sin_addr, sizeof(ia->ia_broadaddr.sin_addr));
1063 bzero(&ia->ia_broadaddr.sin_zero, sizeof(ia->ia_broadaddr.sin_zero));
1064
1065 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1066 ev_msg.kev_class = KEV_NETWORK_CLASS;
1067 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1068
1069 ev_msg.event_code = KEV_INET_SIFBRDADDR;
1070
1071 if (ia->ia_ifa.ifa_dstaddr) {
1072 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
1073 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
1074 } else {
1075 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1076 }
1077 in_event_data.ia_addr = ia->ia_addr.sin_addr;
1078 in_event_data.ia_net = ia->ia_net;
1079 in_event_data.ia_netmask = ia->ia_netmask;
1080 in_event_data.ia_subnet = ia->ia_subnet;
1081 in_event_data.ia_subnetmask = ia->ia_subnetmask;
1082 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
1083 IFA_UNLOCK(&ia->ia_ifa);
1084 (void) strlcpy(&in_event_data.link_data.if_name[0],
1085 ifp->if_name, IFNAMSIZ);
1086 in_event_data.link_data.if_family = ifp->if_family;
1087 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
1088
1089 ev_msg.dv[0].data_ptr = &in_event_data;
1090 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1091 ev_msg.dv[1].data_length = 0;
1092
1093 dlil_post_complete_msg(ifp, &ev_msg);
1094 break;
1095
1096 default:
1097 VERIFY(0);
1098 /* NOTREACHED */
1099 }
1100
1101 return error;
1102 }
1103
1104 /*
1105 * Caller passes in the ioctl data pointer directly via "ifr", with the
1106 * expectation that this routine always uses bcopy() or other byte-aligned
1107 * memory accesses.
1108 */
1109 static __attribute__((noinline)) int
inctl_ifnetmask(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)1110 inctl_ifnetmask(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
1111 struct ifreq *ifr)
1112 {
1113 struct kev_in_data in_event_data;
1114 struct kev_msg ev_msg;
1115 struct sockaddr_in mask;
1116 int error = 0;
1117
1118 VERIFY(ifp != NULL);
1119
1120 bzero(&in_event_data, sizeof(struct kev_in_data));
1121 bzero(&ev_msg, sizeof(struct kev_msg));
1122
1123 switch (cmd) {
1124 case SIOCGIFNETMASK: /* struct ifreq */
1125 if (ia == NULL) {
1126 error = EADDRNOTAVAIL;
1127 break;
1128 }
1129 IFA_LOCK(&ia->ia_ifa);
1130 bcopy(&ia->ia_sockmask, &ifr->ifr_addr, sizeof(mask));
1131 IFA_UNLOCK(&ia->ia_ifa);
1132 break;
1133
1134 case SIOCSIFNETMASK: { /* struct ifreq */
1135 in_addr_t i;
1136
1137 bcopy(&ifr->ifr_addr, &mask, sizeof(mask));
1138 i = mask.sin_addr.s_addr;
1139
1140 VERIFY(ia != NULL);
1141 IFA_LOCK(&ia->ia_ifa);
1142 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
1143 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1144 ev_msg.kev_class = KEV_NETWORK_CLASS;
1145 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1146
1147 ev_msg.event_code = KEV_INET_SIFNETMASK;
1148
1149 if (ia->ia_ifa.ifa_dstaddr) {
1150 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
1151 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
1152 } else {
1153 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1154 }
1155 in_event_data.ia_addr = ia->ia_addr.sin_addr;
1156 in_event_data.ia_net = ia->ia_net;
1157 in_event_data.ia_netmask = ia->ia_netmask;
1158 in_event_data.ia_subnet = ia->ia_subnet;
1159 in_event_data.ia_subnetmask = ia->ia_subnetmask;
1160 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
1161 IFA_UNLOCK(&ia->ia_ifa);
1162 (void) strlcpy(&in_event_data.link_data.if_name[0],
1163 ifp->if_name, IFNAMSIZ);
1164 in_event_data.link_data.if_family = ifp->if_family;
1165 in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
1166
1167 ev_msg.dv[0].data_ptr = &in_event_data;
1168 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1169 ev_msg.dv[1].data_length = 0;
1170
1171 dlil_post_complete_msg(ifp, &ev_msg);
1172 break;
1173 }
1174
1175 default:
1176 VERIFY(0);
1177 /* NOTREACHED */
1178 }
1179
1180 return error;
1181 }
1182
1183 /*
1184 * Generic INET control operations (ioctl's).
1185 *
1186 * ifp is NULL if not an interface-specific ioctl.
1187 *
1188 * Most of the routines called to handle the ioctls would end up being
1189 * tail-call optimized, which unfortunately causes this routine to
1190 * consume too much stack space; this is the reason for the "noinline"
1191 * attribute used on those routines.
1192 *
1193 * If called directly from within the networking stack (as opposed to via
1194 * pru_control), the socket parameter may be NULL.
1195 */
1196 int
in_control(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp,struct proc * p)1197 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
1198 struct proc *p)
1199 {
1200 struct ifreq *ifr = (struct ifreq *)(void *)data;
1201 struct sockaddr_in addr, dstaddr;
1202 struct sockaddr_in sin, *sa = NULL;
1203 boolean_t privileged = (proc_suser(p) == 0);
1204 boolean_t so_unlocked = FALSE;
1205 struct in_ifaddr *ia = NULL;
1206 struct ifaddr *ifa;
1207 int error = 0;
1208 int intval;
1209
1210 /* In case it's NULL, make sure it came from the kernel */
1211 VERIFY(so != NULL || p == kernproc);
1212
1213 /*
1214 * ioctls which don't require ifp, but require socket.
1215 */
1216 switch (cmd) {
1217 case SIOCGASSOCIDS32: /* struct so_aidreq32 */
1218 case SIOCGASSOCIDS64: /* struct so_aidreq64 */
1219 return inctl_associd(so, cmd, data);
1220 /* NOTREACHED */
1221
1222 case SIOCGCONNIDS32: /* struct so_cidreq32 */
1223 case SIOCGCONNIDS64: /* struct so_cidreq64 */
1224 return inctl_connid(so, cmd, data);
1225 /* NOTREACHED */
1226
1227 case SIOCGCONNINFO32: /* struct so_cinforeq32 */
1228 case SIOCGCONNINFO64: /* struct so_cinforeq64 */
1229 return inctl_conninfo(so, cmd, data);
1230 /* NOTREACHED */
1231 }
1232
1233 /*
1234 * The rest of ioctls require ifp; reject if we don't have one;
1235 * return ENXIO to be consistent with ifioctl().
1236 */
1237 if (ifp == NULL) {
1238 return ENXIO;
1239 }
1240
1241 /*
1242 * ioctls which require ifp but not interface address.
1243 */
1244 switch (cmd) {
1245 case SIOCAUTOADDR: /* struct ifreq */
1246 if (!privileged) {
1247 return EPERM;
1248 }
1249 return inctl_autoaddr(ifp, ifr);
1250 /* NOTREACHED */
1251
1252 case SIOCARPIPLL: /* struct ifreq */
1253 if (!privileged) {
1254 return EPERM;
1255 }
1256 return inctl_arpipll(ifp, ifr);
1257 /* NOTREACHED */
1258
1259 case SIOCGETROUTERMODE: /* struct ifreq */
1260 intval = (ifp->if_eflags & IFEF_IPV4_ROUTER) != 0 ? 1 : 0;
1261 bcopy(&intval, &ifr->ifr_intval, sizeof(intval));
1262 return 0;
1263 /* NOTREACHED */
1264
1265 case SIOCSETROUTERMODE: /* struct ifreq */
1266 if (!privileged) {
1267 return EPERM;
1268 }
1269 return inctl_setrouter(ifp, ifr);
1270 /* NOTREACHED */
1271
1272 case SIOCPROTOATTACH: /* struct ifreq */
1273 if (!privileged) {
1274 return EPERM;
1275 }
1276 return in_domifattach(ifp);
1277 /* NOTREACHED */
1278
1279 case SIOCPROTODETACH: /* struct ifreq */
1280 if (!privileged) {
1281 return EPERM;
1282 }
1283
1284 /*
1285 * If an IPv4 address is still present, refuse to detach.
1286 */
1287 ifnet_lock_shared(ifp);
1288 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1289 IFA_LOCK(ifa);
1290 if (ifa->ifa_addr->sa_family == AF_INET) {
1291 IFA_UNLOCK(ifa);
1292 break;
1293 }
1294 IFA_UNLOCK(ifa);
1295 }
1296 ifnet_lock_done(ifp);
1297 return (ifa == NULL) ? proto_unplumb(PF_INET, ifp) : EBUSY;
1298 /* NOTREACHED */
1299 }
1300
1301 /*
1302 * ioctls which require interface address; obtain sockaddr_in.
1303 */
1304 switch (cmd) {
1305 case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1306 if (!privileged) {
1307 return EPERM;
1308 }
1309 bcopy(&((struct in_aliasreq *)(void *)data)->ifra_addr,
1310 &sin, sizeof(sin));
1311 sa = &sin;
1312 break;
1313
1314 case SIOCDIFADDR: /* struct ifreq */
1315 case SIOCSIFADDR: /* struct ifreq */
1316 case SIOCSIFDSTADDR: /* struct ifreq */
1317 case SIOCSIFNETMASK: /* struct ifreq */
1318 case SIOCSIFBRDADDR: /* struct ifreq */
1319 if (!privileged) {
1320 return EPERM;
1321 }
1322 OS_FALLTHROUGH;
1323 case SIOCGIFADDR: /* struct ifreq */
1324 case SIOCGIFDSTADDR: /* struct ifreq */
1325 case SIOCGIFNETMASK: /* struct ifreq */
1326 case SIOCGIFBRDADDR: /* struct ifreq */
1327 bcopy(&ifr->ifr_addr, &sin, sizeof(sin));
1328 sa = &sin;
1329 break;
1330 }
1331
1332 /*
1333 * Find address for this interface, if it exists.
1334 *
1335 * If an alias address was specified, find that one instead of
1336 * the first one on the interface, if possible.
1337 */
1338 VERIFY(ia == NULL);
1339 if (sa != NULL) {
1340 struct in_ifaddr *iap;
1341
1342 /*
1343 * Any failures from this point on must take into account
1344 * a non-NULL "ia" with an outstanding reference count, and
1345 * therefore requires IFA_REMREF. Jump to "done" label
1346 * instead of calling return if "ia" is valid.
1347 */
1348 lck_rw_lock_shared(&in_ifaddr_rwlock);
1349 TAILQ_FOREACH(iap, INADDR_HASH(sa->sin_addr.s_addr), ia_hash) {
1350 IFA_LOCK(&iap->ia_ifa);
1351 if (iap->ia_ifp == ifp &&
1352 iap->ia_addr.sin_addr.s_addr ==
1353 sa->sin_addr.s_addr) {
1354 ia = iap;
1355 IFA_ADDREF_LOCKED(&iap->ia_ifa);
1356 IFA_UNLOCK(&iap->ia_ifa);
1357 break;
1358 }
1359 IFA_UNLOCK(&iap->ia_ifa);
1360 }
1361 lck_rw_done(&in_ifaddr_rwlock);
1362
1363 if (ia == NULL) {
1364 ifnet_lock_shared(ifp);
1365 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1366 iap = ifatoia(ifa);
1367 IFA_LOCK(&iap->ia_ifa);
1368 if (iap->ia_addr.sin_family == AF_INET) {
1369 ia = iap;
1370 IFA_ADDREF_LOCKED(&iap->ia_ifa);
1371 IFA_UNLOCK(&iap->ia_ifa);
1372 break;
1373 }
1374 IFA_UNLOCK(&iap->ia_ifa);
1375 }
1376 ifnet_lock_done(ifp);
1377 }
1378 }
1379
1380 /*
1381 * Unlock the socket since ifnet_ioctl() may be invoked by
1382 * one of the ioctl handlers below. Socket will be re-locked
1383 * prior to returning.
1384 */
1385 if (so != NULL) {
1386 socket_unlock(so, 0);
1387 so_unlocked = TRUE;
1388 }
1389
1390 switch (cmd) {
1391 case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1392 case SIOCDIFADDR: /* struct ifreq */
1393 if (cmd == SIOCAIFADDR) {
1394 bcopy(&((struct in_aliasreq *)(void *)data)->
1395 ifra_addr, &addr, sizeof(addr));
1396 bcopy(&((struct in_aliasreq *)(void *)data)->
1397 ifra_dstaddr, &dstaddr, sizeof(dstaddr));
1398 } else {
1399 VERIFY(cmd == SIOCDIFADDR);
1400 bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
1401 &addr, sizeof(addr));
1402 bzero(&dstaddr, sizeof(dstaddr));
1403 }
1404
1405 if (addr.sin_family == AF_INET) {
1406 struct in_ifaddr *oia;
1407
1408 lck_rw_lock_shared(&in_ifaddr_rwlock);
1409 for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
1410 IFA_LOCK(&ia->ia_ifa);
1411 if (ia->ia_ifp == ifp &&
1412 ia->ia_addr.sin_addr.s_addr ==
1413 addr.sin_addr.s_addr) {
1414 IFA_ADDREF_LOCKED(&ia->ia_ifa);
1415 IFA_UNLOCK(&ia->ia_ifa);
1416 break;
1417 }
1418 IFA_UNLOCK(&ia->ia_ifa);
1419 }
1420 lck_rw_done(&in_ifaddr_rwlock);
1421 if (oia != NULL) {
1422 IFA_REMREF(&oia->ia_ifa);
1423 }
1424 if ((ifp->if_flags & IFF_POINTOPOINT) &&
1425 (cmd == SIOCAIFADDR) &&
1426 (dstaddr.sin_addr.s_addr == INADDR_ANY)) {
1427 error = EDESTADDRREQ;
1428 goto done;
1429 }
1430 } else if (cmd == SIOCAIFADDR) {
1431 error = EINVAL;
1432 goto done;
1433 }
1434 if (cmd == SIOCDIFADDR) {
1435 if (ia == NULL) {
1436 error = EADDRNOTAVAIL;
1437 goto done;
1438 }
1439
1440 IFA_LOCK(&ia->ia_ifa);
1441 /*
1442 * Avoid the race condition seen when two
1443 * threads process SIOCDIFADDR command
1444 * at the same time.
1445 */
1446 while (ia->ia_ifa.ifa_debug & IFD_DETACHING) {
1447 os_log(OS_LOG_DEFAULT,
1448 "Another thread is already attempting to "
1449 "delete IPv4 address: %s on interface %s. "
1450 "Go to sleep and check again after the operation is done",
1451 inet_ntoa(sa->sin_addr), ia->ia_ifp->if_xname);
1452 ia->ia_ifa.ifa_del_waiters++;
1453 (void) msleep(ia->ia_ifa.ifa_del_wc, &ia->ia_ifa.ifa_lock, (PZERO - 1),
1454 __func__, NULL);
1455 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1456 }
1457
1458 if ((ia->ia_ifa.ifa_debug & IFD_ATTACHED) == 0) {
1459 error = EADDRNOTAVAIL;
1460 IFA_UNLOCK(&ia->ia_ifa);
1461 goto done;
1462 }
1463
1464 ia->ia_ifa.ifa_debug |= IFD_DETACHING;
1465 IFA_UNLOCK(&ia->ia_ifa);
1466 }
1467
1468 OS_FALLTHROUGH;
1469 case SIOCSIFADDR: /* struct ifreq */
1470 case SIOCSIFDSTADDR: /* struct ifreq */
1471 case SIOCSIFNETMASK: /* struct ifreq */
1472 if (cmd == SIOCAIFADDR) {
1473 /* fell thru from above; just repeat it */
1474 bcopy(&((struct in_aliasreq *)(void *)data)->
1475 ifra_addr, &addr, sizeof(addr));
1476 } else {
1477 VERIFY(cmd == SIOCDIFADDR || cmd == SIOCSIFADDR ||
1478 cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR);
1479 bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
1480 &addr, sizeof(addr));
1481 }
1482
1483 if (addr.sin_family != AF_INET && cmd == SIOCSIFADDR) {
1484 error = EINVAL;
1485 goto done;
1486 }
1487
1488 if ((cmd == SIOCAIFADDR || cmd == SIOCSIFADDR) &&
1489 (IN_MULTICAST(ntohl(addr.sin_addr.s_addr)) ||
1490 addr.sin_addr.s_addr == INADDR_BROADCAST ||
1491 addr.sin_addr.s_addr == INADDR_ANY)) {
1492 error = EINVAL;
1493 goto done;
1494 }
1495
1496 if (ia == NULL) {
1497 ia = in_ifaddr_alloc(Z_WAITOK);
1498 if (ia == NULL) {
1499 error = ENOBUFS;
1500 goto done;
1501 }
1502 ifnet_lock_exclusive(ifp);
1503 ifa = &ia->ia_ifa;
1504 IFA_LOCK(ifa);
1505 /* Hold a reference for this routine */
1506 IFA_ADDREF_LOCKED(ifa);
1507 IA_HASH_INIT(ia);
1508 ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
1509 ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
1510 ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
1511 ia->ia_sockmask.sin_len = offsetof(struct sockaddr_in, sin_zero);
1512 if (ifp->if_flags & IFF_BROADCAST) {
1513 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
1514 ia->ia_broadaddr.sin_family = AF_INET;
1515 }
1516 ia->ia_ifp = ifp;
1517 if (!(ifp->if_flags & IFF_LOOPBACK)) {
1518 in_interfaces++;
1519 }
1520 /* if_attach_ifa() holds a reference for ifa_link */
1521 if_attach_ifa(ifp, ifa);
1522 /*
1523 * If we have to go through in_ifinit(), make sure
1524 * to avoid installing route(s) based on this address
1525 * via PFC_IFUP event, before the link resolver (ARP)
1526 * initializes it.
1527 */
1528 if (cmd == SIOCAIFADDR || cmd == SIOCSIFADDR) {
1529 ifa->ifa_debug |= IFD_NOTREADY;
1530 }
1531 IFA_UNLOCK(ifa);
1532 ifnet_lock_done(ifp);
1533 lck_rw_lock_exclusive(&in_ifaddr_rwlock);
1534 /* Hold a reference for ia_link */
1535 IFA_ADDREF(ifa);
1536 TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
1537 lck_rw_done(&in_ifaddr_rwlock);
1538 /* discard error */
1539 (void) in_domifattach(ifp);
1540 error = 0;
1541 }
1542 break;
1543 }
1544
1545 switch (cmd) {
1546 case SIOCGIFDSTADDR: /* struct ifreq */
1547 case SIOCSIFDSTADDR: /* struct ifreq */
1548 error = inctl_ifdstaddr(ifp, ia, cmd, ifr);
1549 break;
1550
1551 case SIOCGIFBRDADDR: /* struct ifreq */
1552 case SIOCSIFBRDADDR: /* struct ifreq */
1553 error = inctl_ifbrdaddr(ifp, ia, cmd, ifr);
1554 break;
1555
1556 case SIOCGIFNETMASK: /* struct ifreq */
1557 case SIOCSIFNETMASK: /* struct ifreq */
1558 error = inctl_ifnetmask(ifp, ia, cmd, ifr);
1559 break;
1560
1561 case SIOCGIFADDR: /* struct ifreq */
1562 case SIOCSIFADDR: /* struct ifreq */
1563 case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1564 case SIOCDIFADDR: /* struct ifreq */
1565 error = inctl_ifaddr(ifp, ia, cmd, ifr);
1566 break;
1567
1568 default:
1569 error = EOPNOTSUPP;
1570 break;
1571 }
1572
1573 done:
1574 if (ia != NULL) {
1575 if (cmd == SIOCDIFADDR) {
1576 IFA_LOCK(&ia->ia_ifa);
1577 ia->ia_ifa.ifa_debug &= ~IFD_DETACHING;
1578 if (ia->ia_ifa.ifa_del_waiters > 0) {
1579 ia->ia_ifa.ifa_del_waiters = 0;
1580 wakeup(ia->ia_ifa.ifa_del_wc);
1581 }
1582 IFA_UNLOCK(&ia->ia_ifa);
1583 }
1584 IFA_REMREF(&ia->ia_ifa);
1585 }
1586 if (so_unlocked) {
1587 socket_lock(so, 0);
1588 }
1589
1590 return error;
1591 }
1592
1593 /*
1594 * Delete any existing route for an interface.
1595 */
1596 void
in_ifscrub(struct ifnet * ifp,struct in_ifaddr * ia,int locked)1597 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, int locked)
1598 {
1599 IFA_LOCK(&ia->ia_ifa);
1600 if ((ia->ia_flags & IFA_ROUTE) == 0) {
1601 IFA_UNLOCK(&ia->ia_ifa);
1602 return;
1603 }
1604 IFA_UNLOCK(&ia->ia_ifa);
1605 if (!locked) {
1606 lck_mtx_lock(rnh_lock);
1607 }
1608 if (ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) {
1609 rtinit_locked(&(ia->ia_ifa), RTM_DELETE, RTF_HOST);
1610 } else {
1611 rtinit_locked(&(ia->ia_ifa), RTM_DELETE, 0);
1612 }
1613 IFA_LOCK(&ia->ia_ifa);
1614 ia->ia_flags &= ~IFA_ROUTE;
1615 IFA_UNLOCK(&ia->ia_ifa);
1616 if (!locked) {
1617 lck_mtx_unlock(rnh_lock);
1618 }
1619 }
1620
1621 /*
1622 * Caller must hold in_ifaddr_rwlock as writer.
1623 */
1624 static void
in_iahash_remove(struct in_ifaddr * ia)1625 in_iahash_remove(struct in_ifaddr *ia)
1626 {
1627 LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1628 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1629
1630 if (!IA_IS_HASHED(ia)) {
1631 panic("attempt to remove wrong ia %p from hash table", ia);
1632 /* NOTREACHED */
1633 }
1634 TAILQ_REMOVE(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
1635 IA_HASH_INIT(ia);
1636 if (IFA_REMREF_LOCKED(&ia->ia_ifa) == NULL) {
1637 panic("%s: unexpected (missing) refcnt ifa=%p", __func__,
1638 &ia->ia_ifa);
1639 /* NOTREACHED */
1640 }
1641 }
1642
1643 /*
1644 * Caller must hold in_ifaddr_rwlock as writer.
1645 */
1646 static void
in_iahash_insert(struct in_ifaddr * ia)1647 in_iahash_insert(struct in_ifaddr *ia)
1648 {
1649 LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1650 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1651
1652 if (ia->ia_addr.sin_family != AF_INET) {
1653 panic("attempt to insert wrong ia %p into hash table", ia);
1654 /* NOTREACHED */
1655 } else if (IA_IS_HASHED(ia)) {
1656 panic("attempt to double-insert ia %p into hash table", ia);
1657 /* NOTREACHED */
1658 }
1659 TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1660 ia, ia_hash);
1661 IFA_ADDREF_LOCKED(&ia->ia_ifa);
1662 }
1663
1664 /*
1665 * Some point to point interfaces that are tunnels borrow the address from
1666 * an underlying interface (e.g. VPN server). In order for source address
1667 * selection logic to find the underlying interface first, we add the address
1668 * of borrowing point to point interfaces at the end of the list.
1669 * (see rdar://6733789)
1670 *
1671 * Caller must hold in_ifaddr_rwlock as writer.
1672 */
1673 static void
in_iahash_insert_ptp(struct in_ifaddr * ia)1674 in_iahash_insert_ptp(struct in_ifaddr *ia)
1675 {
1676 struct in_ifaddr *tmp_ifa;
1677 struct ifnet *tmp_ifp;
1678
1679 LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1680 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1681
1682 if (ia->ia_addr.sin_family != AF_INET) {
1683 panic("attempt to insert wrong ia %p into hash table", ia);
1684 /* NOTREACHED */
1685 } else if (IA_IS_HASHED(ia)) {
1686 panic("attempt to double-insert ia %p into hash table", ia);
1687 /* NOTREACHED */
1688 }
1689 IFA_UNLOCK(&ia->ia_ifa);
1690 TAILQ_FOREACH(tmp_ifa, INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1691 ia_hash) {
1692 IFA_LOCK(&tmp_ifa->ia_ifa);
1693 /* ia->ia_addr won't change, so check without lock */
1694 if (IA_SIN(tmp_ifa)->sin_addr.s_addr ==
1695 ia->ia_addr.sin_addr.s_addr) {
1696 IFA_UNLOCK(&tmp_ifa->ia_ifa);
1697 break;
1698 }
1699 IFA_UNLOCK(&tmp_ifa->ia_ifa);
1700 }
1701 tmp_ifp = (tmp_ifa == NULL) ? NULL : tmp_ifa->ia_ifp;
1702
1703 IFA_LOCK(&ia->ia_ifa);
1704 if (tmp_ifp == NULL) {
1705 TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1706 ia, ia_hash);
1707 } else {
1708 TAILQ_INSERT_TAIL(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1709 ia, ia_hash);
1710 }
1711 IFA_ADDREF_LOCKED(&ia->ia_ifa);
1712 }
1713
1714 /*
1715 * Initialize an interface's internet address
1716 * and routing table entry.
1717 */
1718 static int
in_ifinit(struct ifnet * ifp,struct in_ifaddr * ia,struct sockaddr_in * sin,int scrub)1719 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
1720 int scrub)
1721 {
1722 u_int32_t i = ntohl(sin->sin_addr.s_addr);
1723 struct sockaddr_in oldaddr;
1724 int flags = RTF_UP, error;
1725 struct ifaddr *ifa0;
1726 unsigned int cmd;
1727 int oldremoved = 0;
1728
1729 /* Take an extra reference for this routine */
1730 IFA_ADDREF(&ia->ia_ifa);
1731
1732 lck_rw_lock_exclusive(&in_ifaddr_rwlock);
1733 IFA_LOCK(&ia->ia_ifa);
1734 oldaddr = ia->ia_addr;
1735 if (IA_IS_HASHED(ia)) {
1736 oldremoved = 1;
1737 in_iahash_remove(ia);
1738 }
1739 ia->ia_addr = *sin;
1740 /*
1741 * Interface addresses should not contain port or sin_zero information.
1742 */
1743 SIN(&ia->ia_addr)->sin_family = AF_INET;
1744 SIN(&ia->ia_addr)->sin_len = sizeof(struct sockaddr_in);
1745 SIN(&ia->ia_addr)->sin_port = 0;
1746 bzero(&SIN(&ia->ia_addr)->sin_zero, sizeof(sin->sin_zero));
1747 if ((ifp->if_flags & IFF_POINTOPOINT)) {
1748 in_iahash_insert_ptp(ia);
1749 } else {
1750 in_iahash_insert(ia);
1751 }
1752 IFA_UNLOCK(&ia->ia_ifa);
1753 lck_rw_done(&in_ifaddr_rwlock);
1754
1755 /*
1756 * Give the interface a chance to initialize if this is its first
1757 * address, and to validate the address if necessary. Send down
1758 * SIOCSIFADDR for first address, and SIOCAIFADDR for alias(es).
1759 * We find the first IPV4 address assigned to it and check if this
1760 * is the same as the one passed into this routine.
1761 */
1762 ifa0 = ifa_ifpgetprimary(ifp, AF_INET);
1763 cmd = (&ia->ia_ifa == ifa0) ? SIOCSIFADDR : SIOCAIFADDR;
1764 error = ifnet_ioctl(ifp, PF_INET, cmd, ia);
1765 if (error == EOPNOTSUPP) {
1766 error = 0;
1767 }
1768 /*
1769 * If we've just sent down SIOCAIFADDR, send another ioctl down
1770 * for SIOCSIFADDR for the first IPV4 address of the interface,
1771 * because an address change on one of the addresses will result
1772 * in the removal of the previous first IPV4 address. KDP needs
1773 * be reconfigured with the current primary IPV4 address.
1774 */
1775 if (error == 0 && cmd == SIOCAIFADDR) {
1776 /*
1777 * NOTE: SIOCSIFADDR is defined with struct ifreq
1778 * as parameter, but here we are sending it down
1779 * to the interface with a pointer to struct ifaddr,
1780 * for legacy reasons.
1781 */
1782 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa0);
1783 if (error == EOPNOTSUPP) {
1784 error = 0;
1785 }
1786 }
1787
1788 /* Release reference from ifa_ifpgetprimary() */
1789 IFA_REMREF(ifa0);
1790
1791 if (error) {
1792 lck_rw_lock_exclusive(&in_ifaddr_rwlock);
1793 IFA_LOCK(&ia->ia_ifa);
1794 if (IA_IS_HASHED(ia)) {
1795 in_iahash_remove(ia);
1796 }
1797 ia->ia_addr = oldaddr;
1798 if (oldremoved) {
1799 if ((ifp->if_flags & IFF_POINTOPOINT)) {
1800 in_iahash_insert_ptp(ia);
1801 } else {
1802 in_iahash_insert(ia);
1803 }
1804 }
1805 IFA_UNLOCK(&ia->ia_ifa);
1806 lck_rw_done(&in_ifaddr_rwlock);
1807 /* Release extra reference taken above */
1808 IFA_REMREF(&ia->ia_ifa);
1809 return error;
1810 }
1811 lck_mtx_lock(rnh_lock);
1812 IFA_LOCK(&ia->ia_ifa);
1813 /*
1814 * Address has been initialized by the link resolver (ARP)
1815 * via ifnet_ioctl() above; it may now generate route(s).
1816 */
1817 ia->ia_ifa.ifa_debug &= ~IFD_NOTREADY;
1818 if (scrub) {
1819 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
1820 IFA_UNLOCK(&ia->ia_ifa);
1821 in_ifscrub(ifp, ia, 1);
1822 IFA_LOCK(&ia->ia_ifa);
1823 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1824 }
1825 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1826 if (IN_CLASSA(i)) {
1827 ia->ia_netmask = IN_CLASSA_NET;
1828 } else if (IN_CLASSB(i)) {
1829 ia->ia_netmask = IN_CLASSB_NET;
1830 } else {
1831 ia->ia_netmask = IN_CLASSC_NET;
1832 }
1833 /*
1834 * The subnet mask usually includes at least the standard network part,
1835 * but may may be smaller in the case of supernetting.
1836 * If it is set, we believe it.
1837 */
1838 if (ia->ia_subnetmask == 0) {
1839 ia->ia_subnetmask = ia->ia_netmask;
1840 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
1841 } else {
1842 ia->ia_netmask &= ia->ia_subnetmask;
1843 }
1844 ia->ia_net = i & ia->ia_netmask;
1845 ia->ia_subnet = i & ia->ia_subnetmask;
1846 in_socktrim(&ia->ia_sockmask);
1847 /*
1848 * Add route for the network.
1849 */
1850 ia->ia_ifa.ifa_metric = ifp->if_metric;
1851 if (ifp->if_flags & IFF_BROADCAST) {
1852 ia->ia_broadaddr.sin_addr.s_addr =
1853 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
1854 ia->ia_netbroadcast.s_addr =
1855 htonl(ia->ia_net | ~ia->ia_netmask);
1856 } else if (ifp->if_flags & IFF_LOOPBACK) {
1857 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1858 flags |= RTF_HOST;
1859 } else if (ifp->if_flags & IFF_POINTOPOINT) {
1860 if (ia->ia_dstaddr.sin_family != AF_INET) {
1861 IFA_UNLOCK(&ia->ia_ifa);
1862 lck_mtx_unlock(rnh_lock);
1863 /* Release extra reference taken above */
1864 IFA_REMREF(&ia->ia_ifa);
1865 return 0;
1866 }
1867 ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
1868 flags |= RTF_HOST;
1869 }
1870 IFA_UNLOCK(&ia->ia_ifa);
1871
1872 if ((error = rtinit_locked(&(ia->ia_ifa), RTM_ADD, flags)) == 0) {
1873 IFA_LOCK(&ia->ia_ifa);
1874 ia->ia_flags |= IFA_ROUTE;
1875 IFA_UNLOCK(&ia->ia_ifa);
1876 }
1877 lck_mtx_unlock(rnh_lock);
1878
1879 /* XXX check if the subnet route points to the same interface */
1880 if (error == EEXIST) {
1881 error = 0;
1882 }
1883
1884 /*
1885 * If the interface supports multicast, join the "all hosts"
1886 * multicast group on that interface.
1887 */
1888 if (ifp->if_flags & IFF_MULTICAST) {
1889 struct in_addr addr;
1890
1891 lck_mtx_lock(&ifp->if_addrconfig_lock);
1892 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
1893 if (ifp->if_allhostsinm == NULL) {
1894 struct in_multi *inm;
1895 inm = in_addmulti(&addr, ifp);
1896
1897 if (inm != NULL) {
1898 /*
1899 * Keep the reference on inm added by
1900 * in_addmulti above for storing the
1901 * pointer in allhostsinm.
1902 */
1903 ifp->if_allhostsinm = inm;
1904 } else {
1905 printf("%s: failed to add membership to "
1906 "all-hosts multicast address on %s\n",
1907 __func__, if_name(ifp));
1908 }
1909 }
1910 lck_mtx_unlock(&ifp->if_addrconfig_lock);
1911 }
1912
1913 /* Release extra reference taken above */
1914 IFA_REMREF(&ia->ia_ifa);
1915
1916 if (error == 0) {
1917 /* invalidate route caches */
1918 routegenid_inet_update();
1919 }
1920
1921 return error;
1922 }
1923
1924 /*
1925 * Return TRUE if the address might be a local broadcast address.
1926 */
1927 boolean_t
in_broadcast(struct in_addr in,struct ifnet * ifp)1928 in_broadcast(struct in_addr in, struct ifnet *ifp)
1929 {
1930 struct ifaddr *ifa;
1931 u_int32_t t;
1932
1933 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) {
1934 return TRUE;
1935 }
1936 if (!(ifp->if_flags & IFF_BROADCAST)) {
1937 return FALSE;
1938 }
1939 t = ntohl(in.s_addr);
1940
1941 /*
1942 * Look through the list of addresses for a match
1943 * with a broadcast address.
1944 */
1945 #define ia ((struct in_ifaddr *)ifa)
1946 ifnet_lock_shared(ifp);
1947 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1948 IFA_LOCK(ifa);
1949 if (ifa->ifa_addr->sa_family == AF_INET &&
1950 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
1951 in.s_addr == ia->ia_netbroadcast.s_addr ||
1952 /*
1953 * Check for old-style (host 0) broadcast.
1954 */
1955 t == ia->ia_subnet || t == ia->ia_net) &&
1956 /*
1957 * Check for an all one subnetmask. These
1958 * only exist when an interface gets a secondary
1959 * address.
1960 */
1961 ia->ia_subnetmask != (u_int32_t)0xffffffff) {
1962 IFA_UNLOCK(ifa);
1963 ifnet_lock_done(ifp);
1964 return TRUE;
1965 }
1966 IFA_UNLOCK(ifa);
1967 }
1968 ifnet_lock_done(ifp);
1969 return FALSE;
1970 #undef ia
1971 }
1972
1973 void
in_purgeaddrs(struct ifnet * ifp)1974 in_purgeaddrs(struct ifnet *ifp)
1975 {
1976 struct ifaddr **ifap;
1977 int err, i;
1978
1979 VERIFY(ifp != NULL);
1980
1981 /*
1982 * Be nice, and try the civilized way first. If we can't get
1983 * rid of them this way, then do it the rough way. We must
1984 * only get here during detach time, after the ifnet has been
1985 * removed from the global list and arrays.
1986 */
1987 err = ifnet_get_address_list_family_internal(ifp, &ifap, AF_INET, 1,
1988 M_WAITOK, 0);
1989 if (err == 0 && ifap != NULL) {
1990 struct ifreq ifr;
1991
1992 bzero(&ifr, sizeof(ifr));
1993 (void) snprintf(ifr.ifr_name, sizeof(ifr.ifr_name),
1994 "%s", if_name(ifp));
1995
1996 for (i = 0; ifap[i] != NULL; i++) {
1997 struct ifaddr *ifa;
1998
1999 ifa = ifap[i];
2000 IFA_LOCK(ifa);
2001 bcopy(ifa->ifa_addr, &ifr.ifr_addr,
2002 sizeof(struct sockaddr_in));
2003 IFA_UNLOCK(ifa);
2004 err = in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
2005 kernproc);
2006 /* if we lost the race, ignore it */
2007 if (err == EADDRNOTAVAIL) {
2008 err = 0;
2009 }
2010 if (err != 0) {
2011 char s_addr[MAX_IPv4_STR_LEN];
2012 char s_dstaddr[MAX_IPv4_STR_LEN];
2013 struct in_addr *s, *d;
2014
2015 IFA_LOCK(ifa);
2016 s = &((struct sockaddr_in *)
2017 (void *)ifa->ifa_addr)->sin_addr;
2018 d = &((struct sockaddr_in *)
2019 (void *)ifa->ifa_dstaddr)->sin_addr;
2020 (void) inet_ntop(AF_INET, &s->s_addr, s_addr,
2021 sizeof(s_addr));
2022 (void) inet_ntop(AF_INET, &d->s_addr, s_dstaddr,
2023 sizeof(s_dstaddr));
2024 IFA_UNLOCK(ifa);
2025
2026 printf("%s: SIOCDIFADDR ifp=%s ifa_addr=%s "
2027 "ifa_dstaddr=%s (err=%d)\n", __func__,
2028 ifp->if_xname, s_addr, s_dstaddr, err);
2029 }
2030 }
2031 ifnet_free_address_list(ifap);
2032 } else if (err != 0 && err != ENXIO) {
2033 printf("%s: error retrieving list of AF_INET addresses for "
2034 "ifp=%s (err=%d)\n", __func__, ifp->if_xname, err);
2035 }
2036 }
2037
2038 /*
2039 * Called as part of ip_init
2040 */
2041 void
in_ifaddr_init(void)2042 in_ifaddr_init(void)
2043 {
2044 size_t inifa_size = (inifa_debug == 0) ? sizeof(struct in_ifaddr) :
2045 sizeof(struct in_ifaddr_dbg);
2046
2047 in_multi_init();
2048
2049 inifa_zone = zone_create(INIFA_ZONE_NAME, inifa_size, ZC_NONE);
2050
2051 TAILQ_INIT(&inifa_trash_head);
2052 }
2053
2054 static struct in_ifaddr *
in_ifaddr_alloc(zalloc_flags_t how)2055 in_ifaddr_alloc(zalloc_flags_t how)
2056 {
2057 struct in_ifaddr *inifa;
2058
2059 inifa = zalloc_flags(inifa_zone, Z_ZERO | how);
2060 if (inifa != NULL) {
2061 inifa->ia_ifa.ifa_free = in_ifaddr_free;
2062 inifa->ia_ifa.ifa_debug |= IFD_ALLOC;
2063 inifa->ia_ifa.ifa_del_wc = &inifa->ia_ifa.ifa_debug;
2064 inifa->ia_ifa.ifa_del_waiters = 0;
2065 ifa_lock_init(&inifa->ia_ifa);
2066 if (inifa_debug != 0) {
2067 struct in_ifaddr_dbg *inifa_dbg =
2068 (struct in_ifaddr_dbg *)inifa;
2069 inifa->ia_ifa.ifa_debug |= IFD_DEBUG;
2070 inifa->ia_ifa.ifa_trace = in_ifaddr_trace;
2071 inifa->ia_ifa.ifa_attached = in_ifaddr_attached;
2072 inifa->ia_ifa.ifa_detached = in_ifaddr_detached;
2073 ctrace_record(&inifa_dbg->inifa_alloc);
2074 }
2075 }
2076 return inifa;
2077 }
2078
2079 static void
in_ifaddr_free(struct ifaddr * ifa)2080 in_ifaddr_free(struct ifaddr *ifa)
2081 {
2082 IFA_LOCK_ASSERT_HELD(ifa);
2083
2084 if (ifa->ifa_refcnt != 0) {
2085 panic("%s: ifa %p bad ref cnt", __func__, ifa);
2086 /* NOTREACHED */
2087 }
2088 if (!(ifa->ifa_debug & IFD_ALLOC)) {
2089 panic("%s: ifa %p cannot be freed", __func__, ifa);
2090 /* NOTREACHED */
2091 }
2092 if (ifa->ifa_debug & IFD_DEBUG) {
2093 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2094 ctrace_record(&inifa_dbg->inifa_free);
2095 bcopy(&inifa_dbg->inifa, &inifa_dbg->inifa_old,
2096 sizeof(struct in_ifaddr));
2097 if (ifa->ifa_debug & IFD_TRASHED) {
2098 /* Become a regular mutex, just in case */
2099 IFA_CONVERT_LOCK(ifa);
2100 lck_mtx_lock(&inifa_trash_lock);
2101 TAILQ_REMOVE(&inifa_trash_head, inifa_dbg,
2102 inifa_trash_link);
2103 lck_mtx_unlock(&inifa_trash_lock);
2104 ifa->ifa_debug &= ~IFD_TRASHED;
2105 }
2106 }
2107 IFA_UNLOCK(ifa);
2108 ifa_lock_destroy(ifa);
2109 bzero(ifa, sizeof(struct in_ifaddr));
2110 zfree(inifa_zone, ifa);
2111 }
2112
2113 static void
in_ifaddr_attached(struct ifaddr * ifa)2114 in_ifaddr_attached(struct ifaddr *ifa)
2115 {
2116 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2117
2118 IFA_LOCK_ASSERT_HELD(ifa);
2119
2120 if (!(ifa->ifa_debug & IFD_DEBUG)) {
2121 panic("%s: ifa %p has no debug structure", __func__, ifa);
2122 /* NOTREACHED */
2123 }
2124 if (ifa->ifa_debug & IFD_TRASHED) {
2125 /* Become a regular mutex, just in case */
2126 IFA_CONVERT_LOCK(ifa);
2127 lck_mtx_lock(&inifa_trash_lock);
2128 TAILQ_REMOVE(&inifa_trash_head, inifa_dbg, inifa_trash_link);
2129 lck_mtx_unlock(&inifa_trash_lock);
2130 ifa->ifa_debug &= ~IFD_TRASHED;
2131 }
2132 }
2133
2134 static void
in_ifaddr_detached(struct ifaddr * ifa)2135 in_ifaddr_detached(struct ifaddr *ifa)
2136 {
2137 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2138
2139 IFA_LOCK_ASSERT_HELD(ifa);
2140
2141 if (!(ifa->ifa_debug & IFD_DEBUG)) {
2142 panic("%s: ifa %p has no debug structure", __func__, ifa);
2143 /* NOTREACHED */
2144 } else if (ifa->ifa_debug & IFD_TRASHED) {
2145 panic("%s: ifa %p is already in trash list", __func__, ifa);
2146 /* NOTREACHED */
2147 }
2148 ifa->ifa_debug |= IFD_TRASHED;
2149 /* Become a regular mutex, just in case */
2150 IFA_CONVERT_LOCK(ifa);
2151 lck_mtx_lock(&inifa_trash_lock);
2152 TAILQ_INSERT_TAIL(&inifa_trash_head, inifa_dbg, inifa_trash_link);
2153 lck_mtx_unlock(&inifa_trash_lock);
2154 }
2155
2156 static void
in_ifaddr_trace(struct ifaddr * ifa,int refhold)2157 in_ifaddr_trace(struct ifaddr *ifa, int refhold)
2158 {
2159 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2160 ctrace_t *tr;
2161 u_int32_t idx;
2162 u_int16_t *cnt;
2163
2164 if (!(ifa->ifa_debug & IFD_DEBUG)) {
2165 panic("%s: ifa %p has no debug structure", __func__, ifa);
2166 /* NOTREACHED */
2167 }
2168 if (refhold) {
2169 cnt = &inifa_dbg->inifa_refhold_cnt;
2170 tr = inifa_dbg->inifa_refhold;
2171 } else {
2172 cnt = &inifa_dbg->inifa_refrele_cnt;
2173 tr = inifa_dbg->inifa_refrele;
2174 }
2175
2176 idx = atomic_add_16_ov(cnt, 1) % INIFA_TRACE_HIST_SIZE;
2177 ctrace_record(&tr[idx]);
2178 }
2179
2180 /*
2181 * Handle SIOCGASSOCIDS ioctl for PF_INET domain.
2182 */
2183 static int
in_getassocids(struct socket * so,uint32_t * cnt,user_addr_t aidp)2184 in_getassocids(struct socket *so, uint32_t *cnt, user_addr_t aidp)
2185 {
2186 struct inpcb *inp = sotoinpcb(so);
2187 sae_associd_t aid;
2188
2189 if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) {
2190 return EINVAL;
2191 }
2192
2193 /* INPCB has no concept of association */
2194 aid = SAE_ASSOCID_ANY;
2195 *cnt = 0;
2196
2197 /* just asking how many there are? */
2198 if (aidp == USER_ADDR_NULL) {
2199 return 0;
2200 }
2201
2202 return copyout(&aid, aidp, sizeof(aid));
2203 }
2204
2205 /*
2206 * Handle SIOCGCONNIDS ioctl for PF_INET domain.
2207 */
2208 static int
in_getconnids(struct socket * so,sae_associd_t aid,uint32_t * cnt,user_addr_t cidp)2209 in_getconnids(struct socket *so, sae_associd_t aid, uint32_t *cnt,
2210 user_addr_t cidp)
2211 {
2212 struct inpcb *inp = sotoinpcb(so);
2213 sae_connid_t cid;
2214
2215 if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) {
2216 return EINVAL;
2217 }
2218
2219 if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL) {
2220 return EINVAL;
2221 }
2222
2223 /* if connected, return 1 connection count */
2224 *cnt = ((so->so_state & SS_ISCONNECTED) ? 1 : 0);
2225
2226 /* just asking how many there are? */
2227 if (cidp == USER_ADDR_NULL) {
2228 return 0;
2229 }
2230
2231 /* if INPCB is connected, assign it connid 1 */
2232 cid = ((*cnt != 0) ? 1 : SAE_CONNID_ANY);
2233
2234 return copyout(&cid, cidp, sizeof(cid));
2235 }
2236
2237 /*
2238 * Handle SIOCGCONNINFO ioctl for PF_INET domain.
2239 */
2240 int
in_getconninfo(struct socket * so,sae_connid_t cid,uint32_t * flags,uint32_t * ifindex,int32_t * soerror,user_addr_t src,socklen_t * src_len,user_addr_t dst,socklen_t * dst_len,uint32_t * aux_type,user_addr_t aux_data,uint32_t * aux_len)2241 in_getconninfo(struct socket *so, sae_connid_t cid, uint32_t *flags,
2242 uint32_t *ifindex, int32_t *soerror, user_addr_t src, socklen_t *src_len,
2243 user_addr_t dst, socklen_t *dst_len, uint32_t *aux_type,
2244 user_addr_t aux_data, uint32_t *aux_len)
2245 {
2246 struct inpcb *inp = sotoinpcb(so);
2247 struct sockaddr_in sin;
2248 struct ifnet *ifp = NULL;
2249 int error = 0;
2250 u_int32_t copy_len = 0;
2251
2252 /*
2253 * Don't test for INPCB_STATE_DEAD since this may be called
2254 * after SOF_PCBCLEARING is set, e.g. after tcp_close().
2255 */
2256 if (inp == NULL) {
2257 error = EINVAL;
2258 goto out;
2259 }
2260
2261 if (cid != SAE_CONNID_ANY && cid != SAE_CONNID_ALL && cid != 1) {
2262 error = EINVAL;
2263 goto out;
2264 }
2265
2266 ifp = inp->inp_last_outifp;
2267 *ifindex = ((ifp != NULL) ? ifp->if_index : 0);
2268 *soerror = so->so_error;
2269 *flags = 0;
2270 if (so->so_state & SS_ISCONNECTED) {
2271 *flags |= (CIF_CONNECTED | CIF_PREFERRED);
2272 }
2273 if (inp->inp_flags & INP_BOUND_IF) {
2274 *flags |= CIF_BOUND_IF;
2275 }
2276 if (!(inp->inp_flags & INP_INADDR_ANY)) {
2277 *flags |= CIF_BOUND_IP;
2278 }
2279 if (!(inp->inp_flags & INP_ANONPORT)) {
2280 *flags |= CIF_BOUND_PORT;
2281 }
2282
2283 bzero(&sin, sizeof(sin));
2284 sin.sin_len = sizeof(sin);
2285 sin.sin_family = AF_INET;
2286
2287 /* source address and port */
2288 sin.sin_port = inp->inp_lport;
2289 sin.sin_addr.s_addr = inp->inp_laddr.s_addr;
2290 if (*src_len == 0) {
2291 *src_len = sin.sin_len;
2292 } else {
2293 if (src != USER_ADDR_NULL) {
2294 copy_len = min(*src_len, sizeof(sin));
2295 error = copyout(&sin, src, copy_len);
2296 if (error != 0) {
2297 goto out;
2298 }
2299 *src_len = copy_len;
2300 }
2301 }
2302
2303 /* destination address and port */
2304 sin.sin_port = inp->inp_fport;
2305 sin.sin_addr.s_addr = inp->inp_faddr.s_addr;
2306 if (*dst_len == 0) {
2307 *dst_len = sin.sin_len;
2308 } else {
2309 if (dst != USER_ADDR_NULL) {
2310 copy_len = min(*dst_len, sizeof(sin));
2311 error = copyout(&sin, dst, copy_len);
2312 if (error != 0) {
2313 goto out;
2314 }
2315 *dst_len = copy_len;
2316 }
2317 }
2318
2319 if (SOCK_PROTO(so) == IPPROTO_TCP) {
2320 struct conninfo_tcp tcp_ci;
2321
2322 *aux_type = CIAUX_TCP;
2323 if (*aux_len == 0) {
2324 *aux_len = sizeof(tcp_ci);
2325 } else {
2326 if (aux_data != USER_ADDR_NULL) {
2327 copy_len = min(*aux_len, sizeof(tcp_ci));
2328 bzero(&tcp_ci, sizeof(tcp_ci));
2329 tcp_getconninfo(so, &tcp_ci);
2330 error = copyout(&tcp_ci, aux_data, copy_len);
2331 if (error != 0) {
2332 goto out;
2333 }
2334 *aux_len = copy_len;
2335 }
2336 }
2337 } else {
2338 *aux_type = 0;
2339 *aux_len = 0;
2340 }
2341
2342 out:
2343 return error;
2344 }
2345
2346 struct in_llentry {
2347 struct llentry base;
2348 };
2349
2350 #define IN_LLTBL_DEFAULT_HSIZE 32
2351 #define IN_LLTBL_HASH(k, h) \
2352 ((((((((k) >> 8) ^ (k)) >> 8) ^ (k)) >> 8) ^ (k)) & ((h) - 1))
2353
2354 /*
2355 * Do actual deallocation of @lle.
2356 */
2357 static void
in_lltable_destroy_lle_unlocked(struct llentry * lle)2358 in_lltable_destroy_lle_unlocked(struct llentry *lle)
2359 {
2360 LLE_LOCK_DESTROY(lle);
2361 LLE_REQ_DESTROY(lle);
2362 struct in_llentry *in_lle = (struct in_llentry *)lle;
2363 kfree_type(struct in_llentry, in_lle);
2364 }
2365
2366 /*
2367 * Called by LLE_FREE_LOCKED when number of references
2368 * drops to zero.
2369 */
2370 static void
in_lltable_destroy_lle(struct llentry * lle)2371 in_lltable_destroy_lle(struct llentry *lle)
2372 {
2373 LLE_WUNLOCK(lle);
2374 in_lltable_destroy_lle_unlocked(lle);
2375 }
2376
2377 static struct llentry *
in_lltable_new(struct in_addr addr4,uint16_t flags)2378 in_lltable_new(struct in_addr addr4, uint16_t flags)
2379 {
2380 #pragma unused(flags)
2381 struct in_llentry *lle;
2382
2383 lle = kalloc_type(struct in_llentry, Z_NOWAIT | Z_ZERO);
2384 if (lle == NULL) { /* NB: caller generates msg */
2385 return NULL;
2386 }
2387
2388 /*
2389 * For IPv4 this will trigger "arpresolve" to generate
2390 * an ARP request.
2391 */
2392 lle->base.la_expire = net_uptime(); /* mark expired */
2393 lle->base.r_l3addr.addr4 = addr4;
2394 lle->base.lle_refcnt = 1;
2395 lle->base.lle_free = in_lltable_destroy_lle;
2396
2397 LLE_LOCK_INIT(&lle->base);
2398 LLE_REQ_INIT(&lle->base);
2399 //callout_init(&lle->base.lle_timer, 1);
2400
2401 return &lle->base;
2402 }
2403
2404 #define IN_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
2405 ((((d).s_addr ^ (a).s_addr) & (m).s_addr)) == 0 )
2406
2407 static int
in_lltable_match_prefix(const struct sockaddr * saddr,const struct sockaddr * smask,uint16_t flags,struct llentry * lle)2408 in_lltable_match_prefix(const struct sockaddr *saddr,
2409 const struct sockaddr *smask, uint16_t flags, struct llentry *lle)
2410 {
2411 struct in_addr addr, mask, lle_addr;
2412
2413 addr = ((const struct sockaddr_in *)(const void *)saddr)->sin_addr;
2414 mask = ((const struct sockaddr_in *)(const void *)smask)->sin_addr;
2415 lle_addr.s_addr = ntohl(lle->r_l3addr.addr4.s_addr);
2416
2417 if (IN_ARE_MASKED_ADDR_EQUAL(lle_addr, addr, mask) == 0) {
2418 return 0;
2419 }
2420
2421 if (lle->la_flags & LLE_IFADDR) {
2422 /*
2423 * Delete LLE_IFADDR records IFF address & flag matches.
2424 * Note that addr is the interface address within prefix
2425 * being matched.
2426 * Note also we should handle 'ifdown' cases without removing
2427 * ifaddr macs.
2428 */
2429 if (addr.s_addr == lle_addr.s_addr && (flags & LLE_STATIC) != 0) {
2430 return 1;
2431 }
2432 return 0;
2433 }
2434
2435 /* flags & LLE_STATIC means deleting both dynamic and static entries */
2436 if ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC)) {
2437 return 1;
2438 }
2439
2440 return 0;
2441 }
2442
2443 static void
in_lltable_free_entry(struct lltable * llt,struct llentry * lle)2444 in_lltable_free_entry(struct lltable *llt, struct llentry *lle)
2445 {
2446 struct ifnet *ifp;
2447 size_t pkts_dropped;
2448
2449 LLE_WLOCK_ASSERT(lle);
2450 KASSERT(llt != NULL, ("lltable is NULL"));
2451
2452 /* Unlink entry from table if not already */
2453 if ((lle->la_flags & LLE_LINKED) != 0) {
2454 ifp = llt->llt_ifp;
2455 IF_AFDATA_WLOCK_ASSERT(ifp, llt->llt_af);
2456 lltable_unlink_entry(llt, lle);
2457 }
2458
2459 #if 0
2460 /* cancel timer */
2461 if (callout_stop(&lle->lle_timer) > 0) {
2462 LLE_REMREF(lle);
2463 }
2464 #endif
2465 /* Drop hold queue */
2466 pkts_dropped = llentry_free(lle);
2467 arpstat.dropped += pkts_dropped;
2468 }
2469
2470
2471 static int
in_lltable_rtcheck(struct ifnet * ifp,uint16_t flags,const struct sockaddr * l3addr)2472 in_lltable_rtcheck(struct ifnet *ifp, uint16_t flags, const struct sockaddr *l3addr)
2473 {
2474 #pragma unused(flags)
2475 struct rtentry *rt;
2476
2477 KASSERT(l3addr->sa_family == AF_INET,
2478 ("sin_family %d", l3addr->sa_family));
2479
2480 /* XXX rtalloc1 should take a const param */
2481 rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
2482 if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
2483 log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
2484 inet_ntoa(((const struct sockaddr_in *)(const void *)l3addr)->sin_addr));
2485 if (rt != NULL) {
2486 rtfree_locked(rt);
2487 }
2488 return EINVAL;
2489 }
2490 rtfree_locked(rt);
2491 return 0;
2492 }
2493
2494 static inline uint32_t
in_lltable_hash_dst(const struct in_addr dst,uint32_t hsize)2495 in_lltable_hash_dst(const struct in_addr dst, uint32_t hsize)
2496 {
2497 return IN_LLTBL_HASH(dst.s_addr, hsize);
2498 }
2499
2500 static uint32_t
in_lltable_hash(const struct llentry * lle,uint32_t hsize)2501 in_lltable_hash(const struct llentry *lle, uint32_t hsize)
2502 {
2503 return in_lltable_hash_dst(lle->r_l3addr.addr4, hsize);
2504 }
2505
2506
2507 static void
in_lltable_fill_sa_entry(const struct llentry * lle,struct sockaddr * sa)2508 in_lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
2509 {
2510 struct sockaddr_in *sin;
2511
2512 sin = (struct sockaddr_in *)(void *)sa;
2513 bzero(sin, sizeof(*sin));
2514 sin->sin_family = AF_INET;
2515 sin->sin_len = sizeof(*sin);
2516 sin->sin_addr = lle->r_l3addr.addr4;
2517 }
2518
2519 static inline struct llentry *
in_lltable_find_dst(struct lltable * llt,struct in_addr dst)2520 in_lltable_find_dst(struct lltable *llt, struct in_addr dst)
2521 {
2522 struct llentry *lle;
2523 struct llentries *lleh;
2524 u_int hashidx;
2525
2526 hashidx = in_lltable_hash_dst(dst, llt->llt_hsize);
2527 lleh = &llt->lle_head[hashidx];
2528 LIST_FOREACH(lle, lleh, lle_next) {
2529 if (lle->la_flags & LLE_DELETED) {
2530 continue;
2531 }
2532 if (lle->r_l3addr.addr4.s_addr == dst.s_addr) {
2533 break;
2534 }
2535 }
2536
2537 return lle;
2538 }
2539
2540 static void
in_lltable_delete_entry(struct lltable * llt,struct llentry * lle)2541 in_lltable_delete_entry(struct lltable *llt, struct llentry *lle)
2542 {
2543 #pragma unused(llt)
2544 lle->la_flags |= LLE_DELETED;
2545 //EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED);
2546 #ifdef DIAGNOSTIC
2547 log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
2548 #endif
2549 llentry_free(lle);
2550 }
2551
2552 static struct llentry *
in_lltable_alloc(struct lltable * llt,uint16_t flags,const struct sockaddr * l3addr)2553 in_lltable_alloc(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr)
2554 {
2555 const struct sockaddr_in *sin = (const struct sockaddr_in *) (const void *)l3addr;
2556 struct ifnet *ifp = llt->llt_ifp;
2557 struct llentry *lle;
2558
2559 KASSERT(l3addr->sa_family == AF_INET,
2560 ("sin_family %d", l3addr->sa_family));
2561
2562 /*
2563 * A route that covers the given address must have
2564 * been installed 1st because we are doing a resolution,
2565 * verify this.
2566 */
2567 if (!(flags & LLE_IFADDR) &&
2568 in_lltable_rtcheck(ifp, flags, l3addr) != 0) {
2569 return NULL;
2570 }
2571
2572 lle = in_lltable_new(sin->sin_addr, flags);
2573 if (lle == NULL) {
2574 log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
2575 return NULL;
2576 }
2577 lle->la_flags = flags & ~LLE_CREATE;
2578 if (flags & LLE_STATIC) {
2579 lle->r_flags |= RLLE_VALID;
2580 }
2581 if ((flags & LLE_IFADDR) == LLE_IFADDR) {
2582 lltable_set_entry_addr(ifp, lle, LLADDR(SDL(ifp->if_lladdr->ifa_addr)));
2583 lle->la_flags |= LLE_STATIC;
2584 lle->r_flags |= (RLLE_VALID | RLLE_IFADDR);
2585 }
2586 return lle;
2587 }
2588
2589 /*
2590 * Return NULL if not found or marked for deletion.
2591 * If found return lle read locked.
2592 */
2593 static struct llentry *
in_lltable_lookup(struct lltable * llt,uint16_t flags,const struct sockaddr * l3addr)2594 in_lltable_lookup(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr)
2595 {
2596 const struct sockaddr_in *sin = (const struct sockaddr_in *)(const void *)l3addr;
2597 struct llentry *lle;
2598
2599 IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp, llt->llt_af);
2600
2601 KASSERT(l3addr->sa_family == AF_INET,
2602 ("sin_family %d", l3addr->sa_family));
2603 lle = in_lltable_find_dst(llt, sin->sin_addr);
2604
2605 if (lle == NULL) {
2606 return NULL;
2607 }
2608
2609 KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=
2610 (LLE_UNLOCKED | LLE_EXCLUSIVE), ("wrong lle request flags: 0x%X",
2611 flags));
2612
2613 if (flags & LLE_UNLOCKED) {
2614 return lle;
2615 }
2616
2617 if (flags & LLE_EXCLUSIVE) {
2618 LLE_WLOCK(lle);
2619 } else {
2620 LLE_RLOCK(lle);
2621 }
2622
2623 return lle;
2624 }
2625
2626 static int
in_lltable_dump_entry(struct lltable * llt,struct llentry * lle,struct sysctl_req * wr)2627 in_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
2628 struct sysctl_req *wr)
2629 {
2630 struct ifnet *ifp = llt->llt_ifp;
2631 /* XXX stack use */
2632 struct {
2633 struct rt_msghdr rtm;
2634 struct sockaddr_in sin;
2635 struct sockaddr_dl sdl;
2636 } arpc;
2637 struct sockaddr_dl *sdl;
2638 int error;
2639
2640 bzero(&arpc, sizeof(arpc));
2641 /* skip deleted entries */
2642 if ((lle->la_flags & LLE_DELETED) == LLE_DELETED) {
2643 return 0;
2644 }
2645 /* Skip if jailed and not a valid IP of the prison. */
2646 lltable_fill_sa_entry(lle, (struct sockaddr *)&arpc.sin);
2647 /*
2648 * produce a msg made of:
2649 * struct rt_msghdr;
2650 * struct sockaddr_in; (IPv4)
2651 * struct sockaddr_dl;
2652 */
2653 arpc.rtm.rtm_msglen = sizeof(arpc);
2654 arpc.rtm.rtm_version = RTM_VERSION;
2655 arpc.rtm.rtm_type = RTM_GET;
2656 arpc.rtm.rtm_flags = RTF_UP;
2657 arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
2658
2659 /* publish */
2660 if (lle->la_flags & LLE_PUB) {
2661 arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
2662 }
2663
2664 sdl = &arpc.sdl;
2665 sdl->sdl_family = AF_LINK;
2666 sdl->sdl_len = sizeof(*sdl);
2667 sdl->sdl_index = ifp->if_index;
2668 sdl->sdl_type = ifp->if_type;
2669 if ((lle->la_flags & LLE_VALID) == LLE_VALID) {
2670 sdl->sdl_alen = ifp->if_addrlen;
2671 bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
2672 } else {
2673 sdl->sdl_alen = 0;
2674 bzero(LLADDR(sdl), ifp->if_addrlen);
2675 }
2676
2677 arpc.rtm.rtm_rmx.rmx_expire =
2678 lle->la_flags & LLE_STATIC ? 0 : (int32_t)lle->la_expire;
2679 arpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
2680 if (lle->la_flags & LLE_STATIC) {
2681 arpc.rtm.rtm_flags |= RTF_STATIC;
2682 }
2683 if (lle->la_flags & LLE_IFADDR) {
2684 arpc.rtm.rtm_flags |= RTF_PINNED;
2685 }
2686 arpc.rtm.rtm_flags |= RTF_PINNED;
2687 arpc.rtm.rtm_index = ifp->if_index;
2688 error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
2689
2690 return error;
2691 }
2692
2693 static struct lltable *
in_lltattach(struct ifnet * ifp)2694 in_lltattach(struct ifnet *ifp)
2695 {
2696 struct lltable *llt;
2697
2698 llt = lltable_allocate_htbl(IN_LLTBL_DEFAULT_HSIZE);
2699 llt->llt_af = AF_INET;
2700 llt->llt_ifp = ifp;
2701
2702 llt->llt_lookup = in_lltable_lookup;
2703 llt->llt_alloc_entry = in_lltable_alloc;
2704 llt->llt_delete_entry = in_lltable_delete_entry;
2705 llt->llt_dump_entry = in_lltable_dump_entry;
2706 llt->llt_hash = in_lltable_hash;
2707 llt->llt_fill_sa_entry = in_lltable_fill_sa_entry;
2708 llt->llt_free_entry = in_lltable_free_entry;
2709 llt->llt_match_prefix = in_lltable_match_prefix;
2710 lltable_link(llt);
2711
2712 return llt;
2713 }
2714
2715 struct in_ifaddr*
inifa_ifpwithflag(struct ifnet * ifp,uint32_t flag)2716 inifa_ifpwithflag(struct ifnet * ifp, uint32_t flag)
2717 {
2718 struct ifaddr *ifa;
2719
2720 ifnet_lock_shared(ifp);
2721 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_link)
2722 {
2723 IFA_LOCK_SPIN(ifa);
2724 if (ifa->ifa_addr->sa_family != AF_INET) {
2725 IFA_UNLOCK(ifa);
2726 continue;
2727 }
2728 if ((((struct in_ifaddr *)ifa)->ia_flags & flag) == flag) {
2729 IFA_ADDREF_LOCKED(ifa);
2730 IFA_UNLOCK(ifa);
2731 break;
2732 }
2733 IFA_UNLOCK(ifa);
2734 }
2735 ifnet_lock_done(ifp);
2736
2737 return (struct in_ifaddr *)ifa;
2738 }
2739
2740 struct in_ifaddr *
inifa_ifpclatv4(struct ifnet * ifp)2741 inifa_ifpclatv4(struct ifnet * ifp)
2742 {
2743 struct ifaddr *ifa;
2744
2745 ifnet_lock_shared(ifp);
2746 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_link)
2747 {
2748 uint32_t addr = 0;
2749 IFA_LOCK_SPIN(ifa);
2750 if (ifa->ifa_addr->sa_family != AF_INET) {
2751 IFA_UNLOCK(ifa);
2752 continue;
2753 }
2754
2755 addr = ntohl(SIN(ifa->ifa_addr)->sin_addr.s_addr);
2756 if (!IN_LINKLOCAL(addr) &&
2757 !IN_LOOPBACK(addr)) {
2758 IFA_ADDREF_LOCKED(ifa);
2759 IFA_UNLOCK(ifa);
2760 break;
2761 }
2762 IFA_UNLOCK(ifa);
2763 }
2764 ifnet_lock_done(ifp);
2765
2766 return (struct in_ifaddr *)ifa;
2767 }
2768
2769 /*
2770 * IPPROTO_xxx.
2771 *
2772 * The switch statement below does nothing at runtime, as it serves as a
2773 * compile time check to ensure that all of the IPPROTO_xxx constants are
2774 * unique. This works as long as this routine gets updated each time a
2775 * new IPPROTO_xxx constant gets added.
2776 *
2777 * Any failures at compile time indicates duplicated IPPROTO_xxx values.
2778 */
2779 static __attribute__((unused)) void
ipproto_cassert(void)2780 ipproto_cassert(void)
2781 {
2782 /*
2783 * This is equivalent to _CASSERT() and the compiler wouldn't
2784 * generate any instructions, thus for compile time only.
2785 */
2786 switch ((u_int16_t)0) {
2787 /* bsd/netinet/in.h */
2788 case IPPROTO_IP:
2789 // case IPPROTO_HOPOPTS: // same value as IPPROTO_IP
2790 case IPPROTO_ICMP:
2791 case IPPROTO_IGMP:
2792 case IPPROTO_GGP:
2793 case IPPROTO_IPV4:
2794 // #define IPPROTO_IPIP IPPROTO_IPV4
2795 case IPPROTO_TCP:
2796 case IPPROTO_ST:
2797 case IPPROTO_EGP:
2798 case IPPROTO_PIGP:
2799 case IPPROTO_RCCMON:
2800 case IPPROTO_NVPII:
2801 case IPPROTO_PUP:
2802 case IPPROTO_ARGUS:
2803 case IPPROTO_EMCON:
2804 case IPPROTO_XNET:
2805 case IPPROTO_CHAOS:
2806 case IPPROTO_UDP:
2807 case IPPROTO_MUX:
2808 case IPPROTO_MEAS:
2809 case IPPROTO_HMP:
2810 case IPPROTO_PRM:
2811 case IPPROTO_IDP:
2812 case IPPROTO_TRUNK1:
2813 case IPPROTO_TRUNK2:
2814 case IPPROTO_LEAF1:
2815 case IPPROTO_LEAF2:
2816 case IPPROTO_RDP:
2817 case IPPROTO_IRTP:
2818 case IPPROTO_TP:
2819 case IPPROTO_BLT:
2820 case IPPROTO_NSP:
2821 case IPPROTO_INP:
2822 case IPPROTO_SEP:
2823 case IPPROTO_3PC:
2824 case IPPROTO_IDPR:
2825 case IPPROTO_XTP:
2826 case IPPROTO_DDP:
2827 case IPPROTO_CMTP:
2828 case IPPROTO_TPXX:
2829 case IPPROTO_IL:
2830 case IPPROTO_IPV6:
2831 case IPPROTO_SDRP:
2832 case IPPROTO_ROUTING:
2833 case IPPROTO_FRAGMENT:
2834 case IPPROTO_IDRP:
2835 case IPPROTO_RSVP:
2836 case IPPROTO_GRE:
2837 case IPPROTO_MHRP:
2838 case IPPROTO_BHA:
2839 case IPPROTO_ESP:
2840 case IPPROTO_AH:
2841 case IPPROTO_INLSP:
2842 case IPPROTO_SWIPE:
2843 case IPPROTO_NHRP:
2844 case IPPROTO_ICMPV6:
2845 case IPPROTO_NONE:
2846 case IPPROTO_DSTOPTS:
2847 case IPPROTO_AHIP:
2848 case IPPROTO_CFTP:
2849 case IPPROTO_HELLO:
2850 case IPPROTO_SATEXPAK:
2851 case IPPROTO_KRYPTOLAN:
2852 case IPPROTO_RVD:
2853 case IPPROTO_IPPC:
2854 case IPPROTO_ADFS:
2855 case IPPROTO_SATMON:
2856 case IPPROTO_VISA:
2857 case IPPROTO_IPCV:
2858 case IPPROTO_CPNX:
2859 case IPPROTO_CPHB:
2860 case IPPROTO_WSN:
2861 case IPPROTO_PVP:
2862 case IPPROTO_BRSATMON:
2863 case IPPROTO_ND:
2864 case IPPROTO_WBMON:
2865 case IPPROTO_WBEXPAK:
2866 case IPPROTO_EON:
2867 case IPPROTO_VMTP:
2868 case IPPROTO_SVMTP:
2869 case IPPROTO_VINES:
2870 case IPPROTO_TTP:
2871 case IPPROTO_IGP:
2872 case IPPROTO_DGP:
2873 case IPPROTO_TCF:
2874 case IPPROTO_IGRP:
2875 case IPPROTO_OSPFIGP:
2876 case IPPROTO_SRPC:
2877 case IPPROTO_LARP:
2878 case IPPROTO_MTP:
2879 case IPPROTO_AX25:
2880 case IPPROTO_IPEIP:
2881 case IPPROTO_MICP:
2882 case IPPROTO_SCCSP:
2883 case IPPROTO_ETHERIP:
2884 case IPPROTO_ENCAP:
2885 case IPPROTO_APES:
2886 case IPPROTO_GMTP:
2887 case IPPROTO_PIM:
2888 case IPPROTO_IPCOMP:
2889 case IPPROTO_PGM:
2890 case IPPROTO_SCTP:
2891 case IPPROTO_DIVERT:
2892 case IPPROTO_RAW:
2893 case IPPROTO_MAX:
2894 case IPPROTO_DONE:
2895
2896 /* bsd/netinet/in_private.h */
2897 case IPPROTO_QUIC:
2898 ;
2899 }
2900 }
2901
2902 static __attribute__((unused)) void
ipsockopt_cassert(void)2903 ipsockopt_cassert(void)
2904 {
2905 switch ((int)0) {
2906 case 0:
2907
2908 /* bsd/netinet/in.h */
2909 case IP_OPTIONS:
2910 case IP_HDRINCL:
2911 case IP_TOS:
2912 case IP_TTL:
2913 case IP_RECVOPTS:
2914 case IP_RECVRETOPTS:
2915 case IP_RECVDSTADDR:
2916 case IP_RETOPTS:
2917 case IP_MULTICAST_IF:
2918 case IP_MULTICAST_TTL:
2919 case IP_MULTICAST_LOOP:
2920 case IP_ADD_MEMBERSHIP:
2921 case IP_DROP_MEMBERSHIP:
2922 case IP_MULTICAST_VIF:
2923 case IP_RSVP_ON:
2924 case IP_RSVP_OFF:
2925 case IP_RSVP_VIF_ON:
2926 case IP_RSVP_VIF_OFF:
2927 case IP_PORTRANGE:
2928 case IP_RECVIF:
2929 case IP_IPSEC_POLICY:
2930 case IP_FAITH:
2931 #ifdef __APPLE__
2932 case IP_STRIPHDR:
2933 #endif
2934 case IP_RECVTTL:
2935 case IP_BOUND_IF:
2936 case IP_PKTINFO:
2937 // #define IP_RECVPKTINFO IP_PKTINFO
2938 case IP_RECVTOS:
2939 case IP_DONTFRAG:
2940 case IP_FW_ADD:
2941 case IP_FW_DEL:
2942 case IP_FW_FLUSH:
2943 case IP_FW_ZERO:
2944 case IP_FW_GET:
2945 case IP_FW_RESETLOG:
2946 case IP_OLD_FW_ADD:
2947 case IP_OLD_FW_DEL:
2948 case IP_OLD_FW_FLUSH:
2949 case IP_OLD_FW_ZERO:
2950 case IP_OLD_FW_GET:
2951 case IP_NAT__XXX:
2952 case IP_OLD_FW_RESETLOG:
2953 case IP_DUMMYNET_CONFIGURE:
2954 case IP_DUMMYNET_DEL:
2955 case IP_DUMMYNET_FLUSH:
2956 case IP_DUMMYNET_GET:
2957 case IP_TRAFFIC_MGT_BACKGROUND:
2958 case IP_MULTICAST_IFINDEX:
2959 case IP_ADD_SOURCE_MEMBERSHIP:
2960 case IP_DROP_SOURCE_MEMBERSHIP:
2961 case IP_BLOCK_SOURCE:
2962 case IP_UNBLOCK_SOURCE:
2963 case IP_MSFILTER:
2964 case MCAST_JOIN_GROUP:
2965 case MCAST_LEAVE_GROUP:
2966 case MCAST_JOIN_SOURCE_GROUP:
2967 case MCAST_LEAVE_SOURCE_GROUP:
2968 case MCAST_BLOCK_SOURCE:
2969 case MCAST_UNBLOCK_SOURCE:
2970
2971 /* bsd/netinet/in_private.h */
2972 case IP_NO_IFT_CELLULAR:
2973 // #define IP_NO_IFT_PDP IP_NO_IFT_CELLULAR /* deprecated */
2974 case IP_OUT_IF:
2975 ;
2976 }
2977 }
2978