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