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