]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/in.c
xnu-2050.48.11.tar.gz
[apple/xnu.git] / bsd / netinet / in.c
CommitLineData
1c79356b 1/*
6d2010ae 2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 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.
8f6c56a5 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.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
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.
8f6c56a5 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
9bccf70c 61 * $FreeBSD: src/sys/netinet/in.c,v 1.44.2.5 2001/08/13 16:26:17 ume Exp $
1c79356b
A
62 */
63
64#include <sys/param.h>
65#include <sys/systm.h>
66#include <sys/sockio.h>
67#include <sys/socketvar.h>
68#include <sys/malloc.h>
69#include <sys/proc.h>
70#include <sys/socket.h>
71#include <sys/kernel.h>
72#include <sys/sysctl.h>
73#include <sys/kern_event.h>
91447636 74#include <sys/syslog.h>
6d2010ae 75#include <sys/mcache.h>
b0d623f7 76#include <kern/zalloc.h>
1c79356b 77
2d21ac55
A
78#include <pexpert/pexpert.h>
79
1c79356b 80#include <net/if.h>
1c79356b 81#include <net/if_types.h>
9bccf70c 82#include <net/route.h>
2d21ac55 83#include <net/kpi_protocol.h>
1c79356b
A
84
85#include <netinet/in.h>
86#include <netinet/in_var.h>
87#include <netinet/in_pcb.h>
88
89#include <netinet/igmp_var.h>
90#include <net/dlil.h>
91
92#include <netinet/ip_var.h>
93
94#include <netinet/tcp.h>
95#include <netinet/tcp_timer.h>
96#include <netinet/tcp_var.h>
97
98#include <sys/file.h>
99
b0d623f7
A
100#if PF
101#include <net/pfvar.h>
102#endif /* PF */
1c79356b 103
91447636
A
104static int in_mask2len(struct in_addr *);
105static void in_len2mask(struct in_addr *, int);
316670eb
A
106static int in_lifaddr_ioctl(struct socket *, u_long, struct if_laddrreq *,
107 struct ifnet *, struct proc *);
108static int in_setrouter(struct ifnet *, int);
1c79356b 109
91447636
A
110static void in_socktrim(struct sockaddr_in *);
111static int in_ifinit(struct ifnet *,
112 struct in_ifaddr *, struct sockaddr_in *, int);
1c79356b 113
b0d623f7
A
114#define IA_HASH_INIT(ia) { \
115 (ia)->ia_hash.tqe_next = (void *)(uintptr_t)-1; \
116 (ia)->ia_hash.tqe_prev = (void *)(uintptr_t)-1; \
117}
118
119#define IA_IS_HASHED(ia) \
120 (!((ia)->ia_hash.tqe_next == (void *)(uintptr_t)-1 || \
121 (ia)->ia_hash.tqe_prev == (void *)(uintptr_t)-1))
122
123static void in_iahash_remove(struct in_ifaddr *);
124static void in_iahash_insert(struct in_ifaddr *);
125static void in_iahash_insert_ptp(struct in_ifaddr *);
126static struct in_ifaddr *in_ifaddr_alloc(int);
6d2010ae
A
127static void in_ifaddr_attached(struct ifaddr *);
128static void in_ifaddr_detached(struct ifaddr *);
b0d623f7
A
129static void in_ifaddr_free(struct ifaddr *);
130static void in_ifaddr_trace(struct ifaddr *, int);
131
1c79356b 132static int subnetsarelocal = 0;
6d2010ae 133SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW | CTLFLAG_LOCKED,
1c79356b
A
134 &subnetsarelocal, 0, "");
135
91447636
A
136/* Track whether or not the SIOCARPIPLL ioctl has been called */
137__private_extern__ u_int32_t ipv4_ll_arp_aware = 0;
1c79356b 138
6d2010ae
A
139#define INIFA_TRACE_HIST_SIZE 32 /* size of trace history */
140
141/* For gdb */
142__private_extern__ unsigned int inifa_trace_hist_size = INIFA_TRACE_HIST_SIZE;
143
b0d623f7
A
144struct in_ifaddr_dbg {
145 struct in_ifaddr inifa; /* in_ifaddr */
146 struct in_ifaddr inifa_old; /* saved in_ifaddr */
6d2010ae
A
147 u_int16_t inifa_refhold_cnt; /* # of IFA_ADDREF */
148 u_int16_t inifa_refrele_cnt; /* # of IFA_REMREF */
b0d623f7
A
149 /*
150 * Alloc and free callers.
151 */
152 ctrace_t inifa_alloc;
153 ctrace_t inifa_free;
154 /*
6d2010ae 155 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
b0d623f7 156 */
6d2010ae
A
157 ctrace_t inifa_refhold[INIFA_TRACE_HIST_SIZE];
158 ctrace_t inifa_refrele[INIFA_TRACE_HIST_SIZE];
159 /*
160 * Trash list linkage
161 */
162 TAILQ_ENTRY(in_ifaddr_dbg) inifa_trash_link;
b0d623f7
A
163};
164
6d2010ae
A
165/* List of trash in_ifaddr entries protected by inifa_trash_lock */
166static TAILQ_HEAD(, in_ifaddr_dbg) inifa_trash_head;
167static decl_lck_mtx_data(, inifa_trash_lock);
168
169#if DEBUG
170static unsigned int inifa_debug = 1; /* debugging (enabled) */
171#else
172static unsigned int inifa_debug; /* debugging (disabled) */
173#endif /* !DEBUG */
b0d623f7
A
174static unsigned int inifa_size; /* size of zone element */
175static struct zone *inifa_zone; /* zone for in_ifaddr */
176
177#define INIFA_ZONE_MAX 64 /* maximum elements in zone */
178#define INIFA_ZONE_NAME "in_ifaddr" /* zone name */
179
6d2010ae
A
180/*
181 * Return 1 if the address is
182 * - loopback
183 * - unicast or multicast link local
184 * - routed via a link level gateway
185 * - belongs to a directly connected (sub)net
186 */
2d21ac55
A
187int
188inaddr_local(struct in_addr in)
189{
190 struct rtentry *rt;
191 struct sockaddr_in sin;
192 int local = 0;
193
6d2010ae
A
194 if (ntohl(in.s_addr) == INADDR_LOOPBACK || IN_LINKLOCAL(ntohl(in.s_addr))) {
195 local = 1;
196 } else if (ntohl(in.s_addr) >= INADDR_UNSPEC_GROUP &&
197 ntohl(in.s_addr) <= INADDR_MAX_LOCAL_GROUP) {
2d21ac55 198 local = 1;
2d21ac55 199 } else {
6d2010ae
A
200 sin.sin_family = AF_INET;
201 sin.sin_len = sizeof (sin);
202 sin.sin_addr = in;
203 rt = rtalloc1((struct sockaddr *)&sin, 0, 0);
204
205 if (rt != NULL) {
206 RT_LOCK_SPIN(rt);
207 if (rt->rt_gateway->sa_family == AF_LINK ||
208 (rt->rt_ifp->if_flags & IFF_LOOPBACK))
209 local = 1;
210 RT_UNLOCK(rt);
211 rtfree(rt);
212 } else {
213 local = in_localaddr(in);
214 }
2d21ac55
A
215 }
216 return (local);
217}
218
1c79356b
A
219/*
220 * Return 1 if an internet address is for a ``local'' host
221 * (one to which we have a connection). If subnetsarelocal
222 * is true, this includes other subnets of the local net.
223 * Otherwise, it includes only the directly-connected (sub)nets.
224 */
225int
2d21ac55 226in_localaddr(struct in_addr in)
1c79356b 227{
b0d623f7 228 u_int32_t i = ntohl(in.s_addr);
91447636 229 struct in_ifaddr *ia;
1c79356b
A
230
231 if (subnetsarelocal) {
b0d623f7 232 lck_rw_lock_shared(in_ifaddr_rwlock);
1c79356b 233 for (ia = in_ifaddrhead.tqh_first; ia;
6d2010ae
A
234 ia = ia->ia_link.tqe_next) {
235 IFA_LOCK(&ia->ia_ifa);
91447636 236 if ((i & ia->ia_netmask) == ia->ia_net) {
6d2010ae 237 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7 238 lck_rw_done(in_ifaddr_rwlock);
1c79356b 239 return (1);
91447636 240 }
6d2010ae
A
241 IFA_UNLOCK(&ia->ia_ifa);
242 }
b0d623f7 243 lck_rw_done(in_ifaddr_rwlock);
1c79356b 244 } else {
b0d623f7 245 lck_rw_lock_shared(in_ifaddr_rwlock);
1c79356b 246 for (ia = in_ifaddrhead.tqh_first; ia;
6d2010ae
A
247 ia = ia->ia_link.tqe_next) {
248 IFA_LOCK(&ia->ia_ifa);
91447636 249 if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
6d2010ae 250 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7 251 lck_rw_done(in_ifaddr_rwlock);
1c79356b 252 return (1);
91447636 253 }
6d2010ae
A
254 IFA_UNLOCK(&ia->ia_ifa);
255 }
b0d623f7 256 lck_rw_done(in_ifaddr_rwlock);
1c79356b
A
257 }
258 return (0);
259}
260
261/*
262 * Determine whether an IP address is in a reserved set of addresses
263 * that may not be forwarded, or whether datagrams to that destination
264 * may be forwarded.
265 */
266int
2d21ac55 267in_canforward(struct in_addr in)
1c79356b 268{
b0d623f7
A
269 u_int32_t i = ntohl(in.s_addr);
270 u_int32_t net;
1c79356b
A
271
272 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
273 return (0);
274 if (IN_CLASSA(i)) {
275 net = i & IN_CLASSA_NET;
276 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
277 return (0);
278 }
279 return (1);
280}
281
282/*
283 * Trim a mask in a sockaddr
284 */
285static void
2d21ac55 286in_socktrim(struct sockaddr_in *ap)
1c79356b 287{
91447636
A
288 char *cplim = (char *) &ap->sin_addr;
289 char *cp = (char *) (&ap->sin_addr + 1);
1c79356b
A
290
291 ap->sin_len = 0;
292 while (--cp >= cplim)
293 if (*cp) {
294 (ap)->sin_len = cp - (char *) (ap) + 1;
295 break;
296 }
297}
298
299static int
2d21ac55 300in_mask2len(struct in_addr *mask)
1c79356b 301{
2d21ac55 302 size_t x, y;
1c79356b
A
303 u_char *p;
304
305 p = (u_char *)mask;
306 for (x = 0; x < sizeof(*mask); x++) {
307 if (p[x] != 0xff)
308 break;
309 }
310 y = 0;
311 if (x < sizeof(*mask)) {
312 for (y = 0; y < 8; y++) {
313 if ((p[x] & (0x80 >> y)) == 0)
314 break;
315 }
316 }
317 return x * 8 + y;
318}
319
320static void
2d21ac55 321in_len2mask(struct in_addr *mask, int len)
1c79356b
A
322{
323 int i;
324 u_char *p;
325
326 p = (u_char *)mask;
327 bzero(mask, sizeof(*mask));
328 for (i = 0; i < len / 8; i++)
329 p[i] = 0xff;
330 if (len % 8)
331 p[i] = (0xff00 >> (len % 8)) & 0xff;
332}
333
334static int in_interfaces; /* number of external internet interfaces */
335
6d2010ae
A
336static int
337in_domifattach(struct ifnet *ifp)
338{
339 int error;
340
341 if ((error = proto_plumb(PF_INET, ifp)) && error != EEXIST)
342 log(LOG_ERR, "%s: proto_plumb returned %d if=%s%d\n",
343 __func__, error, ifp->if_name, ifp->if_unit);
344
345 return (error);
346}
347
1c79356b
A
348/*
349 * Generic internet control operations (ioctl's).
350 * Ifp is 0 if not an interface-specific ioctl.
2d21ac55
A
351 *
352 * Returns: 0 Success
353 * EINVAL
354 * EADDRNOTAVAIL
355 * EDESTADDRREQ
356 * EPERM
357 * ENOBUFS
358 * EBUSY
359 * EOPNOTSUPP
360 * proc_suser:EPERM
361 * suser:EPERM
362 * in_lifaddr_ioctl:???
363 * dlil_ioctl:???
364 * in_ifinit:???
365 * dlil_plumb_protocol:???
366 * dlil_unplumb_protocol:???
1c79356b
A
367 */
368/* ARGSUSED */
369int
316670eb
A
370in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
371 struct proc *p)
1c79356b 372{
316670eb 373 struct in_ifaddr *ia = NULL;
91447636 374 struct ifaddr *ifa;
1c79356b 375 struct sockaddr_in oldaddr;
2d21ac55
A
376 int error = 0;
377 int hostIsNew, maskIsNew;
316670eb
A
378 struct kev_msg ev_msg;
379 struct kev_in_data in_event_data;
380
381 bzero(&in_event_data, sizeof (struct kev_in_data));
382 bzero(&ev_msg, sizeof (struct kev_msg));
1c79356b 383
1c79356b 384 switch (cmd) {
316670eb
A
385 case SIOCALIFADDR: /* struct if_laddrreq */
386 case SIOCDLIFADDR: /* struct if_laddrreq */
b0d623f7 387 if ((error = proc_suser(p)) != 0)
316670eb
A
388 return (error);
389 /* FALLTHRU */
390 case SIOCGLIFADDR: { /* struct if_laddrreq */
391 struct if_laddrreq iflr;
392
393 if (ifp == NULL)
394 return (EINVAL);
395
396 bcopy(data, &iflr, sizeof (iflr));
397 error = in_lifaddr_ioctl(so, cmd, &iflr, ifp, p);
398 bcopy(&iflr, data, sizeof (iflr));
399 return (error);
400 }
1c79356b
A
401 }
402
403 /*
404 * Find address for this interface, if it exists.
405 *
406 * If an alias address was specified, find that one instead of
407 * the first one on the interface.
408 */
316670eb
A
409 if (ifp != NULL) {
410 struct in_ifaddr *iap;
411 struct sockaddr_in sin;
412
413 bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
414 &sin, sizeof (sin));
415
b0d623f7 416 lck_rw_lock_shared(in_ifaddr_rwlock);
316670eb
A
417 for (iap = in_ifaddrhead.tqh_first; iap != NULL;
418 iap = iap->ia_link.tqe_next) {
419 if (iap->ia_ifp != ifp)
420 continue;
421
422 IFA_LOCK(&iap->ia_ifa);
423 if (sin.sin_addr.s_addr ==
424 iap->ia_addr.sin_addr.s_addr) {
425 ia = iap;
426 IFA_UNLOCK(&iap->ia_ifa);
427 break;
428 } else if (ia == NULL) {
429 ia = iap;
430 if (sin.sin_family != AF_INET) {
6d2010ae 431 IFA_UNLOCK(&iap->ia_ifa);
1c79356b 432 break;
1c79356b
A
433 }
434 }
316670eb
A
435 IFA_UNLOCK(&iap->ia_ifa);
436 }
b0d623f7 437 /* take a reference on ia before releasing lock */
316670eb 438 if (ia != NULL)
6d2010ae 439 IFA_ADDREF(&ia->ia_ifa);
b0d623f7 440 lck_rw_done(in_ifaddr_rwlock);
91447636 441 }
316670eb 442
1c79356b 443 switch (cmd) {
316670eb
A
444 case SIOCAUTOADDR: /* struct ifreq */
445 case SIOCARPIPLL: /* struct ifreq */
446 case SIOCSETROUTERMODE: /* struct ifreq */
b0d623f7 447 if ((error = proc_suser(p)) != 0) {
2d21ac55
A
448 goto done;
449 }
316670eb 450 if (ifp == NULL) {
2d21ac55
A
451 error = EADDRNOTAVAIL;
452 goto done;
453 }
0b4e3aa0 454 break;
1c79356b 455
316670eb
A
456 case SIOCAIFADDR: /* struct ifaliasreq */
457 case SIOCDIFADDR: { /* struct ifreq */
458 struct sockaddr_in addr, dstaddr;
459
460 if (ifp == NULL) {
2d21ac55
A
461 error = EADDRNOTAVAIL;
462 goto done;
463 }
316670eb
A
464
465 if (cmd == SIOCAIFADDR) {
466 bcopy(&((struct in_aliasreq *)(void *)data)->
467 ifra_addr, &addr, sizeof (addr));
468 bcopy(&((struct in_aliasreq *)(void *)data)->
469 ifra_dstaddr, &dstaddr, sizeof (dstaddr));
470 } else {
471 VERIFY(cmd == SIOCDIFADDR);
472 bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
473 &addr, sizeof (addr));
474 bzero(&dstaddr, sizeof (dstaddr));
475 }
476
477 if (addr.sin_family == AF_INET) {
2d21ac55
A
478 struct in_ifaddr *oia;
479
b0d623f7 480 lck_rw_lock_shared(in_ifaddr_rwlock);
1c79356b 481 for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
6d2010ae 482 IFA_LOCK(&ia->ia_ifa);
1c79356b
A
483 if (ia->ia_ifp == ifp &&
484 ia->ia_addr.sin_addr.s_addr ==
316670eb 485 addr.sin_addr.s_addr) {
6d2010ae
A
486 IFA_ADDREF_LOCKED(&ia->ia_ifa);
487 IFA_UNLOCK(&ia->ia_ifa);
1c79356b 488 break;
6d2010ae
A
489 }
490 IFA_UNLOCK(&ia->ia_ifa);
2d21ac55 491 }
b0d623f7 492 lck_rw_done(in_ifaddr_rwlock);
6d2010ae
A
493 if (oia != NULL)
494 IFA_REMREF(&oia->ia_ifa);
316670eb
A
495 if ((ifp->if_flags & IFF_POINTOPOINT) &&
496 (cmd == SIOCAIFADDR) &&
497 (dstaddr.sin_addr.s_addr == INADDR_ANY)) {
2d21ac55
A
498 error = EDESTADDRREQ;
499 goto done;
1c79356b 500 }
316670eb 501 } else if (cmd == SIOCAIFADDR) {
2d21ac55
A
502 error = EINVAL;
503 goto done;
504 }
316670eb 505 if (cmd == SIOCDIFADDR && ia == NULL) {
2d21ac55
A
506 error = EADDRNOTAVAIL;
507 goto done;
508 }
1c79356b 509 /* FALLTHROUGH */
316670eb
A
510 }
511 case SIOCSIFADDR: /* struct ifreq */
512 case SIOCSIFNETMASK: /* struct ifreq */
513 case SIOCSIFDSTADDR: { /* struct ifreq */
514 struct sockaddr_in addr;
515
516 if (cmd == SIOCAIFADDR) {
517 /* fell thru from above; just repeat it */
518 bcopy(&((struct in_aliasreq *)(void *)data)->
519 ifra_addr, &addr, sizeof (addr));
520 } else {
521 VERIFY(cmd == SIOCDIFADDR || cmd == SIOCSIFADDR ||
522 cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR);
523 bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
524 &addr, sizeof (addr));
525 }
526
6d2010ae
A
527 /* socket is NULL if called from in_purgeaddrs() */
528 if (so != NULL && (so->so_state & SS_PRIV) == 0) {
529 error = EPERM;
530 goto done;
531 }
532 /* in case it's NULL, make sure it came from the kernel */
533 if (so == NULL && p != kernproc) {
2d21ac55
A
534 error = EPERM;
535 goto done;
536 }
316670eb 537 if (ifp == NULL) {
2d21ac55
A
538 error = EADDRNOTAVAIL;
539 goto done;
540 }
316670eb 541 if (addr.sin_family != AF_INET && cmd == SIOCSIFADDR) {
2d21ac55
A
542 error = EINVAL;
543 goto done;
544 }
6d2010ae 545 if (ia == NULL) {
b0d623f7 546 ia = in_ifaddr_alloc(M_WAITOK);
6d2010ae 547 if (ia == NULL) {
2d21ac55
A
548 error = ENOBUFS;
549 goto done;
550 }
6d2010ae 551 ifnet_lock_exclusive(ifp);
1c79356b 552 ifa = &ia->ia_ifa;
6d2010ae 553 IFA_LOCK(ifa);
b0d623f7 554 /* Hold a reference for this routine */
6d2010ae
A
555 IFA_ADDREF_LOCKED(ifa);
556 IA_HASH_INIT(ia);
1c79356b
A
557 ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
558 ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
559 ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
560 ia->ia_sockmask.sin_len = 8;
561 if (ifp->if_flags & IFF_BROADCAST) {
316670eb 562 ia->ia_broadaddr.sin_len = sizeof (ia->ia_addr);
1c79356b
A
563 ia->ia_broadaddr.sin_family = AF_INET;
564 }
565 ia->ia_ifp = ifp;
566 if (!(ifp->if_flags & IFF_LOOPBACK))
567 in_interfaces++;
b0d623f7 568 /* if_attach_ifa() holds a reference for ifa_link */
91447636 569 if_attach_ifa(ifp, ifa);
6d2010ae
A
570 /*
571 * If we have to go through in_ifinit(), make sure
572 * to avoid installing route(s) based on this address
573 * via PFC_IFUP event, before the link resolver (ARP)
574 * initializes it.
575 */
576 if (cmd == SIOCAIFADDR || cmd == SIOCSIFADDR)
577 ifa->ifa_debug |= IFD_NOTREADY;
578 IFA_UNLOCK(ifa);
91447636 579 ifnet_lock_done(ifp);
b0d623f7
A
580 lck_rw_lock_exclusive(in_ifaddr_rwlock);
581 /* Hold a reference for ia_link */
6d2010ae 582 IFA_ADDREF(ifa);
91447636 583 TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
b0d623f7 584 lck_rw_done(in_ifaddr_rwlock);
316670eb
A
585 /* discard error */
586 (void) in_domifattach(ifp);
587 error = 0;
1c79356b
A
588 }
589 break;
316670eb 590 }
1c79356b 591
316670eb
A
592 case SIOCPROTOATTACH: /* struct ifreq */
593 case SIOCPROTODETACH: /* struct ifreq */
b0d623f7 594 if ((error = proc_suser(p)) != 0) {
2d21ac55
A
595 goto done;
596 }
316670eb 597 if (ifp == NULL) {
2d21ac55
A
598 error = EADDRNOTAVAIL;
599 goto done;
600 }
9bccf70c 601 break;
b0d623f7 602
316670eb 603 case SIOCSIFBRDADDR: /* struct ifreq */
2d21ac55
A
604 if ((so->so_state & SS_PRIV) == 0) {
605 error = EPERM;
606 goto done;
607 }
1c79356b 608 /* FALLTHROUGH */
316670eb
A
609 case SIOCGIFADDR: /* struct ifreq */
610 case SIOCGIFNETMASK: /* struct ifreq */
611 case SIOCGIFDSTADDR: /* struct ifreq */
612 case SIOCGIFBRDADDR: /* struct ifreq */
613 if (ia == NULL) {
2d21ac55
A
614 error = EADDRNOTAVAIL;
615 goto done;
616 }
1c79356b
A
617 break;
618 }
316670eb 619
1c79356b 620 switch (cmd) {
316670eb
A
621 case SIOCAUTOADDR: { /* struct ifreq */
622 int intval;
623
624 VERIFY(ifp != NULL);
625 bcopy(&((struct ifreq *)(void *)data)->ifr_intval,
626 &intval, sizeof (intval));
627
91447636 628 ifnet_lock_exclusive(ifp);
316670eb
A
629 if (intval) {
630 /*
631 * An interface in IPv4 router mode implies that it
632 * is configured with a static IP address and should
633 * not act as a DHCP client; prevent SIOCAUTOADDR from
634 * being set in that mode.
635 */
636 if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
637 intval = 0; /* be safe; clear flag if set */
638 error = EBUSY;
639 } else {
640 ifp->if_eflags |= IFEF_AUTOCONFIGURING;
641 }
642 }
643 if (!intval)
0b4e3aa0 644 ifp->if_eflags &= ~IFEF_AUTOCONFIGURING;
91447636
A
645 ifnet_lock_done(ifp);
646 break;
316670eb
A
647 }
648
649 case SIOCARPIPLL: { /* struct ifreq */
650 int intval;
651
652 VERIFY(ifp != NULL);
653 bcopy(&((struct ifreq *)(void *)data)->ifr_intval,
654 &intval, sizeof (intval));
91447636 655 ipv4_ll_arp_aware = 1;
316670eb 656
91447636 657 ifnet_lock_exclusive(ifp);
316670eb
A
658 if (intval) {
659 /*
660 * An interface in IPv4 router mode implies that it
661 * is configured with a static IP address and should
662 * not have to deal with IPv4 Link-Local Address;
663 * prevent SIOCARPIPLL from being set in that mode.
664 */
665 if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
666 intval = 0; /* be safe; clear flag if set */
667 error = EBUSY;
668 } else {
669 ifp->if_eflags |= IFEF_ARPLL;
670 }
671 }
672 if (!intval)
91447636
A
673 ifp->if_eflags &= ~IFEF_ARPLL;
674 ifnet_lock_done(ifp);
0b4e3aa0 675 break;
316670eb 676 }
1c79356b 677
316670eb
A
678 case SIOCGIFADDR: /* struct ifreq */
679 VERIFY(ia != NULL);
6d2010ae 680 IFA_LOCK(&ia->ia_ifa);
316670eb
A
681 bcopy(&ia->ia_addr, &((struct ifreq *)(void *)data)->ifr_addr,
682 sizeof (struct sockaddr_in));
6d2010ae 683 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
684 break;
685
316670eb
A
686 case SIOCGIFBRDADDR: /* struct ifreq */
687 VERIFY(ia != NULL);
2d21ac55
A
688 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
689 error = EINVAL;
690 break;
691 }
6d2010ae 692 IFA_LOCK(&ia->ia_ifa);
316670eb
A
693 bcopy(&ia->ia_broadaddr,
694 &((struct ifreq *)(void *)data)->ifr_broadaddr,
695 sizeof (struct sockaddr_in));
6d2010ae 696 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
697 break;
698
316670eb
A
699 case SIOCGIFDSTADDR: /* struct ifreq */
700 VERIFY(ia != NULL);
2d21ac55
A
701 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
702 error = EINVAL;
703 break;
704 }
6d2010ae 705 IFA_LOCK(&ia->ia_ifa);
316670eb
A
706 bcopy(&ia->ia_dstaddr,
707 &((struct ifreq *)(void *)data)->ifr_dstaddr,
708 sizeof (struct sockaddr_in));
6d2010ae 709 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
710 break;
711
316670eb
A
712 case SIOCGIFNETMASK: /* struct ifreq */
713 VERIFY(ia != NULL);
6d2010ae 714 IFA_LOCK(&ia->ia_ifa);
316670eb
A
715 bcopy(&ia->ia_sockmask,
716 &((struct ifreq *)(void *)data)->ifr_addr,
717 sizeof (struct sockaddr_in));
6d2010ae 718 IFA_UNLOCK(&ia->ia_ifa);
1c79356b
A
719 break;
720
316670eb
A
721 case SIOCSIFDSTADDR: /* struct ifreq */
722 VERIFY(ifp != NULL && ia != NULL);
2d21ac55
A
723 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
724 error = EINVAL;
725 break;
726 }
6d2010ae 727 IFA_LOCK(&ia->ia_ifa);
1c79356b 728 oldaddr = ia->ia_dstaddr;
316670eb
A
729 bcopy(&((struct ifreq *)(void *)data)->ifr_dstaddr,
730 &ia->ia_dstaddr, sizeof (struct sockaddr_in));
b0d623f7
A
731 if (ia->ia_dstaddr.sin_family == AF_INET)
732 ia->ia_dstaddr.sin_len = sizeof (struct sockaddr_in);
6d2010ae 733 IFA_UNLOCK(&ia->ia_ifa);
316670eb
A
734 /*
735 * NOTE: SIOCSIFDSTADDR is defined with struct ifreq
736 * as parameter, but here we are sending it down
737 * to the interface with a pointer to struct ifaddr,
738 * for legacy reasons.
739 */
2d21ac55 740 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFDSTADDR, ia);
6d2010ae 741 IFA_LOCK(&ia->ia_ifa);
2d21ac55
A
742 if (error == EOPNOTSUPP) {
743 error = 0;
744 }
1c79356b 745 if (error) {
2d21ac55 746 ia->ia_dstaddr = oldaddr;
6d2010ae 747 IFA_UNLOCK(&ia->ia_ifa);
2d21ac55 748 break;
1c79356b 749 }
6d2010ae 750 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1c79356b
A
751
752 ev_msg.vendor_code = KEV_VENDOR_APPLE;
753 ev_msg.kev_class = KEV_NETWORK_CLASS;
754 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
6d2010ae 755
1c79356b
A
756 ev_msg.event_code = KEV_INET_SIFDSTADDR;
757
316670eb
A
758 if (ia->ia_ifa.ifa_dstaddr) {
759 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
760 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
761 } else {
762 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
763 }
1c79356b
A
764
765 in_event_data.ia_addr = ia->ia_addr.sin_addr;
766 in_event_data.ia_net = ia->ia_net;
767 in_event_data.ia_netmask = ia->ia_netmask;
768 in_event_data.ia_subnet = ia->ia_subnet;
769 in_event_data.ia_subnetmask = ia->ia_subnetmask;
770 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
6d2010ae 771 IFA_UNLOCK(&ia->ia_ifa);
316670eb
A
772 (void) strncpy(&in_event_data.link_data.if_name[0],
773 ifp->if_name, IFNAMSIZ);
1c79356b 774 in_event_data.link_data.if_family = ifp->if_family;
b0d623f7 775 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
1c79356b
A
776
777 ev_msg.dv[0].data_ptr = &in_event_data;
316670eb 778 ev_msg.dv[0].data_length = sizeof (struct kev_in_data);
1c79356b
A
779 ev_msg.dv[1].data_length = 0;
780
781 kev_post_msg(&ev_msg);
782
6d2010ae
A
783 lck_mtx_lock(rnh_lock);
784 IFA_LOCK(&ia->ia_ifa);
1c79356b
A
785 if (ia->ia_flags & IFA_ROUTE) {
786 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
6d2010ae
A
787 IFA_UNLOCK(&ia->ia_ifa);
788 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
789 IFA_LOCK(&ia->ia_ifa);
1c79356b 790 ia->ia_ifa.ifa_dstaddr =
6d2010ae
A
791 (struct sockaddr *)&ia->ia_dstaddr;
792 IFA_UNLOCK(&ia->ia_ifa);
793 rtinit_locked(&(ia->ia_ifa), (int)RTM_ADD,
794 RTF_HOST|RTF_UP);
795 } else {
796 IFA_UNLOCK(&ia->ia_ifa);
1c79356b 797 }
6d2010ae 798 lck_mtx_unlock(rnh_lock);
1c79356b
A
799 break;
800
316670eb
A
801 case SIOCSIFBRDADDR: /* struct ifreq */
802 VERIFY(ia != NULL);
2d21ac55
A
803 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
804 error = EINVAL;
805 break;
806 }
6d2010ae 807 IFA_LOCK(&ia->ia_ifa);
316670eb
A
808 bcopy(&((struct ifreq *)(void *)data)->ifr_broadaddr,
809 &ia->ia_broadaddr, sizeof (struct sockaddr_in));
1c79356b
A
810
811 ev_msg.vendor_code = KEV_VENDOR_APPLE;
812 ev_msg.kev_class = KEV_NETWORK_CLASS;
813 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
6d2010ae 814
1c79356b
A
815 ev_msg.event_code = KEV_INET_SIFBRDADDR;
816
316670eb
A
817 if (ia->ia_ifa.ifa_dstaddr) {
818 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
819 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
820 } else {
821 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
822 }
1c79356b
A
823 in_event_data.ia_addr = ia->ia_addr.sin_addr;
824 in_event_data.ia_net = ia->ia_net;
825 in_event_data.ia_netmask = ia->ia_netmask;
826 in_event_data.ia_subnet = ia->ia_subnet;
827 in_event_data.ia_subnetmask = ia->ia_subnetmask;
828 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
6d2010ae 829 IFA_UNLOCK(&ia->ia_ifa);
316670eb
A
830 (void) strncpy(&in_event_data.link_data.if_name[0],
831 ifp->if_name, IFNAMSIZ);
1c79356b 832 in_event_data.link_data.if_family = ifp->if_family;
b0d623f7 833 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
1c79356b
A
834
835 ev_msg.dv[0].data_ptr = &in_event_data;
316670eb 836 ev_msg.dv[0].data_length = sizeof (struct kev_in_data);
1c79356b
A
837 ev_msg.dv[1].data_length = 0;
838
839 kev_post_msg(&ev_msg);
1c79356b
A
840 break;
841
316670eb
A
842 case SIOCSIFADDR: { /* struct ifreq */
843 struct sockaddr_in addr;
844
845 VERIFY(ifp != NULL && ia != NULL);
846 bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
847 &addr, sizeof (addr));
b0d623f7
A
848 /*
849 * If this is a new address, the reference count for the
850 * hash table has been taken at creation time above.
851 */
316670eb 852 error = in_ifinit(ifp, ia, &addr, 1);
b0d623f7
A
853#if PF
854 if (!error)
855 (void) pf_ifaddr_hook(ifp, cmd);
856#endif /* PF */
2d21ac55 857 break;
316670eb 858 }
1c79356b 859
316670eb
A
860 case SIOCPROTOATTACH: /* struct ifreq */
861 VERIFY(ifp != NULL);
6d2010ae 862 error = in_domifattach(ifp);
2d21ac55 863 break;
6d2010ae 864
316670eb
A
865 case SIOCPROTODETACH: /* struct ifreq */
866 VERIFY(ifp != NULL);
6d2010ae
A
867 /*
868 * If an IPv4 address is still present, refuse to detach.
869 */
91447636 870 ifnet_lock_shared(ifp);
6d2010ae
A
871 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
872 IFA_LOCK(ifa);
873 if (ifa->ifa_addr->sa_family == AF_INET) {
874 IFA_UNLOCK(ifa);
91447636 875 break;
6d2010ae
A
876 }
877 IFA_UNLOCK(ifa);
878 }
91447636 879 ifnet_lock_done(ifp);
6d2010ae 880 if (ifa != NULL) {
2d21ac55
A
881 error = EBUSY;
882 break;
883 }
55e303ae 884
2d21ac55 885 error = proto_unplumb(PF_INET, ifp);
9bccf70c 886 break;
0b4e3aa0 887
316670eb
A
888 case SIOCSETROUTERMODE: { /* struct ifreq */
889 int intval;
890
891 VERIFY(ifp != NULL);
892 bcopy(&((struct ifreq *)(void *)data)->ifr_intval,
893 &intval, sizeof (intval));
894
895 error = in_setrouter(ifp, intval);
896 break;
897 }
898
899 case SIOCSIFNETMASK: { /* struct ifreq */
900 struct sockaddr_in addr;
901 in_addr_t i;
902
903 VERIFY(ifp != NULL && ia != NULL);
904 bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
905 &addr, sizeof (addr));
906 i = addr.sin_addr.s_addr;
6d2010ae 907
6d2010ae 908 IFA_LOCK(&ia->ia_ifa);
1c79356b
A
909 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
910 ev_msg.vendor_code = KEV_VENDOR_APPLE;
911 ev_msg.kev_class = KEV_NETWORK_CLASS;
912 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
6d2010ae 913
1c79356b
A
914 ev_msg.event_code = KEV_INET_SIFNETMASK;
915
316670eb
A
916 if (ia->ia_ifa.ifa_dstaddr) {
917 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
918 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
919 } else {
920 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
921 }
1c79356b
A
922 in_event_data.ia_addr = ia->ia_addr.sin_addr;
923 in_event_data.ia_net = ia->ia_net;
924 in_event_data.ia_netmask = ia->ia_netmask;
925 in_event_data.ia_subnet = ia->ia_subnet;
926 in_event_data.ia_subnetmask = ia->ia_subnetmask;
927 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
6d2010ae 928 IFA_UNLOCK(&ia->ia_ifa);
316670eb
A
929 (void) strncpy(&in_event_data.link_data.if_name[0],
930 ifp->if_name, IFNAMSIZ);
1c79356b 931 in_event_data.link_data.if_family = ifp->if_family;
b0d623f7 932 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
1c79356b
A
933
934 ev_msg.dv[0].data_ptr = &in_event_data;
316670eb 935 ev_msg.dv[0].data_length = sizeof (struct kev_in_data);
1c79356b
A
936 ev_msg.dv[1].data_length = 0;
937
938 kev_post_msg(&ev_msg);
1c79356b 939 break;
2d21ac55 940 }
316670eb
A
941
942 case SIOCAIFADDR: { /* struct ifaliasreq */
943 struct sockaddr_in addr, broadaddr, mask;
944
945 VERIFY(ifp != NULL && ia != NULL);
946 bcopy(&((struct ifaliasreq *)(void *)data)->ifra_addr,
947 &addr, sizeof (addr));
948 bcopy(&((struct ifaliasreq *)(void *)data)->ifra_broadaddr,
949 &broadaddr, sizeof (broadaddr));
950 bcopy(&((struct ifaliasreq *)(void *)data)->ifra_mask,
951 &mask, sizeof (mask));
952
1c79356b
A
953 maskIsNew = 0;
954 hostIsNew = 1;
955 error = 0;
b0d623f7 956
6d2010ae 957 IFA_LOCK(&ia->ia_ifa);
1c79356b 958 if (ia->ia_addr.sin_family == AF_INET) {
316670eb
A
959 if (addr.sin_len == 0) {
960 addr = ia->ia_addr;
1c79356b 961 hostIsNew = 0;
316670eb
A
962 } else if (addr.sin_addr.s_addr ==
963 ia->ia_addr.sin_addr.s_addr) {
1c79356b 964 hostIsNew = 0;
316670eb 965 }
1c79356b 966 }
316670eb 967 if (mask.sin_len) {
6d2010ae 968 IFA_UNLOCK(&ia->ia_ifa);
91447636 969 in_ifscrub(ifp, ia, 0);
6d2010ae 970 IFA_LOCK(&ia->ia_ifa);
316670eb 971 ia->ia_sockmask = mask;
1c79356b
A
972 ia->ia_subnetmask =
973 ntohl(ia->ia_sockmask.sin_addr.s_addr);
974 maskIsNew = 1;
975 }
976 if ((ifp->if_flags & IFF_POINTOPOINT) &&
316670eb 977 (broadaddr.sin_family == AF_INET)) {
6d2010ae 978 IFA_UNLOCK(&ia->ia_ifa);
91447636 979 in_ifscrub(ifp, ia, 0);
6d2010ae 980 IFA_LOCK(&ia->ia_ifa);
316670eb 981 ia->ia_dstaddr = broadaddr;
b0d623f7 982 ia->ia_dstaddr.sin_len = sizeof (struct sockaddr_in);
1c79356b
A
983 maskIsNew = 1; /* We lie; but the effect's the same */
984 }
316670eb 985 if (addr.sin_family == AF_INET && (hostIsNew || maskIsNew)) {
6d2010ae 986 IFA_UNLOCK(&ia->ia_ifa);
316670eb 987 error = in_ifinit(ifp, ia, &addr, 0);
6d2010ae
A
988 } else {
989 IFA_UNLOCK(&ia->ia_ifa);
1c79356b 990 }
b0d623f7
A
991#if PF
992 if (!error)
993 (void) pf_ifaddr_hook(ifp, cmd);
994#endif /* PF */
6d2010ae 995 IFA_LOCK(&ia->ia_ifa);
1c79356b 996 if ((ifp->if_flags & IFF_BROADCAST) &&
316670eb
A
997 (broadaddr.sin_family == AF_INET))
998 ia->ia_broadaddr = broadaddr;
1c79356b
A
999
1000 /*
1001 * Report event.
1002 */
9bccf70c 1003 if ((error == 0) || (error == EEXIST)) {
316670eb
A
1004 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1005 ev_msg.kev_class = KEV_NETWORK_CLASS;
1006 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1007
1008 if (hostIsNew)
1009 ev_msg.event_code = KEV_INET_NEW_ADDR;
1010 else
1011 ev_msg.event_code = KEV_INET_CHANGED_ADDR;
1012
1013 if (ia->ia_ifa.ifa_dstaddr) {
1014 in_event_data.ia_dstaddr =
1015 ((struct sockaddr_in *)(void *)ia->
1016 ia_ifa.ifa_dstaddr)->sin_addr;
1017 } else {
1018 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1019 }
1020 in_event_data.ia_addr = ia->ia_addr.sin_addr;
1021 in_event_data.ia_net = ia->ia_net;
1022 in_event_data.ia_netmask = ia->ia_netmask;
1023 in_event_data.ia_subnet = ia->ia_subnet;
1024 in_event_data.ia_subnetmask = ia->ia_subnetmask;
1025 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
1026 IFA_UNLOCK(&ia->ia_ifa);
1027 (void) strncpy(&in_event_data.link_data.if_name[0],
1028 ifp->if_name, IFNAMSIZ);
1029 in_event_data.link_data.if_family = ifp->if_family;
1030 in_event_data.link_data.if_unit = ifp->if_unit;
1031
1032 ev_msg.dv[0].data_ptr = &in_event_data;
1033 ev_msg.dv[0].data_length = sizeof (struct kev_in_data);
1034 ev_msg.dv[1].data_length = 0;
1035
1036 kev_post_msg(&ev_msg);
6d2010ae 1037 } else {
316670eb 1038 IFA_UNLOCK(&ia->ia_ifa);
1c79356b 1039 }
2d21ac55 1040 break;
316670eb 1041 }
1c79356b 1042
316670eb
A
1043 case SIOCDIFADDR: /* struct ifreq */
1044 VERIFY(ifp != NULL && ia != NULL);
2d21ac55 1045 error = ifnet_ioctl(ifp, PF_INET, SIOCDIFADDR, ia);
91447636
A
1046 if (error == EOPNOTSUPP)
1047 error = 0;
2d21ac55
A
1048 if (error != 0) {
1049 break;
1050 }
9bccf70c 1051
91447636 1052 /* Fill out the kernel event information */
1c79356b
A
1053 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1054 ev_msg.kev_class = KEV_NETWORK_CLASS;
1055 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
6d2010ae 1056
1c79356b
A
1057 ev_msg.event_code = KEV_INET_ADDR_DELETED;
1058
6d2010ae 1059 IFA_LOCK(&ia->ia_ifa);
316670eb
A
1060 if (ia->ia_ifa.ifa_dstaddr) {
1061 in_event_data.ia_dstaddr = ((struct sockaddr_in *)
1062 (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
1063 } else {
1064 in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1065 }
1c79356b
A
1066 in_event_data.ia_addr = ia->ia_addr.sin_addr;
1067 in_event_data.ia_net = ia->ia_net;
1068 in_event_data.ia_netmask = ia->ia_netmask;
1069 in_event_data.ia_subnet = ia->ia_subnet;
1070 in_event_data.ia_subnetmask = ia->ia_subnetmask;
1071 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
6d2010ae 1072 IFA_UNLOCK(&ia->ia_ifa);
316670eb
A
1073 (void) strncpy(&in_event_data.link_data.if_name[0],
1074 ifp->if_name, IFNAMSIZ);
1c79356b 1075 in_event_data.link_data.if_family = ifp->if_family;
b0d623f7 1076 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
1c79356b
A
1077
1078 ev_msg.dv[0].data_ptr = &in_event_data;
91447636 1079 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1c79356b
A
1080 ev_msg.dv[1].data_length = 0;
1081
b0d623f7
A
1082 ifa = &ia->ia_ifa;
1083 lck_rw_lock_exclusive(in_ifaddr_rwlock);
1084 /* Release ia_link reference */
6d2010ae 1085 IFA_REMREF(ifa);
91447636 1086 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
6d2010ae 1087 IFA_LOCK(ifa);
b0d623f7
A
1088 if (IA_IS_HASHED(ia))
1089 in_iahash_remove(ia);
6d2010ae 1090 IFA_UNLOCK(ifa);
b0d623f7
A
1091 lck_rw_done(in_ifaddr_rwlock);
1092
9bccf70c
A
1093 /*
1094 * in_ifscrub kills the interface route.
1095 */
b0d623f7 1096 in_ifscrub(ifp, ia, 0);
91447636 1097 ifnet_lock_exclusive(ifp);
6d2010ae 1098 IFA_LOCK(ifa);
b0d623f7 1099 /* if_detach_ifa() releases ifa_link reference */
91447636 1100 if_detach_ifa(ifp, ifa);
6d2010ae
A
1101 /* Our reference to this address is dropped at the bottom */
1102 IFA_UNLOCK(ifa);
1103
b0d623f7
A
1104 /*
1105 * If the interface supports multicast, and no address is left,
1106 * remove the "all hosts" multicast group from that interface.
1107 */
6d2010ae
A
1108 if ((ifp->if_flags & IFF_MULTICAST) != 0 ||
1109 ifp->if_allhostsinm != NULL ) {
9bccf70c 1110
6d2010ae
A
1111 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1112 IFA_LOCK(ifa);
1113 if (ifa->ifa_addr->sa_family == AF_INET) {
1114 IFA_UNLOCK(ifa);
9bccf70c 1115 break;
6d2010ae
A
1116 }
1117 IFA_UNLOCK(ifa);
9bccf70c 1118 }
91447636 1119 ifnet_lock_done(ifp);
6d2010ae
A
1120
1121 lck_mtx_lock(&ifp->if_addrconfig_lock);
1122 if (ifa == NULL && ifp->if_allhostsinm != NULL) {
1123 struct in_multi *inm = ifp->if_allhostsinm;
1124 ifp->if_allhostsinm = NULL;
1125
1126 in_delmulti(inm);
316670eb
A
1127 /* release the reference for allhostsinm */
1128 INM_REMREF(inm);
6d2010ae
A
1129 }
1130 lck_mtx_unlock(&ifp->if_addrconfig_lock);
1131 } else {
91447636 1132 ifnet_lock_done(ifp);
6d2010ae 1133 }
91447636
A
1134
1135 /* Post the kernel event */
1136 kev_post_msg(&ev_msg);
2d21ac55
A
1137
1138 /*
1139 * See if there is any IPV4 address left and if so,
1140 * reconfigure KDP to use current primary address.
1141 */
1142 ifa = ifa_ifpgetprimary(ifp, AF_INET);
1143 if (ifa != NULL) {
316670eb
A
1144 /*
1145 * NOTE: SIOCSIFADDR is defined with struct ifreq
1146 * as parameter, but here we are sending it down
1147 * to the interface with a pointer to struct ifaddr,
1148 * for legacy reasons.
1149 */
2d21ac55
A
1150 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa);
1151 if (error == EOPNOTSUPP)
1152 error = 0;
1153
1154 /* Release reference from ifa_ifpgetprimary() */
6d2010ae 1155 IFA_REMREF(ifa);
2d21ac55 1156 }
b0d623f7
A
1157#if PF
1158 (void) pf_ifaddr_hook(ifp, cmd);
1159#endif /* PF */
1c79356b
A
1160 break;
1161
9bccf70c 1162#ifdef __APPLE__
316670eb
A
1163 case SIOCSETOT: { /* int */
1164 /*
1165 * Inspiration from tcp_ctloutput() and ip_ctloutput()
1166 * Special ioctl for OpenTransport sockets
1167 */
1168 struct inpcb *inp, *cloned_inp;
1169 int error2 = 0;
1170 int cloned_fd;
1171
1172 bcopy(data, &cloned_fd, sizeof (cloned_fd));
1173
1174 inp = sotoinpcb(so);
1175 if (inp == NULL) {
1176 break;
1177 }
1178
1179 /* let's make sure it's either -1 or a valid file descriptor */
1180 if (cloned_fd != -1) {
1181 struct socket *cloned_so;
1182 error2 = file_socket(cloned_fd, &cloned_so);
1183 if (error2) {
1184 break;
1185 }
1186 cloned_inp = sotoinpcb(cloned_so);
91447636 1187 file_drop(cloned_fd);
316670eb
A
1188 } else {
1189 cloned_inp = NULL;
1190 }
1191
1192 if (cloned_inp == NULL) {
1193 /* OT always uses IP_PORTRANGE_HIGH */
1194 inp->inp_flags &= ~(INP_LOWPORT);
1195 inp->inp_flags |= INP_HIGHPORT;
1196 /*
1197 * For UDP, OT allows broadcast by default;
1198 * for TCP we want to see MSG_OOB when we
1199 * receive urgent data.
1200 */
1201 if (so->so_type == SOCK_DGRAM)
1202 so->so_options |= SO_BROADCAST;
1203 else if (so->so_type == SOCK_STREAM)
1204 so->so_options |= SO_WANTOOBFLAG;
1205 } else {
1206 inp->inp_ip_tos = cloned_inp->inp_ip_tos;
1207 inp->inp_ip_ttl = cloned_inp->inp_ip_ttl;
1208 inp->inp_flags = cloned_inp->inp_flags;
1209
1210 /* Multicast options */
1211 if (cloned_inp->inp_moptions != NULL)
1212 error2 = imo_clone(cloned_inp, inp);
1213 }
1214 break;
1215 }
9bccf70c 1216#endif /* __APPLE__ */
1c79356b
A
1217
1218 default:
2d21ac55 1219 error = EOPNOTSUPP;
1c79356b 1220 }
2d21ac55
A
1221 done:
1222 if (ia != NULL) {
6d2010ae 1223 IFA_REMREF(&ia->ia_ifa);
2d21ac55
A
1224 }
1225 return (error);
1c79356b
A
1226}
1227
1228/*
1229 * SIOC[GAD]LIFADDR.
9bccf70c 1230 * SIOCGLIFADDR: get first address. (?!?)
1c79356b
A
1231 * SIOCGLIFADDR with IFLR_PREFIX:
1232 * get first address that matches the specified prefix.
1233 * SIOCALIFADDR: add the specified address.
1234 * SIOCALIFADDR with IFLR_PREFIX:
1235 * EINVAL since we can't deduce hostid part of the address.
1236 * SIOCDLIFADDR: delete the specified address.
1237 * SIOCDLIFADDR with IFLR_PREFIX:
1238 * delete the first address that matches the specified prefix.
1239 * return values:
1240 * EINVAL on invalid parameters
1241 * EADDRNOTAVAIL on prefix match failed/specified address not found
1242 * other values may be returned from in_ioctl()
1243 */
1244static int
316670eb
A
1245in_lifaddr_ioctl(struct socket *so, u_long cmd, struct if_laddrreq *iflr,
1246 struct ifnet *ifp, struct proc *p)
1c79356b 1247{
1c79356b
A
1248 struct ifaddr *ifa;
1249
316670eb 1250 VERIFY(ifp != NULL);
1c79356b
A
1251
1252 switch (cmd) {
1253 case SIOCGLIFADDR:
1254 /* address must be specified on GET with IFLR_PREFIX */
1255 if ((iflr->flags & IFLR_PREFIX) == 0)
1256 break;
1257 /*FALLTHROUGH*/
1258 case SIOCALIFADDR:
1259 case SIOCDLIFADDR:
1260 /* address must be specified on ADD and DELETE */
1261 if (iflr->addr.ss_family != AF_INET)
1262 return EINVAL;
1263 if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
1264 return EINVAL;
1265 /* XXX need improvement */
1266 if (iflr->dstaddr.ss_family
1267 && iflr->dstaddr.ss_family != AF_INET)
1268 return EINVAL;
1269 if (iflr->dstaddr.ss_family
1270 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
1271 return EINVAL;
1272 break;
1273 default: /*shouldn't happen*/
1c79356b 1274 return EOPNOTSUPP;
1c79356b
A
1275 }
1276 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
1277 return EINVAL;
1278
1279 switch (cmd) {
1280 case SIOCALIFADDR:
1281 {
1282 struct in_aliasreq ifra;
1283
1284 if (iflr->flags & IFLR_PREFIX)
1285 return EINVAL;
1286
1287 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
1288 bzero(&ifra, sizeof(ifra));
1289 bcopy(iflr->iflr_name, ifra.ifra_name,
1290 sizeof(ifra.ifra_name));
1291
1292 bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
1293
1294 if (iflr->dstaddr.ss_family) { /*XXX*/
1295 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
1296 iflr->dstaddr.ss_len);
1297 }
1298
1299 ifra.ifra_mask.sin_family = AF_INET;
1300 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
1301 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
1302
1303 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p);
1304 }
1305 case SIOCGLIFADDR:
1306 case SIOCDLIFADDR:
1307 {
1308 struct in_ifaddr *ia;
2d21ac55
A
1309 struct in_addr mask, candidate;
1310 struct in_addr match = { 0 };
1c79356b
A
1311 struct sockaddr_in *sin;
1312 int cmp;
1313
1314 bzero(&mask, sizeof(mask));
1315 if (iflr->flags & IFLR_PREFIX) {
1316 /* lookup a prefix rather than address. */
1317 in_len2mask(&mask, iflr->prefixlen);
1318
1319 sin = (struct sockaddr_in *)&iflr->addr;
1320 match.s_addr = sin->sin_addr.s_addr;
1321 match.s_addr &= mask.s_addr;
1322
1323 /* if you set extra bits, that's wrong */
1324 if (match.s_addr != sin->sin_addr.s_addr)
1325 return EINVAL;
1326
1327 cmp = 1;
1328 } else {
1329 if (cmd == SIOCGLIFADDR) {
1330 /* on getting an address, take the 1st match */
1331 cmp = 0; /*XXX*/
1332 } else {
1333 /* on deleting an address, do exact match */
1334 in_len2mask(&mask, 32);
1335 sin = (struct sockaddr_in *)&iflr->addr;
1336 match.s_addr = sin->sin_addr.s_addr;
1337
1338 cmp = 1;
1339 }
1340 }
1341
91447636 1342 ifnet_lock_shared(ifp);
1c79356b 1343 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
6d2010ae
A
1344 IFA_LOCK(ifa);
1345 if (ifa->ifa_addr->sa_family != AF_INET6) {
1346 IFA_UNLOCK(ifa);
1c79356b 1347 continue;
6d2010ae
A
1348 }
1349 if (!cmp) {
1350 IFA_UNLOCK(ifa);
1c79356b 1351 break;
6d2010ae 1352 }
1c79356b
A
1353 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
1354 candidate.s_addr &= mask.s_addr;
6d2010ae 1355 IFA_UNLOCK(ifa);
1c79356b
A
1356 if (candidate.s_addr == match.s_addr)
1357 break;
1358 }
6d2010ae
A
1359 if (ifa != NULL)
1360 IFA_ADDREF(ifa);
91447636 1361 ifnet_lock_done(ifp);
1c79356b
A
1362 if (!ifa)
1363 return EADDRNOTAVAIL;
1364 ia = (struct in_ifaddr *)ifa;
1365
1366 if (cmd == SIOCGLIFADDR) {
6d2010ae 1367 IFA_LOCK(ifa);
1c79356b
A
1368 /* fill in the if_laddrreq structure */
1369 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
1370
1371 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1372 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
1373 ia->ia_dstaddr.sin_len);
1374 } else
1375 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
1376
1377 iflr->prefixlen =
1378 in_mask2len(&ia->ia_sockmask.sin_addr);
1379
1380 iflr->flags = 0; /*XXX*/
1381
6d2010ae
A
1382 IFA_UNLOCK(ifa);
1383 IFA_REMREF(ifa);
1c79356b
A
1384 return 0;
1385 } else {
1386 struct in_aliasreq ifra;
1387
1388 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
1389 bzero(&ifra, sizeof(ifra));
1390 bcopy(iflr->iflr_name, ifra.ifra_name,
1391 sizeof(ifra.ifra_name));
1392
6d2010ae 1393 IFA_LOCK(ifa);
1c79356b
A
1394 bcopy(&ia->ia_addr, &ifra.ifra_addr,
1395 ia->ia_addr.sin_len);
1396 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
1397 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
1398 ia->ia_dstaddr.sin_len);
1399 }
1400 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
1401 ia->ia_sockmask.sin_len);
6d2010ae
A
1402 IFA_UNLOCK(ifa);
1403 IFA_REMREF(ifa);
1c79356b
A
1404 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
1405 ifp, p);
1406 }
1407 }
1408 }
1409
1410 return EOPNOTSUPP; /*just for safety*/
1411}
1412
316670eb
A
1413/*
1414 * Handle SIOCSETROUTERMODE to set or clear the IPv4 router mode flag on
1415 * the interface. When in this mode, IPv4 Link-Local Address support is
1416 * disabled in ARP, and DHCP client support is disabled in IP input; turning
1417 * any of them on would cause an error to be returned. Entering or exiting
1418 * this mode will result in the removal of IPv4 addresses currently configured
1419 * on the interface.
1420 */
1421static int
1422in_setrouter(struct ifnet *ifp, int enable)
1423{
1424 if (ifp->if_flags & IFF_LOOPBACK)
1425 return (ENODEV);
1426
1427 ifnet_lock_exclusive(ifp);
1428 if (enable) {
1429 ifp->if_eflags |= IFEF_IPV4_ROUTER;
1430 ifp->if_eflags &= ~(IFEF_ARPLL | IFEF_AUTOCONFIGURING);
1431 } else {
1432 ifp->if_eflags &= ~IFEF_IPV4_ROUTER;
1433 }
1434 ifnet_lock_done(ifp);
1435
1436 /* purge all IPv4 addresses configured on this interface */
1437 in_purgeaddrs(ifp);
1438
1439 return (0);
1440}
1441
1c79356b
A
1442/*
1443 * Delete any existing route for an interface.
1444 */
1445void
6d2010ae 1446in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, int locked)
1c79356b 1447{
6d2010ae
A
1448 IFA_LOCK(&ia->ia_ifa);
1449 if ((ia->ia_flags & IFA_ROUTE) == 0) {
1450 IFA_UNLOCK(&ia->ia_ifa);
1c79356b 1451 return;
6d2010ae
A
1452 }
1453 IFA_UNLOCK(&ia->ia_ifa);
91447636 1454 if (!locked)
b0d623f7 1455 lck_mtx_lock(rnh_lock);
1c79356b 1456 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
91447636 1457 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
1c79356b 1458 else
91447636 1459 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, 0);
6d2010ae 1460 IFA_LOCK(&ia->ia_ifa);
1c79356b 1461 ia->ia_flags &= ~IFA_ROUTE;
6d2010ae 1462 IFA_UNLOCK(&ia->ia_ifa);
91447636 1463 if (!locked)
b0d623f7
A
1464 lck_mtx_unlock(rnh_lock);
1465}
1466
1467/*
1468 * Caller must hold in_ifaddr_rwlock as writer.
1469 */
1470static void
1471in_iahash_remove(struct in_ifaddr *ia)
1472{
6d2010ae
A
1473 lck_rw_assert(in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1474 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
b0d623f7 1475
6d2010ae
A
1476 if (!IA_IS_HASHED(ia)) {
1477 panic("attempt to remove wrong ia %p from hash table\n", ia);
1478 /* NOTREACHED */
1479 }
b0d623f7
A
1480 TAILQ_REMOVE(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
1481 IA_HASH_INIT(ia);
6d2010ae
A
1482 if (IFA_REMREF_LOCKED(&ia->ia_ifa) == NULL) {
1483 panic("%s: unexpected (missing) refcnt ifa=%p", __func__,
1484 &ia->ia_ifa);
1485 /* NOTREACHED */
1486 }
b0d623f7
A
1487}
1488
1489/*
1490 * Caller must hold in_ifaddr_rwlock as writer.
1491 */
1492static void
1493in_iahash_insert(struct in_ifaddr *ia)
1494{
6d2010ae
A
1495 lck_rw_assert(in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1496 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1497
1498 if (ia->ia_addr.sin_family != AF_INET) {
b0d623f7 1499 panic("attempt to insert wrong ia %p into hash table\n", ia);
6d2010ae
A
1500 /* NOTREACHED */
1501 } else if (IA_IS_HASHED(ia)) {
b0d623f7 1502 panic("attempt to double-insert ia %p into hash table\n", ia);
6d2010ae
A
1503 /* NOTREACHED */
1504 }
b0d623f7 1505 TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
6d2010ae 1506 IFA_ADDREF_LOCKED(&ia->ia_ifa);
b0d623f7
A
1507}
1508
1509/*
1510 * Some point to point interfaces that are tunnels
1511 * borrow the address from an underlying interface (e.g.
1512 * VPN server). In order for source address selection logic to
1513 * find the underlying interface first, we add the address
1514 * of borrowing point to point interfaces at the end of the list.
1515 * (see rdar://6733789)
1516 *
1517 * Caller must hold in_ifaddr_rwlock as writer.
1518 */
1519static void
1520in_iahash_insert_ptp(struct in_ifaddr *ia)
1521{
1522 struct in_ifaddr *tmp_ifa;
1523 struct ifnet *tmp_ifp;
1524
6d2010ae
A
1525 lck_rw_assert(in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1526 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1527
1528 if (ia->ia_addr.sin_family != AF_INET) {
b0d623f7 1529 panic("attempt to insert wrong ia %p into hash table\n", ia);
6d2010ae
A
1530 /* NOTREACHED */
1531 } else if (IA_IS_HASHED(ia)) {
b0d623f7 1532 panic("attempt to double-insert ia %p into hash table\n", ia);
6d2010ae
A
1533 /* NOTREACHED */
1534 }
1535 IFA_UNLOCK(&ia->ia_ifa);
1536 TAILQ_FOREACH(tmp_ifa, INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1537 ia_hash) {
1538 IFA_LOCK(&tmp_ifa->ia_ifa);
1539 /* ia->ia_addr won't change, so check without lock */
1540 if (IA_SIN(tmp_ifa)->sin_addr.s_addr ==
1541 ia->ia_addr.sin_addr.s_addr) {
1542 IFA_UNLOCK(&tmp_ifa->ia_ifa);
b0d623f7 1543 break;
6d2010ae
A
1544 }
1545 IFA_UNLOCK(&tmp_ifa->ia_ifa);
1546 }
b0d623f7
A
1547 tmp_ifp = (tmp_ifa == NULL) ? NULL : tmp_ifa->ia_ifp;
1548
6d2010ae
A
1549 IFA_LOCK(&ia->ia_ifa);
1550 if (tmp_ifp == NULL) {
1551 TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1552 ia, ia_hash);
1553 } else {
1554 TAILQ_INSERT_TAIL(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1555 ia, ia_hash);
1556 }
1557 IFA_ADDREF_LOCKED(&ia->ia_ifa);
1c79356b
A
1558}
1559
1560/*
1561 * Initialize an interface's internet address
1562 * and routing table entry.
1563 */
1564static int
91447636
A
1565in_ifinit(
1566 struct ifnet *ifp,
1567 struct in_ifaddr *ia,
1568 struct sockaddr_in *sin,
1569 int scrub)
1c79356b 1570{
b0d623f7 1571 u_int32_t i = ntohl(sin->sin_addr.s_addr);
1c79356b 1572 struct sockaddr_in oldaddr;
91447636 1573 int flags = RTF_UP, error;
2d21ac55
A
1574 struct ifaddr *ifa0;
1575 unsigned int cmd;
b0d623f7
A
1576 int oldremoved = 0;
1577
1578 /* Take an extra reference for this routine */
6d2010ae 1579 IFA_ADDREF(&ia->ia_ifa);
1c79356b 1580
b0d623f7 1581 lck_rw_lock_exclusive(in_ifaddr_rwlock);
6d2010ae 1582 IFA_LOCK(&ia->ia_ifa);
1c79356b 1583 oldaddr = ia->ia_addr;
b0d623f7
A
1584 if (IA_IS_HASHED(ia)) {
1585 oldremoved = 1;
1586 in_iahash_remove(ia);
1587 }
1c79356b 1588 ia->ia_addr = *sin;
b0d623f7
A
1589 ia->ia_addr.sin_len = sizeof (*sin);
1590 if ((ifp->if_flags & IFF_POINTOPOINT))
1591 in_iahash_insert_ptp(ia);
6d2010ae 1592 else
b0d623f7 1593 in_iahash_insert(ia);
6d2010ae 1594 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7 1595 lck_rw_done(in_ifaddr_rwlock);
1c79356b 1596
9bccf70c 1597 /*
2d21ac55
A
1598 * Give the interface a chance to initialize if this is its first
1599 * address, and to validate the address if necessary. Send down
1600 * SIOCSIFADDR for first address, and SIOCAIFADDR for alias(es).
1601 * We find the first IPV4 address assigned to it and check if this
1602 * is the same as the one passed into this routine.
9bccf70c 1603 */
2d21ac55
A
1604 ifa0 = ifa_ifpgetprimary(ifp, AF_INET);
1605 cmd = (&ia->ia_ifa == ifa0) ? SIOCSIFADDR : SIOCAIFADDR;
1606 error = ifnet_ioctl(ifp, PF_INET, cmd, ia);
1c79356b 1607 if (error == EOPNOTSUPP)
2d21ac55
A
1608 error = 0;
1609 /*
1610 * If we've just sent down SIOCAIFADDR, send another ioctl down
1611 * for SIOCSIFADDR for the first IPV4 address of the interface,
1612 * because an address change on one of the addresses will result
1613 * in the removal of the previous first IPV4 address. KDP needs
1614 * be reconfigured with the current primary IPV4 address.
1615 */
1616 if (error == 0 && cmd == SIOCAIFADDR) {
316670eb
A
1617 /*
1618 * NOTE: SIOCSIFADDR is defined with struct ifreq
1619 * as parameter, but here we are sending it down
1620 * to the interface with a pointer to struct ifaddr,
1621 * for legacy reasons.
1622 */
2d21ac55
A
1623 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa0);
1624 if (error == EOPNOTSUPP)
1625 error = 0;
1626 }
1627
1628 /* Release reference from ifa_ifpgetprimary() */
6d2010ae 1629 IFA_REMREF(ifa0);
2d21ac55 1630
1c79356b 1631 if (error) {
b0d623f7 1632 lck_rw_lock_exclusive(in_ifaddr_rwlock);
6d2010ae 1633 IFA_LOCK(&ia->ia_ifa);
b0d623f7
A
1634 if (IA_IS_HASHED(ia))
1635 in_iahash_remove(ia);
1c79356b 1636 ia->ia_addr = oldaddr;
b0d623f7
A
1637 if (oldremoved) {
1638 if ((ifp->if_flags & IFF_POINTOPOINT))
1639 in_iahash_insert_ptp(ia);
1640 else
1641 in_iahash_insert(ia);
1642 }
6d2010ae 1643 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7
A
1644 lck_rw_done(in_ifaddr_rwlock);
1645 /* Release extra reference taken above */
6d2010ae 1646 IFA_REMREF(&ia->ia_ifa);
1c79356b
A
1647 return (error);
1648 }
b0d623f7 1649 lck_mtx_lock(rnh_lock);
6d2010ae
A
1650 IFA_LOCK(&ia->ia_ifa);
1651 /*
1652 * Address has been initialized by the link resolver (ARP)
1653 * via ifnet_ioctl() above; it may now generate route(s).
1654 */
1655 ia->ia_ifa.ifa_debug &= ~IFD_NOTREADY;
1c79356b
A
1656 if (scrub) {
1657 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
6d2010ae 1658 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7 1659 in_ifscrub(ifp, ia, 1);
6d2010ae 1660 IFA_LOCK(&ia->ia_ifa);
1c79356b
A
1661 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1662 }
6d2010ae 1663 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1c79356b
A
1664 if (IN_CLASSA(i))
1665 ia->ia_netmask = IN_CLASSA_NET;
1666 else if (IN_CLASSB(i))
1667 ia->ia_netmask = IN_CLASSB_NET;
1668 else
1669 ia->ia_netmask = IN_CLASSC_NET;
1670 /*
1671 * The subnet mask usually includes at least the standard network part,
1672 * but may may be smaller in the case of supernetting.
1673 * If it is set, we believe it.
1674 */
1675 if (ia->ia_subnetmask == 0) {
1676 ia->ia_subnetmask = ia->ia_netmask;
1677 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
1678 } else
1679 ia->ia_netmask &= ia->ia_subnetmask;
1680 ia->ia_net = i & ia->ia_netmask;
1681 ia->ia_subnet = i & ia->ia_subnetmask;
1682 in_socktrim(&ia->ia_sockmask);
1683 /*
1684 * Add route for the network.
1685 */
1686 ia->ia_ifa.ifa_metric = ifp->if_metric;
1687 if (ifp->if_flags & IFF_BROADCAST) {
1688 ia->ia_broadaddr.sin_addr.s_addr =
1689 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
1690 ia->ia_netbroadcast.s_addr =
1691 htonl(ia->ia_net | ~ ia->ia_netmask);
1692 } else if (ifp->if_flags & IFF_LOOPBACK) {
1693 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1694 flags |= RTF_HOST;
1695 } else if (ifp->if_flags & IFF_POINTOPOINT) {
b0d623f7 1696 if (ia->ia_dstaddr.sin_family != AF_INET) {
6d2010ae 1697 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7
A
1698 lck_mtx_unlock(rnh_lock);
1699 /* Release extra reference taken above */
6d2010ae 1700 IFA_REMREF(&ia->ia_ifa);
1c79356b 1701 return (0);
b0d623f7
A
1702 }
1703 ia->ia_dstaddr.sin_len = sizeof (*sin);
1c79356b
A
1704 flags |= RTF_HOST;
1705 }
6d2010ae
A
1706 IFA_UNLOCK(&ia->ia_ifa);
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) {
1732 /* keep the reference on inm added by
1733 * in_addmulti above for storing the
1734 * pointer in allhostsinm
1735 */
1736 ifp->if_allhostsinm = inm;
1737 } else {
1738 printf("Failed to add membership to all-hosts multicast address on interface %s%d\n", ifp->if_name, ifp->if_unit);
1739 }
1740 }
1741 lck_mtx_unlock(&ifp->if_addrconfig_lock);
1c79356b 1742 }
b0d623f7
A
1743
1744 /* Release extra reference taken above */
6d2010ae 1745 IFA_REMREF(&ia->ia_ifa);
1c79356b
A
1746 return (error);
1747}
1748
1749
1750/*
1751 * Return 1 if the address might be a local broadcast address.
1752 */
1753int
6d2010ae 1754in_broadcast(struct in_addr in, struct ifnet *ifp)
1c79356b 1755{
91447636 1756 struct ifaddr *ifa;
b0d623f7 1757 u_int32_t t;
1c79356b 1758
6d2010ae
A
1759 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
1760 return (1);
1c79356b 1761 if ((ifp->if_flags & IFF_BROADCAST) == 0)
6d2010ae 1762 return (0);
1c79356b
A
1763 t = ntohl(in.s_addr);
1764 /*
1765 * Look through the list of addresses for a match
1766 * with a broadcast address.
1767 */
1768#define ia ((struct in_ifaddr *)ifa)
91447636
A
1769 ifnet_lock_shared(ifp);
1770 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
6d2010ae 1771 IFA_LOCK(ifa);
1c79356b
A
1772 if (ifa->ifa_addr->sa_family == AF_INET &&
1773 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
1774 in.s_addr == ia->ia_netbroadcast.s_addr ||
1775 /*
1776 * Check for old-style (host 0) broadcast.
1777 */
1778 t == ia->ia_subnet || t == ia->ia_net) &&
1779 /*
1780 * Check for an all one subnetmask. These
1781 * only exist when an interface gets a secondary
1782 * address.
1783 */
b0d623f7 1784 ia->ia_subnetmask != (u_int32_t)0xffffffff) {
6d2010ae 1785 IFA_UNLOCK(ifa);
91447636 1786 ifnet_lock_done(ifp);
6d2010ae 1787 return (1);
91447636 1788 }
6d2010ae 1789 IFA_UNLOCK(ifa);
0b4e3aa0 1790 }
91447636 1791 ifnet_lock_done(ifp);
1c79356b
A
1792 return (0);
1793#undef ia
1794}
91447636 1795
6d2010ae
A
1796void
1797in_purgeaddrs(struct ifnet *ifp)
1c79356b 1798{
6d2010ae
A
1799 struct ifaddr **ifap;
1800 int err, i;
1c79356b
A
1801
1802 /*
6d2010ae
A
1803 * Be nice, and try the civilized way first. If we can't get
1804 * rid of them this way, then do it the rough way. We must
1805 * only get here during detach time, after the ifnet has been
1806 * removed from the global list and arrays.
1c79356b 1807 */
6d2010ae
A
1808 err = ifnet_get_address_list_family_internal(ifp, &ifap, AF_INET, 1,
1809 M_WAITOK);
1810 if (err == 0 && ifap != NULL) {
1811 for (i = 0; ifap[i] != NULL; i++) {
1812 struct ifaliasreq ifr;
1813 struct ifaddr *ifa;
1814
1815 ifa = ifap[i];
1816 bzero(&ifr, sizeof (ifr));
1817 IFA_LOCK(ifa);
1818 ifr.ifra_addr = *ifa->ifa_addr;
1819 if (ifa->ifa_dstaddr != NULL)
1820 ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
1821 IFA_UNLOCK(ifa);
1822 err = in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
1823 kernproc);
1824 /* if we lost the race, ignore it */
1825 if (err == EADDRNOTAVAIL)
1826 err = 0;
1827 if (err != 0) {
1828 char s_addr[MAX_IPv4_STR_LEN];
1829 char s_dstaddr[MAX_IPv4_STR_LEN];
1830 struct in_addr *s, *d;
1831
1832 IFA_LOCK(ifa);
1833 s = &((struct sockaddr_in *)
316670eb 1834 (void *)ifa->ifa_addr)->sin_addr;
6d2010ae 1835 d = &((struct sockaddr_in *)
316670eb 1836 (void *)ifa->ifa_dstaddr)->sin_addr;
6d2010ae
A
1837 (void) inet_ntop(AF_INET, &s->s_addr, s_addr,
1838 sizeof (s_addr));
1839 (void) inet_ntop(AF_INET, &d->s_addr, s_dstaddr,
1840 sizeof (s_dstaddr));
1841 IFA_UNLOCK(ifa);
1842
1843 printf("%s: SIOCDIFADDR ifp=%p ifa_addr=%s "
1844 "ifa_dstaddr=%s (err=%d)\n", __func__, ifp,
1845 s_addr, s_dstaddr, err);
1846 }
1847 }
1848 ifnet_free_address_list(ifap);
1849 } else if (err != 0 && err != ENXIO) {
1850 printf("%s: error retrieving list of AF_INET addresses for "
1851 "ifp=%p (err=%d)\n", __func__, ifp, err);
1c79356b 1852 }
1c79356b 1853}
91447636 1854
2d21ac55 1855int inet_aton(char *cp, struct in_addr *pin);
91447636
A
1856int
1857inet_aton(char * cp, struct in_addr * pin)
1858{
2d21ac55 1859 u_char * b = (unsigned char *)pin;
91447636
A
1860 int i;
1861 char * p;
1862
1863 for (p = cp, i = 0; i < 4; i++) {
b0d623f7 1864 u_int32_t l = strtoul(p, 0, 0);
91447636
A
1865 if (l > 255)
1866 return (FALSE);
1867 b[i] = l;
1868 p = strchr(p, '.');
1869 if (i < 3 && p == NULL)
1870 return (FALSE);
1871 p++;
1872 }
1873 return (TRUE);
1874}
6d2010ae
A
1875
1876int inet_ntoa2(struct in_addr * pin, char * cp, const int len);
1877int inet_ntoa2(struct in_addr * pin, char * cp, const int len)
1878{
1879 int ret;
1880
1881 /* address is in network byte order */
1882 ret = snprintf(cp, len, "%u.%u.%u.%u", pin->s_addr & 0xFF,
1883 (pin->s_addr >> 8) & 0xFF, (pin->s_addr >> 16) & 0xFF,
1884 (pin->s_addr >> 24) & 0xFF);
1885
1886 return ret < len ? TRUE : FALSE;
1887}
b0d623f7
A
1888
1889/*
1890 * Called as part of ip_init
1891 */
1892void
1893in_ifaddr_init(void)
1894{
6d2010ae
A
1895 in_multi_init();
1896
b0d623f7
A
1897 PE_parse_boot_argn("ifa_debug", &inifa_debug, sizeof (inifa_debug));
1898
1899 inifa_size = (inifa_debug == 0) ? sizeof (struct in_ifaddr) :
1900 sizeof (struct in_ifaddr_dbg);
1901
1902 inifa_zone = zinit(inifa_size, INIFA_ZONE_MAX * inifa_size,
1903 0, INIFA_ZONE_NAME);
6d2010ae 1904 if (inifa_zone == NULL) {
b0d623f7 1905 panic("%s: failed allocating %s", __func__, INIFA_ZONE_NAME);
6d2010ae
A
1906 /* NOTREACHED */
1907 }
b0d623f7 1908 zone_change(inifa_zone, Z_EXPAND, TRUE);
6d2010ae
A
1909 zone_change(inifa_zone, Z_CALLERACCT, FALSE);
1910
1911 lck_mtx_init(&inifa_trash_lock, ifa_mtx_grp, ifa_mtx_attr);
1912 TAILQ_INIT(&inifa_trash_head);
b0d623f7
A
1913}
1914
1915static struct in_ifaddr *
1916in_ifaddr_alloc(int how)
1917{
1918 struct in_ifaddr *inifa;
1919
1920 inifa = (how == M_WAITOK) ? zalloc(inifa_zone) :
1921 zalloc_noblock(inifa_zone);
1922 if (inifa != NULL) {
1923 bzero(inifa, inifa_size);
1924 inifa->ia_ifa.ifa_free = in_ifaddr_free;
1925 inifa->ia_ifa.ifa_debug |= IFD_ALLOC;
6d2010ae 1926 ifa_lock_init(&inifa->ia_ifa);
b0d623f7
A
1927 if (inifa_debug != 0) {
1928 struct in_ifaddr_dbg *inifa_dbg =
1929 (struct in_ifaddr_dbg *)inifa;
1930 inifa->ia_ifa.ifa_debug |= IFD_DEBUG;
1931 inifa->ia_ifa.ifa_trace = in_ifaddr_trace;
6d2010ae
A
1932 inifa->ia_ifa.ifa_attached = in_ifaddr_attached;
1933 inifa->ia_ifa.ifa_detached = in_ifaddr_detached;
b0d623f7
A
1934 ctrace_record(&inifa_dbg->inifa_alloc);
1935 }
1936 }
1937 return (inifa);
1938}
1939
1940static void
1941in_ifaddr_free(struct ifaddr *ifa)
1942{
6d2010ae
A
1943 IFA_LOCK_ASSERT_HELD(ifa);
1944
1945 if (ifa->ifa_refcnt != 0) {
b0d623f7 1946 panic("%s: ifa %p bad ref cnt", __func__, ifa);
6d2010ae
A
1947 /* NOTREACHED */
1948 } if (!(ifa->ifa_debug & IFD_ALLOC)) {
b0d623f7 1949 panic("%s: ifa %p cannot be freed", __func__, ifa);
6d2010ae
A
1950 /* NOTREACHED */
1951 }
b0d623f7
A
1952 if (ifa->ifa_debug & IFD_DEBUG) {
1953 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
1954 ctrace_record(&inifa_dbg->inifa_free);
1955 bcopy(&inifa_dbg->inifa, &inifa_dbg->inifa_old,
1956 sizeof (struct in_ifaddr));
6d2010ae
A
1957 if (ifa->ifa_debug & IFD_TRASHED) {
1958 /* Become a regular mutex, just in case */
1959 IFA_CONVERT_LOCK(ifa);
1960 lck_mtx_lock(&inifa_trash_lock);
1961 TAILQ_REMOVE(&inifa_trash_head, inifa_dbg,
1962 inifa_trash_link);
1963 lck_mtx_unlock(&inifa_trash_lock);
1964 ifa->ifa_debug &= ~IFD_TRASHED;
1965 }
b0d623f7 1966 }
6d2010ae
A
1967 IFA_UNLOCK(ifa);
1968 ifa_lock_destroy(ifa);
b0d623f7
A
1969 bzero(ifa, sizeof (struct in_ifaddr));
1970 zfree(inifa_zone, ifa);
1971}
1972
6d2010ae
A
1973static void
1974in_ifaddr_attached(struct ifaddr *ifa)
1975{
1976 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
1977
1978 IFA_LOCK_ASSERT_HELD(ifa);
1979
1980 if (!(ifa->ifa_debug & IFD_DEBUG)) {
1981 panic("%s: ifa %p has no debug structure", __func__, ifa);
1982 /* NOTREACHED */
1983 }
1984 if (ifa->ifa_debug & IFD_TRASHED) {
1985 /* Become a regular mutex, just in case */
1986 IFA_CONVERT_LOCK(ifa);
1987 lck_mtx_lock(&inifa_trash_lock);
1988 TAILQ_REMOVE(&inifa_trash_head, inifa_dbg, inifa_trash_link);
1989 lck_mtx_unlock(&inifa_trash_lock);
1990 ifa->ifa_debug &= ~IFD_TRASHED;
1991 }
1992}
1993
1994static void
1995in_ifaddr_detached(struct ifaddr *ifa)
1996{
1997 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
1998
1999 IFA_LOCK_ASSERT_HELD(ifa);
2000
2001 if (!(ifa->ifa_debug & IFD_DEBUG)) {
2002 panic("%s: ifa %p has no debug structure", __func__, ifa);
2003 /* NOTREACHED */
2004 } else if (ifa->ifa_debug & IFD_TRASHED) {
2005 panic("%s: ifa %p is already in trash list", __func__, ifa);
2006 /* NOTREACHED */
2007 }
2008 ifa->ifa_debug |= IFD_TRASHED;
2009 /* Become a regular mutex, just in case */
2010 IFA_CONVERT_LOCK(ifa);
2011 lck_mtx_lock(&inifa_trash_lock);
2012 TAILQ_INSERT_TAIL(&inifa_trash_head, inifa_dbg, inifa_trash_link);
2013 lck_mtx_unlock(&inifa_trash_lock);
2014}
2015
b0d623f7
A
2016static void
2017in_ifaddr_trace(struct ifaddr *ifa, int refhold)
2018{
2019 struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2020 ctrace_t *tr;
2021 u_int32_t idx;
2022 u_int16_t *cnt;
2023
6d2010ae 2024 if (!(ifa->ifa_debug & IFD_DEBUG)) {
b0d623f7 2025 panic("%s: ifa %p has no debug structure", __func__, ifa);
6d2010ae
A
2026 /* NOTREACHED */
2027 }
b0d623f7
A
2028 if (refhold) {
2029 cnt = &inifa_dbg->inifa_refhold_cnt;
2030 tr = inifa_dbg->inifa_refhold;
2031 } else {
2032 cnt = &inifa_dbg->inifa_refrele_cnt;
2033 tr = inifa_dbg->inifa_refrele;
2034 }
2035
6d2010ae 2036 idx = atomic_add_16_ov(cnt, 1) % INIFA_TRACE_HIST_SIZE;
b0d623f7
A
2037 ctrace_record(&tr[idx]);
2038}