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