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