]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in.c
85b9d38afa59c376a06a641ae9fe1cd709795682
[apple/xnu.git] / bsd / netinet / in.c
1 /*
2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1982, 1986, 1991, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)in.c 8.4 (Berkeley) 1/9/95
61 * $FreeBSD: src/sys/netinet/in.c,v 1.44.2.5 2001/08/13 16:26:17 ume Exp $
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>
74 #include <sys/syslog.h>
75 #include <sys/mcache.h>
76 #include <kern/zalloc.h>
77
78 #include <pexpert/pexpert.h>
79
80 #include <net/if.h>
81 #include <net/if_types.h>
82 #include <net/route.h>
83 #include <net/kpi_protocol.h>
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
100 #if PF
101 #include <net/pfvar.h>
102 #endif /* PF */
103
104 static int in_mask2len(struct in_addr *);
105 static void in_len2mask(struct in_addr *, int);
106 static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
107 struct ifnet *, struct proc *);
108
109 static void in_socktrim(struct sockaddr_in *);
110 static int in_ifinit(struct ifnet *,
111 struct in_ifaddr *, struct sockaddr_in *, int);
112
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
122 static void in_iahash_remove(struct in_ifaddr *);
123 static void in_iahash_insert(struct in_ifaddr *);
124 static void in_iahash_insert_ptp(struct in_ifaddr *);
125 static struct in_ifaddr *in_ifaddr_alloc(int);
126 static void in_ifaddr_attached(struct ifaddr *);
127 static void in_ifaddr_detached(struct ifaddr *);
128 static void in_ifaddr_free(struct ifaddr *);
129 static void in_ifaddr_trace(struct ifaddr *, int);
130
131 static int subnetsarelocal = 0;
132 SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW | CTLFLAG_LOCKED,
133 &subnetsarelocal, 0, "");
134
135 /* Track whether or not the SIOCARPIPLL ioctl has been called */
136 __private_extern__ u_int32_t ipv4_ll_arp_aware = 0;
137
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
143 struct in_ifaddr_dbg {
144 struct in_ifaddr inifa; /* in_ifaddr */
145 struct in_ifaddr inifa_old; /* saved in_ifaddr */
146 u_int16_t inifa_refhold_cnt; /* # of IFA_ADDREF */
147 u_int16_t inifa_refrele_cnt; /* # of IFA_REMREF */
148 /*
149 * Alloc and free callers.
150 */
151 ctrace_t inifa_alloc;
152 ctrace_t inifa_free;
153 /*
154 * Circular lists of IFA_ADDREF and IFA_REMREF callers.
155 */
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;
162 };
163
164 /* List of trash in_ifaddr entries protected by inifa_trash_lock */
165 static TAILQ_HEAD(, in_ifaddr_dbg) inifa_trash_head;
166 static decl_lck_mtx_data(, inifa_trash_lock);
167
168 #if DEBUG
169 static unsigned int inifa_debug = 1; /* debugging (enabled) */
170 #else
171 static unsigned int inifa_debug; /* debugging (disabled) */
172 #endif /* !DEBUG */
173 static unsigned int inifa_size; /* size of zone element */
174 static 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
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 */
186 int
187 inaddr_local(struct in_addr in)
188 {
189 struct rtentry *rt;
190 struct sockaddr_in sin;
191 int local = 0;
192
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) {
197 local = 1;
198 } else {
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 }
214 }
215 return (local);
216 }
217
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 */
224 int
225 in_localaddr(struct in_addr in)
226 {
227 u_int32_t i = ntohl(in.s_addr);
228 struct in_ifaddr *ia;
229
230 if (subnetsarelocal) {
231 lck_rw_lock_shared(in_ifaddr_rwlock);
232 for (ia = in_ifaddrhead.tqh_first; ia;
233 ia = ia->ia_link.tqe_next) {
234 IFA_LOCK(&ia->ia_ifa);
235 if ((i & ia->ia_netmask) == ia->ia_net) {
236 IFA_UNLOCK(&ia->ia_ifa);
237 lck_rw_done(in_ifaddr_rwlock);
238 return (1);
239 }
240 IFA_UNLOCK(&ia->ia_ifa);
241 }
242 lck_rw_done(in_ifaddr_rwlock);
243 } else {
244 lck_rw_lock_shared(in_ifaddr_rwlock);
245 for (ia = in_ifaddrhead.tqh_first; ia;
246 ia = ia->ia_link.tqe_next) {
247 IFA_LOCK(&ia->ia_ifa);
248 if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
249 IFA_UNLOCK(&ia->ia_ifa);
250 lck_rw_done(in_ifaddr_rwlock);
251 return (1);
252 }
253 IFA_UNLOCK(&ia->ia_ifa);
254 }
255 lck_rw_done(in_ifaddr_rwlock);
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 */
265 int
266 in_canforward(struct in_addr in)
267 {
268 u_int32_t i = ntohl(in.s_addr);
269 u_int32_t net;
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 */
284 static void
285 in_socktrim(struct sockaddr_in *ap)
286 {
287 char *cplim = (char *) &ap->sin_addr;
288 char *cp = (char *) (&ap->sin_addr + 1);
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
298 static int
299 in_mask2len(struct in_addr *mask)
300 {
301 size_t x, y;
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
319 static void
320 in_len2mask(struct in_addr *mask, int len)
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
333 static int in_interfaces; /* number of external internet interfaces */
334
335 static int
336 in_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
347 /*
348 * Generic internet control operations (ioctl's).
349 * Ifp is 0 if not an interface-specific ioctl.
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:???
366 */
367 /* ARGSUSED */
368 int
369 in_control(
370 struct socket *so,
371 u_long cmd,
372 caddr_t data,
373 struct ifnet *ifp,
374 struct proc *p)
375 {
376 struct ifreq *ifr = (struct ifreq *)data;
377 struct in_ifaddr *ia = NULL, *iap;
378 struct ifaddr *ifa;
379 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
380 struct sockaddr_in oldaddr;
381 int error = 0;
382 int hostIsNew, maskIsNew;
383 struct kev_msg ev_msg;
384 struct kev_in_data in_event_data;
385
386 bzero(&in_event_data, sizeof(struct kev_in_data));
387 bzero(&ev_msg, sizeof(struct kev_msg));
388 switch (cmd) {
389 case SIOCALIFADDR:
390 case SIOCDLIFADDR:
391 if ((error = proc_suser(p)) != 0)
392 return error;
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 */
406 if (ifp) {
407 lck_rw_lock_shared(in_ifaddr_rwlock);
408 for (iap = in_ifaddrhead.tqh_first; iap;
409 iap = iap->ia_link.tqe_next)
410 if (iap->ia_ifp == ifp) {
411 IFA_LOCK(&iap->ia_ifa);
412 if (((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr ==
413 iap->ia_addr.sin_addr.s_addr) {
414 ia = iap;
415 IFA_UNLOCK(&iap->ia_ifa);
416 break;
417 } else if (ia == NULL) {
418 ia = iap;
419 if (ifr->ifr_addr.sa_family != AF_INET) {
420 IFA_UNLOCK(&iap->ia_ifa);
421 break;
422 }
423 }
424 IFA_UNLOCK(&iap->ia_ifa);
425 }
426 /* take a reference on ia before releasing lock */
427 if (ia != NULL) {
428 IFA_ADDREF(&ia->ia_ifa);
429 }
430 lck_rw_done(in_ifaddr_rwlock);
431 }
432 switch (cmd) {
433 case SIOCAUTOADDR:
434 case SIOCARPIPLL:
435 if ((error = proc_suser(p)) != 0) {
436 goto done;
437 }
438 if (ifp == 0) {
439 error = EADDRNOTAVAIL;
440 goto done;
441 }
442 break;
443
444 case SIOCAIFADDR:
445 case SIOCDIFADDR:
446 if (ifp == 0) {
447 error = EADDRNOTAVAIL;
448 goto done;
449 }
450 if (ifra->ifra_addr.sin_family == AF_INET) {
451 struct in_ifaddr *oia;
452
453 lck_rw_lock_shared(in_ifaddr_rwlock);
454 for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
455 IFA_LOCK(&ia->ia_ifa);
456 if (ia->ia_ifp == ifp &&
457 ia->ia_addr.sin_addr.s_addr ==
458 ifra->ifra_addr.sin_addr.s_addr) {
459 IFA_ADDREF_LOCKED(&ia->ia_ifa);
460 IFA_UNLOCK(&ia->ia_ifa);
461 break;
462 }
463 IFA_UNLOCK(&ia->ia_ifa);
464 }
465 lck_rw_done(in_ifaddr_rwlock);
466 if (oia != NULL)
467 IFA_REMREF(&oia->ia_ifa);
468 if ((ifp->if_flags & IFF_POINTOPOINT)
469 && (cmd == SIOCAIFADDR)
470 && (ifra->ifra_dstaddr.sin_addr.s_addr
471 == INADDR_ANY)) {
472 error = EDESTADDRREQ;
473 goto done;
474 }
475 }
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 }
484 /* FALLTHROUGH */
485 case SIOCSIFADDR:
486 case SIOCSIFNETMASK:
487 case SIOCSIFDSTADDR:
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) {
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 }
507 if (ia == NULL) {
508 ia = in_ifaddr_alloc(M_WAITOK);
509 if (ia == NULL) {
510 error = ENOBUFS;
511 goto done;
512 }
513 ifnet_lock_exclusive(ifp);
514 ifa = &ia->ia_ifa;
515 IFA_LOCK(ifa);
516 /* Hold a reference for this routine */
517 IFA_ADDREF_LOCKED(ifa);
518 IA_HASH_INIT(ia);
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++;
530 /* if_attach_ifa() holds a reference for ifa_link */
531 if_attach_ifa(ifp, ifa);
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);
541 ifnet_lock_done(ifp);
542 lck_rw_lock_exclusive(in_ifaddr_rwlock);
543 /* Hold a reference for ia_link */
544 IFA_ADDREF(ifa);
545 TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
546 lck_rw_done(in_ifaddr_rwlock);
547 error = in_domifattach(ifp);
548 /* discard error,can be cold with unsupported interfaces */
549 if (error)
550 error = 0;
551 }
552 break;
553
554 case SIOCPROTOATTACH:
555 case SIOCPROTODETACH:
556 if ((error = proc_suser(p)) != 0) {
557 goto done;
558 }
559 if (ifp == 0) {
560 error = EADDRNOTAVAIL;
561 goto done;
562 }
563 break;
564
565 case SIOCSIFBRDADDR:
566 if ((so->so_state & SS_PRIV) == 0) {
567 error = EPERM;
568 goto done;
569 }
570 /* FALLTHROUGH */
571
572 case SIOCGIFADDR:
573 case SIOCGIFNETMASK:
574 case SIOCGIFDSTADDR:
575 case SIOCGIFBRDADDR:
576 if (ia == (struct in_ifaddr *)0) {
577 error = EADDRNOTAVAIL;
578 goto done;
579 }
580 break;
581 }
582 switch (cmd) {
583 case SIOCAUTOADDR:
584 ifnet_lock_exclusive(ifp);
585 if (ifr->ifr_intval)
586 ifp->if_eflags |= IFEF_AUTOCONFIGURING;
587 else
588 ifp->if_eflags &= ~IFEF_AUTOCONFIGURING;
589 ifnet_lock_done(ifp);
590 break;
591
592 case SIOCARPIPLL:
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);
600 break;
601
602 case SIOCGIFADDR:
603 IFA_LOCK(&ia->ia_ifa);
604 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
605 IFA_UNLOCK(&ia->ia_ifa);
606 break;
607
608 case SIOCGIFBRDADDR:
609 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
610 error = EINVAL;
611 break;
612 }
613 IFA_LOCK(&ia->ia_ifa);
614 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
615 IFA_UNLOCK(&ia->ia_ifa);
616 break;
617
618 case SIOCGIFDSTADDR:
619 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
620 error = EINVAL;
621 break;
622 }
623 IFA_LOCK(&ia->ia_ifa);
624 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
625 IFA_UNLOCK(&ia->ia_ifa);
626 break;
627
628 case SIOCGIFNETMASK:
629 IFA_LOCK(&ia->ia_ifa);
630 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
631 IFA_UNLOCK(&ia->ia_ifa);
632 break;
633
634 case SIOCSIFDSTADDR:
635 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
636 error = EINVAL;
637 break;
638 }
639 IFA_LOCK(&ia->ia_ifa);
640 oldaddr = ia->ia_dstaddr;
641 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
642 if (ia->ia_dstaddr.sin_family == AF_INET)
643 ia->ia_dstaddr.sin_len = sizeof (struct sockaddr_in);
644 IFA_UNLOCK(&ia->ia_ifa);
645 error = ifnet_ioctl(ifp, PF_INET, SIOCSIFDSTADDR, ia);
646 IFA_LOCK(&ia->ia_ifa);
647 if (error == EOPNOTSUPP) {
648 error = 0;
649 }
650 if (error) {
651 ia->ia_dstaddr = oldaddr;
652 IFA_UNLOCK(&ia->ia_ifa);
653 break;
654 }
655 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
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;
660
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;
675 IFA_UNLOCK(&ia->ia_ifa);
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;
678 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
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
686 lck_mtx_lock(rnh_lock);
687 IFA_LOCK(&ia->ia_ifa);
688 if (ia->ia_flags & IFA_ROUTE) {
689 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
690 IFA_UNLOCK(&ia->ia_ifa);
691 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
692 IFA_LOCK(&ia->ia_ifa);
693 ia->ia_ifa.ifa_dstaddr =
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);
700 }
701 lck_mtx_unlock(rnh_lock);
702 break;
703
704 case SIOCSIFBRDADDR:
705 if ((ifp->if_flags & IFF_BROADCAST) == 0) {
706 error = EINVAL;
707 break;
708 }
709 IFA_LOCK(&ia->ia_ifa);
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;
715
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;
730 IFA_UNLOCK(&ia->ia_ifa);
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;
733 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
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:
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 */
754 break;
755
756 case SIOCPROTOATTACH:
757 error = in_domifattach(ifp);
758 break;
759
760 case SIOCPROTODETACH:
761 /*
762 * If an IPv4 address is still present, refuse to detach.
763 */
764 ifnet_lock_shared(ifp);
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);
769 break;
770 }
771 IFA_UNLOCK(ifa);
772 }
773 ifnet_lock_done(ifp);
774 if (ifa != NULL) {
775 error = EBUSY;
776 break;
777 }
778
779 error = proto_unplumb(PF_INET, ifp);
780 break;
781
782 case SIOCSIFNETMASK: {
783 u_long i;
784
785 i = ifra->ifra_addr.sin_addr.s_addr;
786 IFA_LOCK(&ia->ia_ifa);
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;
791
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;
806 IFA_UNLOCK(&ia->ia_ifa);
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;
809 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
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;
818 }
819 case SIOCAIFADDR:
820 maskIsNew = 0;
821 hostIsNew = 1;
822 error = 0;
823
824 IFA_LOCK(&ia->ia_ifa);
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) {
834 IFA_UNLOCK(&ia->ia_ifa);
835 in_ifscrub(ifp, ia, 0);
836 IFA_LOCK(&ia->ia_ifa);
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)) {
844 IFA_UNLOCK(&ia->ia_ifa);
845 in_ifscrub(ifp, ia, 0);
846 IFA_LOCK(&ia->ia_ifa);
847 ia->ia_dstaddr = ifra->ifra_dstaddr;
848 ia->ia_dstaddr.sin_len = sizeof (struct sockaddr_in);
849 maskIsNew = 1; /* We lie; but the effect's the same */
850 }
851 if (ifra->ifra_addr.sin_family == AF_INET &&
852 (hostIsNew || maskIsNew)) {
853 IFA_UNLOCK(&ia->ia_ifa);
854 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
855 } else {
856 IFA_UNLOCK(&ia->ia_ifa);
857 }
858 #if PF
859 if (!error)
860 (void) pf_ifaddr_hook(ifp, cmd);
861 #endif /* PF */
862 IFA_LOCK(&ia->ia_ifa);
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
871 if ((error == 0) || (error == EEXIST)) {
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;
893 IFA_UNLOCK(&ia->ia_ifa);
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;
896 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
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);
903 } else {
904 IFA_UNLOCK(&ia->ia_ifa);
905 }
906 break;
907
908 case SIOCDIFADDR:
909 error = ifnet_ioctl(ifp, PF_INET, SIOCDIFADDR, ia);
910 if (error == EOPNOTSUPP)
911 error = 0;
912 if (error != 0) {
913 break;
914 }
915
916 /* Fill out the kernel event information */
917 ev_msg.vendor_code = KEV_VENDOR_APPLE;
918 ev_msg.kev_class = KEV_NETWORK_CLASS;
919 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
920
921 ev_msg.event_code = KEV_INET_ADDR_DELETED;
922
923 IFA_LOCK(&ia->ia_ifa);
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;
936 IFA_UNLOCK(&ia->ia_ifa);
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;
939 in_event_data.link_data.if_unit = (u_int32_t) ifp->if_unit;
940
941 ev_msg.dv[0].data_ptr = &in_event_data;
942 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
943 ev_msg.dv[1].data_length = 0;
944
945 ifa = &ia->ia_ifa;
946 lck_rw_lock_exclusive(in_ifaddr_rwlock);
947 /* Release ia_link reference */
948 IFA_REMREF(ifa);
949 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
950 IFA_LOCK(ifa);
951 if (IA_IS_HASHED(ia))
952 in_iahash_remove(ia);
953 IFA_UNLOCK(ifa);
954 lck_rw_done(in_ifaddr_rwlock);
955
956 /*
957 * in_ifscrub kills the interface route.
958 */
959 in_ifscrub(ifp, ia, 0);
960 ifnet_lock_exclusive(ifp);
961 IFA_LOCK(ifa);
962 /* if_detach_ifa() releases ifa_link reference */
963 if_detach_ifa(ifp, ifa);
964 /* Our reference to this address is dropped at the bottom */
965 IFA_UNLOCK(ifa);
966
967 /*
968 * If the interface supports multicast, and no address is left,
969 * remove the "all hosts" multicast group from that interface.
970 */
971 if ((ifp->if_flags & IFF_MULTICAST) != 0 ||
972 ifp->if_allhostsinm != NULL ) {
973
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);
978 break;
979 }
980 IFA_UNLOCK(ifa);
981 }
982 ifnet_lock_done(ifp);
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 {
995 ifnet_lock_done(ifp);
996 }
997
998 /* Post the kernel event */
999 kev_post_msg(&ev_msg);
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() */
1012 IFA_REMREF(ifa);
1013 }
1014 #if PF
1015 (void) pf_ifaddr_hook(ifp, cmd);
1016 #endif /* PF */
1017 break;
1018
1019 #ifdef __APPLE__
1020 case SIOCSETOT: {
1021 /*
1022 * Inspiration from tcp_ctloutput() and ip_ctloutput()
1023 * Special ioctl for OpenTransport sockets
1024 */
1025 struct inpcb *inp, *cloned_inp;
1026 int error2 = 0;
1027 int cloned_fd = *(int *)data;
1028
1029 inp = sotoinpcb(so);
1030 if (inp == NULL) {
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;
1037 error2 = file_socket(cloned_fd, &cloned_so);
1038 if (error2){
1039 break;
1040 }
1041 cloned_inp = sotoinpcb(cloned_so);
1042 file_drop(cloned_fd);
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) {
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 */
1072 imo = ip_allocmoptions(M_WAITOK);
1073 if (imo == NULL) {
1074 error2 = ENOBUFS;
1075 break;
1076 }
1077 inp->inp_moptions = imo;
1078 }
1079
1080 error2 = imo_clone(cloned_imo, imo);
1081 }
1082 }
1083 break;
1084 }
1085 #endif /* __APPLE__ */
1086
1087 default:
1088 error = EOPNOTSUPP;
1089 }
1090 done:
1091 if (ia != NULL) {
1092 IFA_REMREF(&ia->ia_ifa);
1093 }
1094 return (error);
1095 }
1096
1097 /*
1098 * SIOC[GAD]LIFADDR.
1099 * SIOCGLIFADDR: get first address. (?!?)
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 */
1113 static int
1114 in_lifaddr_ioctl(
1115 struct socket *so,
1116 u_long cmd,
1117 caddr_t data,
1118 struct ifnet *ifp,
1119 struct proc *p)
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");
1127 /*NOTREACHED*/
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*/
1152 return EOPNOTSUPP;
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;
1187 struct in_addr mask, candidate;
1188 struct in_addr match = { 0 };
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
1220 ifnet_lock_shared(ifp);
1221 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1222 IFA_LOCK(ifa);
1223 if (ifa->ifa_addr->sa_family != AF_INET6) {
1224 IFA_UNLOCK(ifa);
1225 continue;
1226 }
1227 if (!cmp) {
1228 IFA_UNLOCK(ifa);
1229 break;
1230 }
1231 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
1232 candidate.s_addr &= mask.s_addr;
1233 IFA_UNLOCK(ifa);
1234 if (candidate.s_addr == match.s_addr)
1235 break;
1236 }
1237 if (ifa != NULL)
1238 IFA_ADDREF(ifa);
1239 ifnet_lock_done(ifp);
1240 if (!ifa)
1241 return EADDRNOTAVAIL;
1242 ia = (struct in_ifaddr *)ifa;
1243
1244 if (cmd == SIOCGLIFADDR) {
1245 IFA_LOCK(ifa);
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
1260 IFA_UNLOCK(ifa);
1261 IFA_REMREF(ifa);
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
1271 IFA_LOCK(ifa);
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);
1280 IFA_UNLOCK(ifa);
1281 IFA_REMREF(ifa);
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 */
1294 void
1295 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, int locked)
1296 {
1297 IFA_LOCK(&ia->ia_ifa);
1298 if ((ia->ia_flags & IFA_ROUTE) == 0) {
1299 IFA_UNLOCK(&ia->ia_ifa);
1300 return;
1301 }
1302 IFA_UNLOCK(&ia->ia_ifa);
1303 if (!locked)
1304 lck_mtx_lock(rnh_lock);
1305 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
1306 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
1307 else
1308 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1309 IFA_LOCK(&ia->ia_ifa);
1310 ia->ia_flags &= ~IFA_ROUTE;
1311 IFA_UNLOCK(&ia->ia_ifa);
1312 if (!locked)
1313 lck_mtx_unlock(rnh_lock);
1314 }
1315
1316 /*
1317 * Caller must hold in_ifaddr_rwlock as writer.
1318 */
1319 static void
1320 in_iahash_remove(struct in_ifaddr *ia)
1321 {
1322 lck_rw_assert(in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1323 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1324
1325 if (!IA_IS_HASHED(ia)) {
1326 panic("attempt to remove wrong ia %p from hash table\n", ia);
1327 /* NOTREACHED */
1328 }
1329 TAILQ_REMOVE(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
1330 IA_HASH_INIT(ia);
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 }
1336 }
1337
1338 /*
1339 * Caller must hold in_ifaddr_rwlock as writer.
1340 */
1341 static void
1342 in_iahash_insert(struct in_ifaddr *ia)
1343 {
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) {
1348 panic("attempt to insert wrong ia %p into hash table\n", ia);
1349 /* NOTREACHED */
1350 } else if (IA_IS_HASHED(ia)) {
1351 panic("attempt to double-insert ia %p into hash table\n", ia);
1352 /* NOTREACHED */
1353 }
1354 TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
1355 IFA_ADDREF_LOCKED(&ia->ia_ifa);
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 */
1368 static void
1369 in_iahash_insert_ptp(struct in_ifaddr *ia)
1370 {
1371 struct in_ifaddr *tmp_ifa;
1372 struct ifnet *tmp_ifp;
1373
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) {
1378 panic("attempt to insert wrong ia %p into hash table\n", ia);
1379 /* NOTREACHED */
1380 } else if (IA_IS_HASHED(ia)) {
1381 panic("attempt to double-insert ia %p into hash table\n", ia);
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);
1392 break;
1393 }
1394 IFA_UNLOCK(&tmp_ifa->ia_ifa);
1395 }
1396 tmp_ifp = (tmp_ifa == NULL) ? NULL : tmp_ifa->ia_ifp;
1397
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);
1407 }
1408
1409 /*
1410 * Initialize an interface's internet address
1411 * and routing table entry.
1412 */
1413 static int
1414 in_ifinit(
1415 struct ifnet *ifp,
1416 struct in_ifaddr *ia,
1417 struct sockaddr_in *sin,
1418 int scrub)
1419 {
1420 u_int32_t i = ntohl(sin->sin_addr.s_addr);
1421 struct sockaddr_in oldaddr;
1422 int flags = RTF_UP, error;
1423 struct ifaddr *ifa0;
1424 unsigned int cmd;
1425 int oldremoved = 0;
1426
1427 /* Take an extra reference for this routine */
1428 IFA_ADDREF(&ia->ia_ifa);
1429
1430 lck_rw_lock_exclusive(in_ifaddr_rwlock);
1431 IFA_LOCK(&ia->ia_ifa);
1432 oldaddr = ia->ia_addr;
1433 if (IA_IS_HASHED(ia)) {
1434 oldremoved = 1;
1435 in_iahash_remove(ia);
1436 }
1437 ia->ia_addr = *sin;
1438 ia->ia_addr.sin_len = sizeof (*sin);
1439 if ((ifp->if_flags & IFF_POINTOPOINT))
1440 in_iahash_insert_ptp(ia);
1441 else
1442 in_iahash_insert(ia);
1443 IFA_UNLOCK(&ia->ia_ifa);
1444 lck_rw_done(in_ifaddr_rwlock);
1445
1446 /*
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.
1452 */
1453 ifa0 = ifa_ifpgetprimary(ifp, AF_INET);
1454 cmd = (&ia->ia_ifa == ifa0) ? SIOCSIFADDR : SIOCAIFADDR;
1455 error = ifnet_ioctl(ifp, PF_INET, cmd, ia);
1456 if (error == EOPNOTSUPP)
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() */
1472 IFA_REMREF(ifa0);
1473
1474 if (error) {
1475 lck_rw_lock_exclusive(in_ifaddr_rwlock);
1476 IFA_LOCK(&ia->ia_ifa);
1477 if (IA_IS_HASHED(ia))
1478 in_iahash_remove(ia);
1479 ia->ia_addr = oldaddr;
1480 if (oldremoved) {
1481 if ((ifp->if_flags & IFF_POINTOPOINT))
1482 in_iahash_insert_ptp(ia);
1483 else
1484 in_iahash_insert(ia);
1485 }
1486 IFA_UNLOCK(&ia->ia_ifa);
1487 lck_rw_done(in_ifaddr_rwlock);
1488 /* Release extra reference taken above */
1489 IFA_REMREF(&ia->ia_ifa);
1490 return (error);
1491 }
1492 lck_mtx_lock(rnh_lock);
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;
1499 if (scrub) {
1500 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
1501 IFA_UNLOCK(&ia->ia_ifa);
1502 in_ifscrub(ifp, ia, 1);
1503 IFA_LOCK(&ia->ia_ifa);
1504 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1505 }
1506 IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
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) {
1539 if (ia->ia_dstaddr.sin_family != AF_INET) {
1540 IFA_UNLOCK(&ia->ia_ifa);
1541 lck_mtx_unlock(rnh_lock);
1542 /* Release extra reference taken above */
1543 IFA_REMREF(&ia->ia_ifa);
1544 return (0);
1545 }
1546 ia->ia_dstaddr.sin_len = sizeof (*sin);
1547 flags |= RTF_HOST;
1548 }
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);
1552 ia->ia_flags |= IFA_ROUTE;
1553 IFA_UNLOCK(&ia->ia_ifa);
1554 }
1555 lck_mtx_unlock(rnh_lock);
1556
1557 /* XXX check if the subnet route points to the same interface */
1558 if (error == EEXIST)
1559 error = 0;
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
1568 lck_mtx_lock(&ifp->if_addrconfig_lock);
1569 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
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);
1585 }
1586
1587 /* Release extra reference taken above */
1588 IFA_REMREF(&ia->ia_ifa);
1589 return (error);
1590 }
1591
1592
1593 /*
1594 * Return 1 if the address might be a local broadcast address.
1595 */
1596 int
1597 in_broadcast(struct in_addr in, struct ifnet *ifp)
1598 {
1599 struct ifaddr *ifa;
1600 u_int32_t t;
1601
1602 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
1603 return (1);
1604 if ((ifp->if_flags & IFF_BROADCAST) == 0)
1605 return (0);
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)
1612 ifnet_lock_shared(ifp);
1613 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1614 IFA_LOCK(ifa);
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 */
1627 ia->ia_subnetmask != (u_int32_t)0xffffffff) {
1628 IFA_UNLOCK(ifa);
1629 ifnet_lock_done(ifp);
1630 return (1);
1631 }
1632 IFA_UNLOCK(ifa);
1633 }
1634 ifnet_lock_done(ifp);
1635 return (0);
1636 #undef ia
1637 }
1638
1639 void
1640 in_purgeaddrs(struct ifnet *ifp)
1641 {
1642 struct ifaddr **ifap;
1643 int err, i;
1644
1645 /*
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.
1650 */
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);
1695 }
1696 }
1697
1698 int inet_aton(char *cp, struct in_addr *pin);
1699 int
1700 inet_aton(char * cp, struct in_addr * pin)
1701 {
1702 u_char * b = (unsigned char *)pin;
1703 int i;
1704 char * p;
1705
1706 for (p = cp, i = 0; i < 4; i++) {
1707 u_int32_t l = strtoul(p, 0, 0);
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 }
1718
1719 int inet_ntoa2(struct in_addr * pin, char * cp, const int len);
1720 int 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 }
1731
1732 /*
1733 * Called as part of ip_init
1734 */
1735 void
1736 in_ifaddr_init(void)
1737 {
1738 in_multi_init();
1739
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);
1747 if (inifa_zone == NULL) {
1748 panic("%s: failed allocating %s", __func__, INIFA_ZONE_NAME);
1749 /* NOTREACHED */
1750 }
1751 zone_change(inifa_zone, Z_EXPAND, TRUE);
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);
1756 }
1757
1758 static struct in_ifaddr *
1759 in_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;
1769 ifa_lock_init(&inifa->ia_ifa);
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;
1775 inifa->ia_ifa.ifa_attached = in_ifaddr_attached;
1776 inifa->ia_ifa.ifa_detached = in_ifaddr_detached;
1777 ctrace_record(&inifa_dbg->inifa_alloc);
1778 }
1779 }
1780 return (inifa);
1781 }
1782
1783 static void
1784 in_ifaddr_free(struct ifaddr *ifa)
1785 {
1786 IFA_LOCK_ASSERT_HELD(ifa);
1787
1788 if (ifa->ifa_refcnt != 0) {
1789 panic("%s: ifa %p bad ref cnt", __func__, ifa);
1790 /* NOTREACHED */
1791 } if (!(ifa->ifa_debug & IFD_ALLOC)) {
1792 panic("%s: ifa %p cannot be freed", __func__, ifa);
1793 /* NOTREACHED */
1794 }
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));
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 }
1809 }
1810 IFA_UNLOCK(ifa);
1811 ifa_lock_destroy(ifa);
1812 bzero(ifa, sizeof (struct in_ifaddr));
1813 zfree(inifa_zone, ifa);
1814 }
1815
1816 static void
1817 in_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
1837 static void
1838 in_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
1859 static void
1860 in_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
1867 if (!(ifa->ifa_debug & IFD_DEBUG)) {
1868 panic("%s: ifa %p has no debug structure", __func__, ifa);
1869 /* NOTREACHED */
1870 }
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
1879 idx = atomic_add_16_ov(cnt, 1) % INIFA_TRACE_HIST_SIZE;
1880 ctrace_record(&tr[idx]);
1881 }