1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions * Copyright (c) 2000-2021 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions *
4*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions *
6*aca3beaaSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*aca3beaaSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*aca3beaaSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*aca3beaaSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*aca3beaaSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*aca3beaaSApple OSS Distributions *
15*aca3beaaSApple OSS Distributions * Please obtain a copy of the License at
16*aca3beaaSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*aca3beaaSApple OSS Distributions *
18*aca3beaaSApple OSS Distributions * The Original Code and all software distributed under the License are
19*aca3beaaSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*aca3beaaSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*aca3beaaSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*aca3beaaSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*aca3beaaSApple OSS Distributions * Please see the License for the specific language governing rights and
24*aca3beaaSApple OSS Distributions * limitations under the License.
25*aca3beaaSApple OSS Distributions *
26*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*aca3beaaSApple OSS Distributions */
28*aca3beaaSApple OSS Distributions /*
29*aca3beaaSApple OSS Distributions * Copyright (c) 1982, 1986, 1991, 1993
30*aca3beaaSApple OSS Distributions * The Regents of the University of California. All rights reserved.
31*aca3beaaSApple OSS Distributions *
32*aca3beaaSApple OSS Distributions * Redistribution and use in source and binary forms, with or without
33*aca3beaaSApple OSS Distributions * modification, are permitted provided that the following conditions
34*aca3beaaSApple OSS Distributions * are met:
35*aca3beaaSApple OSS Distributions * 1. Redistributions of source code must retain the above copyright
36*aca3beaaSApple OSS Distributions * notice, this list of conditions and the following disclaimer.
37*aca3beaaSApple OSS Distributions * 2. Redistributions in binary form must reproduce the above copyright
38*aca3beaaSApple OSS Distributions * notice, this list of conditions and the following disclaimer in the
39*aca3beaaSApple OSS Distributions * documentation and/or other materials provided with the distribution.
40*aca3beaaSApple OSS Distributions * 3. All advertising materials mentioning features or use of this software
41*aca3beaaSApple OSS Distributions * must display the following acknowledgement:
42*aca3beaaSApple OSS Distributions * This product includes software developed by the University of
43*aca3beaaSApple OSS Distributions * California, Berkeley and its contributors.
44*aca3beaaSApple OSS Distributions * 4. Neither the name of the University nor the names of its contributors
45*aca3beaaSApple OSS Distributions * may be used to endorse or promote products derived from this software
46*aca3beaaSApple OSS Distributions * without specific prior written permission.
47*aca3beaaSApple OSS Distributions *
48*aca3beaaSApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49*aca3beaaSApple OSS Distributions * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50*aca3beaaSApple OSS Distributions * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51*aca3beaaSApple OSS Distributions * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52*aca3beaaSApple OSS Distributions * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53*aca3beaaSApple OSS Distributions * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54*aca3beaaSApple OSS Distributions * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55*aca3beaaSApple OSS Distributions * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56*aca3beaaSApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57*aca3beaaSApple OSS Distributions * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58*aca3beaaSApple OSS Distributions * SUCH DAMAGE.
59*aca3beaaSApple OSS Distributions *
60*aca3beaaSApple OSS Distributions * @(#)in.c 8.4 (Berkeley) 1/9/95
61*aca3beaaSApple OSS Distributions */
62*aca3beaaSApple OSS Distributions
63*aca3beaaSApple OSS Distributions #include <sys/param.h>
64*aca3beaaSApple OSS Distributions #include <sys/systm.h>
65*aca3beaaSApple OSS Distributions #include <sys/sockio.h>
66*aca3beaaSApple OSS Distributions #include <sys/socketvar.h>
67*aca3beaaSApple OSS Distributions #include <sys/malloc.h>
68*aca3beaaSApple OSS Distributions #include <sys/proc.h>
69*aca3beaaSApple OSS Distributions #include <sys/socket.h>
70*aca3beaaSApple OSS Distributions #include <sys/kernel.h>
71*aca3beaaSApple OSS Distributions #include <sys/sysctl.h>
72*aca3beaaSApple OSS Distributions #include <sys/kern_event.h>
73*aca3beaaSApple OSS Distributions #include <sys/syslog.h>
74*aca3beaaSApple OSS Distributions #include <sys/mcache.h>
75*aca3beaaSApple OSS Distributions #include <sys/protosw.h>
76*aca3beaaSApple OSS Distributions #include <sys/file.h>
77*aca3beaaSApple OSS Distributions
78*aca3beaaSApple OSS Distributions #include <kern/zalloc.h>
79*aca3beaaSApple OSS Distributions #include <pexpert/pexpert.h>
80*aca3beaaSApple OSS Distributions #include <os/log.h>
81*aca3beaaSApple OSS Distributions
82*aca3beaaSApple OSS Distributions #include <net/if.h>
83*aca3beaaSApple OSS Distributions #include <net/if_types.h>
84*aca3beaaSApple OSS Distributions #include <net/route.h>
85*aca3beaaSApple OSS Distributions #include <net/kpi_protocol.h>
86*aca3beaaSApple OSS Distributions #include <net/dlil.h>
87*aca3beaaSApple OSS Distributions #include <net/if_llatbl.h>
88*aca3beaaSApple OSS Distributions #include <net/if_arp.h>
89*aca3beaaSApple OSS Distributions #if PF
90*aca3beaaSApple OSS Distributions #include <net/pfvar.h>
91*aca3beaaSApple OSS Distributions #endif /* PF */
92*aca3beaaSApple OSS Distributions
93*aca3beaaSApple OSS Distributions #include <netinet/in.h>
94*aca3beaaSApple OSS Distributions #include <netinet/in_var.h>
95*aca3beaaSApple OSS Distributions #include <netinet/in_pcb.h>
96*aca3beaaSApple OSS Distributions #include <netinet/igmp_var.h>
97*aca3beaaSApple OSS Distributions #include <netinet/ip_var.h>
98*aca3beaaSApple OSS Distributions #include <netinet/tcp.h>
99*aca3beaaSApple OSS Distributions #include <netinet/tcp_timer.h>
100*aca3beaaSApple OSS Distributions #include <netinet/tcp_var.h>
101*aca3beaaSApple OSS Distributions #include <netinet/if_ether.h>
102*aca3beaaSApple OSS Distributions
103*aca3beaaSApple OSS Distributions static int inctl_associd(struct socket *, u_long, caddr_t);
104*aca3beaaSApple OSS Distributions static int inctl_connid(struct socket *, u_long, caddr_t);
105*aca3beaaSApple OSS Distributions static int inctl_conninfo(struct socket *, u_long, caddr_t);
106*aca3beaaSApple OSS Distributions static int inctl_autoaddr(struct ifnet *, struct ifreq *);
107*aca3beaaSApple OSS Distributions static int inctl_arpipll(struct ifnet *, struct ifreq *);
108*aca3beaaSApple OSS Distributions static int inctl_setrouter(struct ifnet *, struct ifreq *);
109*aca3beaaSApple OSS Distributions static int inctl_ifaddr(struct ifnet *, struct in_ifaddr *, u_long,
110*aca3beaaSApple OSS Distributions struct ifreq *);
111*aca3beaaSApple OSS Distributions static int inctl_ifdstaddr(struct ifnet *, struct in_ifaddr *, u_long,
112*aca3beaaSApple OSS Distributions struct ifreq *);
113*aca3beaaSApple OSS Distributions static int inctl_ifbrdaddr(struct ifnet *, struct in_ifaddr *, u_long,
114*aca3beaaSApple OSS Distributions struct ifreq *);
115*aca3beaaSApple OSS Distributions static int inctl_ifnetmask(struct ifnet *, struct in_ifaddr *, u_long,
116*aca3beaaSApple OSS Distributions struct ifreq *);
117*aca3beaaSApple OSS Distributions
118*aca3beaaSApple OSS Distributions static void in_socktrim(struct sockaddr_in *);
119*aca3beaaSApple OSS Distributions static int in_ifinit(struct ifnet *, struct in_ifaddr *,
120*aca3beaaSApple OSS Distributions struct sockaddr_in *, int);
121*aca3beaaSApple OSS Distributions
122*aca3beaaSApple OSS Distributions #define IA_HASH_INIT(ia) { \
123*aca3beaaSApple OSS Distributions (ia)->ia_hash.tqe_next = (void *)(uintptr_t)-1; \
124*aca3beaaSApple OSS Distributions (ia)->ia_hash.tqe_prev = (void *)(uintptr_t)-1; \
125*aca3beaaSApple OSS Distributions }
126*aca3beaaSApple OSS Distributions
127*aca3beaaSApple OSS Distributions #define IA_IS_HASHED(ia) \
128*aca3beaaSApple OSS Distributions (!((ia)->ia_hash.tqe_next == (void *)(uintptr_t)-1 || \
129*aca3beaaSApple OSS Distributions (ia)->ia_hash.tqe_prev == (void *)(uintptr_t)-1))
130*aca3beaaSApple OSS Distributions
131*aca3beaaSApple OSS Distributions static void in_iahash_remove(struct in_ifaddr *);
132*aca3beaaSApple OSS Distributions static void in_iahash_insert(struct in_ifaddr *);
133*aca3beaaSApple OSS Distributions static void in_iahash_insert_ptp(struct in_ifaddr *);
134*aca3beaaSApple OSS Distributions static struct in_ifaddr *in_ifaddr_alloc(zalloc_flags_t);
135*aca3beaaSApple OSS Distributions static void in_ifaddr_attached(struct ifaddr *);
136*aca3beaaSApple OSS Distributions static void in_ifaddr_detached(struct ifaddr *);
137*aca3beaaSApple OSS Distributions static void in_ifaddr_free(struct ifaddr *);
138*aca3beaaSApple OSS Distributions static void in_ifaddr_trace(struct ifaddr *, int);
139*aca3beaaSApple OSS Distributions
140*aca3beaaSApple OSS Distributions static int in_getassocids(struct socket *, uint32_t *, user_addr_t);
141*aca3beaaSApple OSS Distributions static int in_getconnids(struct socket *, sae_associd_t, uint32_t *, user_addr_t);
142*aca3beaaSApple OSS Distributions
143*aca3beaaSApple OSS Distributions /* IPv4 Layer 2 neighbor cache management routines */
144*aca3beaaSApple OSS Distributions static void in_lltable_destroy_lle_unlocked(struct llentry *lle);
145*aca3beaaSApple OSS Distributions static void in_lltable_destroy_lle(struct llentry *lle);
146*aca3beaaSApple OSS Distributions static struct llentry *in_lltable_new(struct in_addr addr4, uint16_t flags);
147*aca3beaaSApple OSS Distributions static int in_lltable_match_prefix(const struct sockaddr *saddr,
148*aca3beaaSApple OSS Distributions const struct sockaddr *smask, uint16_t flags, struct llentry *lle);
149*aca3beaaSApple OSS Distributions static void in_lltable_free_entry(struct lltable *llt, struct llentry *lle);
150*aca3beaaSApple OSS Distributions static int in_lltable_rtcheck(struct ifnet *ifp, uint16_t flags, const struct sockaddr *l3addr);
151*aca3beaaSApple OSS Distributions static inline uint32_t in_lltable_hash_dst(const struct in_addr dst, uint32_t hsize);
152*aca3beaaSApple OSS Distributions static uint32_t in_lltable_hash(const struct llentry *lle, uint32_t hsize);
153*aca3beaaSApple OSS Distributions static void in_lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa);
154*aca3beaaSApple OSS Distributions static inline struct llentry * in_lltable_find_dst(struct lltable *llt, struct in_addr dst);
155*aca3beaaSApple OSS Distributions static void in_lltable_delete_entry(struct lltable *llt, struct llentry *lle);
156*aca3beaaSApple OSS Distributions static struct llentry * in_lltable_alloc(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr);
157*aca3beaaSApple OSS Distributions static struct llentry * in_lltable_lookup(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr);
158*aca3beaaSApple OSS Distributions static int in_lltable_dump_entry(struct lltable *llt, struct llentry *lle, struct sysctl_req *wr);
159*aca3beaaSApple OSS Distributions static struct lltable * in_lltattach(struct ifnet *ifp);
160*aca3beaaSApple OSS Distributions
161*aca3beaaSApple OSS Distributions static int subnetsarelocal = 0;
162*aca3beaaSApple OSS Distributions SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local,
163*aca3beaaSApple OSS Distributions CTLFLAG_RW | CTLFLAG_LOCKED, &subnetsarelocal, 0, "");
164*aca3beaaSApple OSS Distributions
165*aca3beaaSApple OSS Distributions /* Track whether or not the SIOCARPIPLL ioctl has been called */
166*aca3beaaSApple OSS Distributions u_int32_t ipv4_ll_arp_aware = 0;
167*aca3beaaSApple OSS Distributions
168*aca3beaaSApple OSS Distributions #define INIFA_TRACE_HIST_SIZE 32 /* size of trace history */
169*aca3beaaSApple OSS Distributions
170*aca3beaaSApple OSS Distributions /* For gdb */
171*aca3beaaSApple OSS Distributions __private_extern__ unsigned int inifa_trace_hist_size = INIFA_TRACE_HIST_SIZE;
172*aca3beaaSApple OSS Distributions
173*aca3beaaSApple OSS Distributions struct in_ifaddr_dbg {
174*aca3beaaSApple OSS Distributions struct in_ifaddr inifa; /* in_ifaddr */
175*aca3beaaSApple OSS Distributions struct in_ifaddr inifa_old; /* saved in_ifaddr */
176*aca3beaaSApple OSS Distributions u_int16_t inifa_refhold_cnt; /* # of IFA_ADDREF */
177*aca3beaaSApple OSS Distributions u_int16_t inifa_refrele_cnt; /* # of IFA_REMREF */
178*aca3beaaSApple OSS Distributions /*
179*aca3beaaSApple OSS Distributions * Alloc and free callers.
180*aca3beaaSApple OSS Distributions */
181*aca3beaaSApple OSS Distributions ctrace_t inifa_alloc;
182*aca3beaaSApple OSS Distributions ctrace_t inifa_free;
183*aca3beaaSApple OSS Distributions /*
184*aca3beaaSApple OSS Distributions * Circular lists of IFA_ADDREF and IFA_REMREF callers.
185*aca3beaaSApple OSS Distributions */
186*aca3beaaSApple OSS Distributions ctrace_t inifa_refhold[INIFA_TRACE_HIST_SIZE];
187*aca3beaaSApple OSS Distributions ctrace_t inifa_refrele[INIFA_TRACE_HIST_SIZE];
188*aca3beaaSApple OSS Distributions /*
189*aca3beaaSApple OSS Distributions * Trash list linkage
190*aca3beaaSApple OSS Distributions */
191*aca3beaaSApple OSS Distributions TAILQ_ENTRY(in_ifaddr_dbg) inifa_trash_link;
192*aca3beaaSApple OSS Distributions };
193*aca3beaaSApple OSS Distributions
194*aca3beaaSApple OSS Distributions /* List of trash in_ifaddr entries protected by inifa_trash_lock */
195*aca3beaaSApple OSS Distributions static TAILQ_HEAD(, in_ifaddr_dbg) inifa_trash_head;
196*aca3beaaSApple OSS Distributions static LCK_MTX_DECLARE_ATTR(inifa_trash_lock, &ifa_mtx_grp, &ifa_mtx_attr);
197*aca3beaaSApple OSS Distributions
198*aca3beaaSApple OSS Distributions #if DEBUG
199*aca3beaaSApple OSS Distributions static TUNABLE(bool, inifa_debug, "ifa_debug", true); /* debugging (enabled) */
200*aca3beaaSApple OSS Distributions #else
201*aca3beaaSApple OSS Distributions static TUNABLE(bool, inifa_debug, "ifa_debug", false); /* debugging (disabled) */
202*aca3beaaSApple OSS Distributions #endif /* !DEBUG */
203*aca3beaaSApple OSS Distributions static struct zone *inifa_zone; /* zone for in_ifaddr */
204*aca3beaaSApple OSS Distributions
205*aca3beaaSApple OSS Distributions #define INIFA_ZONE_NAME "in_ifaddr" /* zone name */
206*aca3beaaSApple OSS Distributions
207*aca3beaaSApple OSS Distributions /*
208*aca3beaaSApple OSS Distributions * Return 1 if the address is
209*aca3beaaSApple OSS Distributions * - loopback
210*aca3beaaSApple OSS Distributions * - unicast or multicast link local
211*aca3beaaSApple OSS Distributions * - routed via a link level gateway
212*aca3beaaSApple OSS Distributions * - belongs to a directly connected (sub)net
213*aca3beaaSApple OSS Distributions */
214*aca3beaaSApple OSS Distributions int
inaddr_local(struct in_addr in)215*aca3beaaSApple OSS Distributions inaddr_local(struct in_addr in)
216*aca3beaaSApple OSS Distributions {
217*aca3beaaSApple OSS Distributions struct rtentry *rt;
218*aca3beaaSApple OSS Distributions struct sockaddr_in sin;
219*aca3beaaSApple OSS Distributions int local = 0;
220*aca3beaaSApple OSS Distributions
221*aca3beaaSApple OSS Distributions if (ntohl(in.s_addr) == INADDR_LOOPBACK ||
222*aca3beaaSApple OSS Distributions IN_LINKLOCAL(ntohl(in.s_addr))) {
223*aca3beaaSApple OSS Distributions local = 1;
224*aca3beaaSApple OSS Distributions } else if (ntohl(in.s_addr) >= INADDR_UNSPEC_GROUP &&
225*aca3beaaSApple OSS Distributions ntohl(in.s_addr) <= INADDR_MAX_LOCAL_GROUP) {
226*aca3beaaSApple OSS Distributions local = 1;
227*aca3beaaSApple OSS Distributions } else {
228*aca3beaaSApple OSS Distributions sin.sin_family = AF_INET;
229*aca3beaaSApple OSS Distributions sin.sin_len = sizeof(sin);
230*aca3beaaSApple OSS Distributions sin.sin_addr = in;
231*aca3beaaSApple OSS Distributions rt = rtalloc1((struct sockaddr *)&sin, 0, 0);
232*aca3beaaSApple OSS Distributions
233*aca3beaaSApple OSS Distributions if (rt != NULL) {
234*aca3beaaSApple OSS Distributions RT_LOCK_SPIN(rt);
235*aca3beaaSApple OSS Distributions if (rt->rt_gateway->sa_family == AF_LINK ||
236*aca3beaaSApple OSS Distributions (rt->rt_ifp->if_flags & IFF_LOOPBACK)) {
237*aca3beaaSApple OSS Distributions local = 1;
238*aca3beaaSApple OSS Distributions }
239*aca3beaaSApple OSS Distributions RT_UNLOCK(rt);
240*aca3beaaSApple OSS Distributions rtfree(rt);
241*aca3beaaSApple OSS Distributions } else {
242*aca3beaaSApple OSS Distributions local = in_localaddr(in);
243*aca3beaaSApple OSS Distributions }
244*aca3beaaSApple OSS Distributions }
245*aca3beaaSApple OSS Distributions return local;
246*aca3beaaSApple OSS Distributions }
247*aca3beaaSApple OSS Distributions
248*aca3beaaSApple OSS Distributions /*
249*aca3beaaSApple OSS Distributions * Return 1 if an internet address is for a ``local'' host
250*aca3beaaSApple OSS Distributions * (one to which we have a connection). If subnetsarelocal
251*aca3beaaSApple OSS Distributions * is true, this includes other subnets of the local net,
252*aca3beaaSApple OSS Distributions * otherwise, it includes the directly-connected (sub)nets.
253*aca3beaaSApple OSS Distributions * The IPv4 link local prefix 169.254/16 is also included.
254*aca3beaaSApple OSS Distributions */
255*aca3beaaSApple OSS Distributions int
in_localaddr(struct in_addr in)256*aca3beaaSApple OSS Distributions in_localaddr(struct in_addr in)
257*aca3beaaSApple OSS Distributions {
258*aca3beaaSApple OSS Distributions u_int32_t i = ntohl(in.s_addr);
259*aca3beaaSApple OSS Distributions struct in_ifaddr *ia;
260*aca3beaaSApple OSS Distributions
261*aca3beaaSApple OSS Distributions if (IN_LINKLOCAL(i)) {
262*aca3beaaSApple OSS Distributions return 1;
263*aca3beaaSApple OSS Distributions }
264*aca3beaaSApple OSS Distributions
265*aca3beaaSApple OSS Distributions if (subnetsarelocal) {
266*aca3beaaSApple OSS Distributions lck_rw_lock_shared(&in_ifaddr_rwlock);
267*aca3beaaSApple OSS Distributions for (ia = in_ifaddrhead.tqh_first; ia != NULL;
268*aca3beaaSApple OSS Distributions ia = ia->ia_link.tqe_next) {
269*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
270*aca3beaaSApple OSS Distributions if ((i & ia->ia_netmask) == ia->ia_net) {
271*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
272*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
273*aca3beaaSApple OSS Distributions return 1;
274*aca3beaaSApple OSS Distributions }
275*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
276*aca3beaaSApple OSS Distributions }
277*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
278*aca3beaaSApple OSS Distributions } else {
279*aca3beaaSApple OSS Distributions lck_rw_lock_shared(&in_ifaddr_rwlock);
280*aca3beaaSApple OSS Distributions for (ia = in_ifaddrhead.tqh_first; ia != NULL;
281*aca3beaaSApple OSS Distributions ia = ia->ia_link.tqe_next) {
282*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
283*aca3beaaSApple OSS Distributions if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
284*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
285*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
286*aca3beaaSApple OSS Distributions return 1;
287*aca3beaaSApple OSS Distributions }
288*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
289*aca3beaaSApple OSS Distributions }
290*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
291*aca3beaaSApple OSS Distributions }
292*aca3beaaSApple OSS Distributions return 0;
293*aca3beaaSApple OSS Distributions }
294*aca3beaaSApple OSS Distributions
295*aca3beaaSApple OSS Distributions /*
296*aca3beaaSApple OSS Distributions * Determine whether an IP address is in a reserved set of addresses
297*aca3beaaSApple OSS Distributions * that may not be forwarded, or whether datagrams to that destination
298*aca3beaaSApple OSS Distributions * may be forwarded.
299*aca3beaaSApple OSS Distributions */
300*aca3beaaSApple OSS Distributions boolean_t
in_canforward(struct in_addr in)301*aca3beaaSApple OSS Distributions in_canforward(struct in_addr in)
302*aca3beaaSApple OSS Distributions {
303*aca3beaaSApple OSS Distributions u_int32_t i = ntohl(in.s_addr);
304*aca3beaaSApple OSS Distributions u_int32_t net;
305*aca3beaaSApple OSS Distributions
306*aca3beaaSApple OSS Distributions if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i)) {
307*aca3beaaSApple OSS Distributions return FALSE;
308*aca3beaaSApple OSS Distributions }
309*aca3beaaSApple OSS Distributions if (IN_CLASSA(i)) {
310*aca3beaaSApple OSS Distributions net = i & IN_CLASSA_NET;
311*aca3beaaSApple OSS Distributions if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) {
312*aca3beaaSApple OSS Distributions return FALSE;
313*aca3beaaSApple OSS Distributions }
314*aca3beaaSApple OSS Distributions }
315*aca3beaaSApple OSS Distributions return TRUE;
316*aca3beaaSApple OSS Distributions }
317*aca3beaaSApple OSS Distributions
318*aca3beaaSApple OSS Distributions /*
319*aca3beaaSApple OSS Distributions * Trim a mask in a sockaddr
320*aca3beaaSApple OSS Distributions */
321*aca3beaaSApple OSS Distributions static void
in_socktrim(struct sockaddr_in * ap)322*aca3beaaSApple OSS Distributions in_socktrim(struct sockaddr_in *ap)
323*aca3beaaSApple OSS Distributions {
324*aca3beaaSApple OSS Distributions char *cplim = (char *)&ap->sin_addr;
325*aca3beaaSApple OSS Distributions char *cp = (char *)(&ap->sin_addr + 1);
326*aca3beaaSApple OSS Distributions
327*aca3beaaSApple OSS Distributions ap->sin_len = 0;
328*aca3beaaSApple OSS Distributions while (--cp >= cplim) {
329*aca3beaaSApple OSS Distributions if (*cp) {
330*aca3beaaSApple OSS Distributions (ap)->sin_len = (uint8_t)(cp - (char *)(ap) + 1);
331*aca3beaaSApple OSS Distributions break;
332*aca3beaaSApple OSS Distributions }
333*aca3beaaSApple OSS Distributions }
334*aca3beaaSApple OSS Distributions }
335*aca3beaaSApple OSS Distributions
336*aca3beaaSApple OSS Distributions static int in_interfaces; /* number of external internet interfaces */
337*aca3beaaSApple OSS Distributions
338*aca3beaaSApple OSS Distributions static int
in_domifattach(struct ifnet * ifp)339*aca3beaaSApple OSS Distributions in_domifattach(struct ifnet *ifp)
340*aca3beaaSApple OSS Distributions {
341*aca3beaaSApple OSS Distributions int error = 0;
342*aca3beaaSApple OSS Distributions
343*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
344*aca3beaaSApple OSS Distributions
345*aca3beaaSApple OSS Distributions if ((error = proto_plumb(PF_INET, ifp)) && error != EEXIST) {
346*aca3beaaSApple OSS Distributions log(LOG_ERR, "%s: proto_plumb returned %d if=%s\n",
347*aca3beaaSApple OSS Distributions __func__, error, if_name(ifp));
348*aca3beaaSApple OSS Distributions return error;
349*aca3beaaSApple OSS Distributions }
350*aca3beaaSApple OSS Distributions
351*aca3beaaSApple OSS Distributions if (ifp->if_inetdata == NULL) {
352*aca3beaaSApple OSS Distributions ifp->if_inetdata = zalloc_permanent_type(struct in_ifextra);
353*aca3beaaSApple OSS Distributions IN_IFEXTRA(ifp)->ii_llt = in_lltattach(ifp);
354*aca3beaaSApple OSS Distributions error = 0;
355*aca3beaaSApple OSS Distributions } else if (error != EEXIST) {
356*aca3beaaSApple OSS Distributions /*
357*aca3beaaSApple OSS Distributions * Since the structure is never freed, we need to
358*aca3beaaSApple OSS Distributions * zero out its contents to avoid reusing stale data.
359*aca3beaaSApple OSS Distributions * A little redundant with allocation above, but it
360*aca3beaaSApple OSS Distributions * keeps the code simpler for all cases.
361*aca3beaaSApple OSS Distributions */
362*aca3beaaSApple OSS Distributions IN_IFEXTRA(ifp)->netsig_len = 0;
363*aca3beaaSApple OSS Distributions bzero(IN_IFEXTRA(ifp)->netsig, sizeof(IN_IFEXTRA(ifp)->netsig));
364*aca3beaaSApple OSS Distributions if (LLTABLE(ifp)) {
365*aca3beaaSApple OSS Distributions lltable_purge(LLTABLE(ifp));
366*aca3beaaSApple OSS Distributions }
367*aca3beaaSApple OSS Distributions }
368*aca3beaaSApple OSS Distributions return error;
369*aca3beaaSApple OSS Distributions }
370*aca3beaaSApple OSS Distributions
371*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_associd(struct socket * so,u_long cmd,caddr_t data)372*aca3beaaSApple OSS Distributions inctl_associd(struct socket *so, u_long cmd, caddr_t data)
373*aca3beaaSApple OSS Distributions {
374*aca3beaaSApple OSS Distributions int error = 0;
375*aca3beaaSApple OSS Distributions union {
376*aca3beaaSApple OSS Distributions struct so_aidreq32 a32;
377*aca3beaaSApple OSS Distributions struct so_aidreq64 a64;
378*aca3beaaSApple OSS Distributions } u;
379*aca3beaaSApple OSS Distributions
380*aca3beaaSApple OSS Distributions VERIFY(so != NULL);
381*aca3beaaSApple OSS Distributions
382*aca3beaaSApple OSS Distributions switch (cmd) {
383*aca3beaaSApple OSS Distributions case SIOCGASSOCIDS32: /* struct so_aidreq32 */
384*aca3beaaSApple OSS Distributions bcopy(data, &u.a32, sizeof(u.a32));
385*aca3beaaSApple OSS Distributions error = in_getassocids(so, &u.a32.sar_cnt, u.a32.sar_aidp);
386*aca3beaaSApple OSS Distributions if (error == 0) {
387*aca3beaaSApple OSS Distributions bcopy(&u.a32, data, sizeof(u.a32));
388*aca3beaaSApple OSS Distributions }
389*aca3beaaSApple OSS Distributions break;
390*aca3beaaSApple OSS Distributions
391*aca3beaaSApple OSS Distributions case SIOCGASSOCIDS64: /* struct so_aidreq64 */
392*aca3beaaSApple OSS Distributions bcopy(data, &u.a64, sizeof(u.a64));
393*aca3beaaSApple OSS Distributions error = in_getassocids(so, &u.a64.sar_cnt, (user_addr_t)u.a64.sar_aidp);
394*aca3beaaSApple OSS Distributions if (error == 0) {
395*aca3beaaSApple OSS Distributions bcopy(&u.a64, data, sizeof(u.a64));
396*aca3beaaSApple OSS Distributions }
397*aca3beaaSApple OSS Distributions break;
398*aca3beaaSApple OSS Distributions
399*aca3beaaSApple OSS Distributions default:
400*aca3beaaSApple OSS Distributions VERIFY(0);
401*aca3beaaSApple OSS Distributions /* NOTREACHED */
402*aca3beaaSApple OSS Distributions }
403*aca3beaaSApple OSS Distributions
404*aca3beaaSApple OSS Distributions return error;
405*aca3beaaSApple OSS Distributions }
406*aca3beaaSApple OSS Distributions
407*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_connid(struct socket * so,u_long cmd,caddr_t data)408*aca3beaaSApple OSS Distributions inctl_connid(struct socket *so, u_long cmd, caddr_t data)
409*aca3beaaSApple OSS Distributions {
410*aca3beaaSApple OSS Distributions int error = 0;
411*aca3beaaSApple OSS Distributions union {
412*aca3beaaSApple OSS Distributions struct so_cidreq32 c32;
413*aca3beaaSApple OSS Distributions struct so_cidreq64 c64;
414*aca3beaaSApple OSS Distributions } u;
415*aca3beaaSApple OSS Distributions
416*aca3beaaSApple OSS Distributions VERIFY(so != NULL);
417*aca3beaaSApple OSS Distributions
418*aca3beaaSApple OSS Distributions switch (cmd) {
419*aca3beaaSApple OSS Distributions case SIOCGCONNIDS32: /* struct so_cidreq32 */
420*aca3beaaSApple OSS Distributions bcopy(data, &u.c32, sizeof(u.c32));
421*aca3beaaSApple OSS Distributions error = in_getconnids(so, u.c32.scr_aid, &u.c32.scr_cnt,
422*aca3beaaSApple OSS Distributions u.c32.scr_cidp);
423*aca3beaaSApple OSS Distributions if (error == 0) {
424*aca3beaaSApple OSS Distributions bcopy(&u.c32, data, sizeof(u.c32));
425*aca3beaaSApple OSS Distributions }
426*aca3beaaSApple OSS Distributions break;
427*aca3beaaSApple OSS Distributions
428*aca3beaaSApple OSS Distributions case SIOCGCONNIDS64: /* struct so_cidreq64 */
429*aca3beaaSApple OSS Distributions bcopy(data, &u.c64, sizeof(u.c64));
430*aca3beaaSApple OSS Distributions error = in_getconnids(so, u.c64.scr_aid, &u.c64.scr_cnt,
431*aca3beaaSApple OSS Distributions (user_addr_t)u.c64.scr_cidp);
432*aca3beaaSApple OSS Distributions if (error == 0) {
433*aca3beaaSApple OSS Distributions bcopy(&u.c64, data, sizeof(u.c64));
434*aca3beaaSApple OSS Distributions }
435*aca3beaaSApple OSS Distributions break;
436*aca3beaaSApple OSS Distributions
437*aca3beaaSApple OSS Distributions default:
438*aca3beaaSApple OSS Distributions VERIFY(0);
439*aca3beaaSApple OSS Distributions /* NOTREACHED */
440*aca3beaaSApple OSS Distributions }
441*aca3beaaSApple OSS Distributions
442*aca3beaaSApple OSS Distributions return error;
443*aca3beaaSApple OSS Distributions }
444*aca3beaaSApple OSS Distributions
445*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_conninfo(struct socket * so,u_long cmd,caddr_t data)446*aca3beaaSApple OSS Distributions inctl_conninfo(struct socket *so, u_long cmd, caddr_t data)
447*aca3beaaSApple OSS Distributions {
448*aca3beaaSApple OSS Distributions int error = 0;
449*aca3beaaSApple OSS Distributions union {
450*aca3beaaSApple OSS Distributions struct so_cinforeq32 ci32;
451*aca3beaaSApple OSS Distributions struct so_cinforeq64 ci64;
452*aca3beaaSApple OSS Distributions } u;
453*aca3beaaSApple OSS Distributions
454*aca3beaaSApple OSS Distributions VERIFY(so != NULL);
455*aca3beaaSApple OSS Distributions
456*aca3beaaSApple OSS Distributions switch (cmd) {
457*aca3beaaSApple OSS Distributions case SIOCGCONNINFO32: /* struct so_cinforeq32 */
458*aca3beaaSApple OSS Distributions bcopy(data, &u.ci32, sizeof(u.ci32));
459*aca3beaaSApple OSS Distributions error = in_getconninfo(so, u.ci32.scir_cid, &u.ci32.scir_flags,
460*aca3beaaSApple OSS Distributions &u.ci32.scir_ifindex, &u.ci32.scir_error, u.ci32.scir_src,
461*aca3beaaSApple OSS Distributions &u.ci32.scir_src_len, u.ci32.scir_dst, &u.ci32.scir_dst_len,
462*aca3beaaSApple OSS Distributions &u.ci32.scir_aux_type, u.ci32.scir_aux_data,
463*aca3beaaSApple OSS Distributions &u.ci32.scir_aux_len);
464*aca3beaaSApple OSS Distributions if (error == 0) {
465*aca3beaaSApple OSS Distributions bcopy(&u.ci32, data, sizeof(u.ci32));
466*aca3beaaSApple OSS Distributions }
467*aca3beaaSApple OSS Distributions break;
468*aca3beaaSApple OSS Distributions
469*aca3beaaSApple OSS Distributions case SIOCGCONNINFO64: /* struct so_cinforeq64 */
470*aca3beaaSApple OSS Distributions bcopy(data, &u.ci64, sizeof(u.ci64));
471*aca3beaaSApple OSS Distributions error = in_getconninfo(so, u.ci64.scir_cid, &u.ci64.scir_flags,
472*aca3beaaSApple OSS Distributions &u.ci64.scir_ifindex, &u.ci64.scir_error, (user_addr_t)u.ci64.scir_src,
473*aca3beaaSApple OSS Distributions &u.ci64.scir_src_len, (user_addr_t)u.ci64.scir_dst, &u.ci64.scir_dst_len,
474*aca3beaaSApple OSS Distributions &u.ci64.scir_aux_type, (user_addr_t)u.ci64.scir_aux_data,
475*aca3beaaSApple OSS Distributions &u.ci64.scir_aux_len);
476*aca3beaaSApple OSS Distributions if (error == 0) {
477*aca3beaaSApple OSS Distributions bcopy(&u.ci64, data, sizeof(u.ci64));
478*aca3beaaSApple OSS Distributions }
479*aca3beaaSApple OSS Distributions break;
480*aca3beaaSApple OSS Distributions
481*aca3beaaSApple OSS Distributions default:
482*aca3beaaSApple OSS Distributions VERIFY(0);
483*aca3beaaSApple OSS Distributions /* NOTREACHED */
484*aca3beaaSApple OSS Distributions }
485*aca3beaaSApple OSS Distributions
486*aca3beaaSApple OSS Distributions return error;
487*aca3beaaSApple OSS Distributions }
488*aca3beaaSApple OSS Distributions
489*aca3beaaSApple OSS Distributions /*
490*aca3beaaSApple OSS Distributions * Caller passes in the ioctl data pointer directly via "ifr", with the
491*aca3beaaSApple OSS Distributions * expectation that this routine always uses bcopy() or other byte-aligned
492*aca3beaaSApple OSS Distributions * memory accesses.
493*aca3beaaSApple OSS Distributions */
494*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_autoaddr(struct ifnet * ifp,struct ifreq * ifr)495*aca3beaaSApple OSS Distributions inctl_autoaddr(struct ifnet *ifp, struct ifreq *ifr)
496*aca3beaaSApple OSS Distributions {
497*aca3beaaSApple OSS Distributions int error = 0, intval;
498*aca3beaaSApple OSS Distributions
499*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
500*aca3beaaSApple OSS Distributions
501*aca3beaaSApple OSS Distributions bcopy(&ifr->ifr_intval, &intval, sizeof(intval));
502*aca3beaaSApple OSS Distributions
503*aca3beaaSApple OSS Distributions ifnet_lock_exclusive(ifp);
504*aca3beaaSApple OSS Distributions if (intval) {
505*aca3beaaSApple OSS Distributions /*
506*aca3beaaSApple OSS Distributions * An interface in IPv4 router mode implies that it
507*aca3beaaSApple OSS Distributions * is configured with a static IP address and should
508*aca3beaaSApple OSS Distributions * not act as a DHCP client; prevent SIOCAUTOADDR from
509*aca3beaaSApple OSS Distributions * being set in that mode.
510*aca3beaaSApple OSS Distributions */
511*aca3beaaSApple OSS Distributions if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
512*aca3beaaSApple OSS Distributions intval = 0; /* be safe; clear flag if set */
513*aca3beaaSApple OSS Distributions error = EBUSY;
514*aca3beaaSApple OSS Distributions } else {
515*aca3beaaSApple OSS Distributions if_set_eflags(ifp, IFEF_AUTOCONFIGURING);
516*aca3beaaSApple OSS Distributions }
517*aca3beaaSApple OSS Distributions }
518*aca3beaaSApple OSS Distributions if (!intval) {
519*aca3beaaSApple OSS Distributions if_clear_eflags(ifp, IFEF_AUTOCONFIGURING);
520*aca3beaaSApple OSS Distributions }
521*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
522*aca3beaaSApple OSS Distributions
523*aca3beaaSApple OSS Distributions return error;
524*aca3beaaSApple OSS Distributions }
525*aca3beaaSApple OSS Distributions
526*aca3beaaSApple OSS Distributions /*
527*aca3beaaSApple OSS Distributions * Caller passes in the ioctl data pointer directly via "ifr", with the
528*aca3beaaSApple OSS Distributions * expectation that this routine always uses bcopy() or other byte-aligned
529*aca3beaaSApple OSS Distributions * memory accesses.
530*aca3beaaSApple OSS Distributions */
531*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_arpipll(struct ifnet * ifp,struct ifreq * ifr)532*aca3beaaSApple OSS Distributions inctl_arpipll(struct ifnet *ifp, struct ifreq *ifr)
533*aca3beaaSApple OSS Distributions {
534*aca3beaaSApple OSS Distributions int error = 0, intval;
535*aca3beaaSApple OSS Distributions
536*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
537*aca3beaaSApple OSS Distributions
538*aca3beaaSApple OSS Distributions bcopy(&ifr->ifr_intval, &intval, sizeof(intval));
539*aca3beaaSApple OSS Distributions ipv4_ll_arp_aware = 1;
540*aca3beaaSApple OSS Distributions
541*aca3beaaSApple OSS Distributions ifnet_lock_exclusive(ifp);
542*aca3beaaSApple OSS Distributions if (intval) {
543*aca3beaaSApple OSS Distributions /*
544*aca3beaaSApple OSS Distributions * An interface in IPv4 router mode implies that it
545*aca3beaaSApple OSS Distributions * is configured with a static IP address and should
546*aca3beaaSApple OSS Distributions * not have to deal with IPv4 Link-Local Address;
547*aca3beaaSApple OSS Distributions * prevent SIOCARPIPLL from being set in that mode.
548*aca3beaaSApple OSS Distributions */
549*aca3beaaSApple OSS Distributions if (ifp->if_eflags & IFEF_IPV4_ROUTER) {
550*aca3beaaSApple OSS Distributions intval = 0; /* be safe; clear flag if set */
551*aca3beaaSApple OSS Distributions error = EBUSY;
552*aca3beaaSApple OSS Distributions } else {
553*aca3beaaSApple OSS Distributions if_set_eflags(ifp, IFEF_ARPLL);
554*aca3beaaSApple OSS Distributions }
555*aca3beaaSApple OSS Distributions }
556*aca3beaaSApple OSS Distributions if (!intval) {
557*aca3beaaSApple OSS Distributions if_clear_eflags(ifp, IFEF_ARPLL);
558*aca3beaaSApple OSS Distributions }
559*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
560*aca3beaaSApple OSS Distributions
561*aca3beaaSApple OSS Distributions return error;
562*aca3beaaSApple OSS Distributions }
563*aca3beaaSApple OSS Distributions
564*aca3beaaSApple OSS Distributions /*
565*aca3beaaSApple OSS Distributions * Handle SIOCSETROUTERMODE to set or clear the IPv4 router mode flag on
566*aca3beaaSApple OSS Distributions * the interface. When in this mode, IPv4 Link-Local Address support is
567*aca3beaaSApple OSS Distributions * disabled in ARP, and DHCP client support is disabled in IP input; turning
568*aca3beaaSApple OSS Distributions * any of them on would cause an error to be returned. Entering or exiting
569*aca3beaaSApple OSS Distributions * this mode will result in the removal of IPv4 addresses currently configured
570*aca3beaaSApple OSS Distributions * on the interface.
571*aca3beaaSApple OSS Distributions *
572*aca3beaaSApple OSS Distributions * Caller passes in the ioctl data pointer directly via "ifr", with the
573*aca3beaaSApple OSS Distributions * expectation that this routine always uses bcopy() or other byte-aligned
574*aca3beaaSApple OSS Distributions * memory accesses.
575*aca3beaaSApple OSS Distributions */
576*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_setrouter(struct ifnet * ifp,struct ifreq * ifr)577*aca3beaaSApple OSS Distributions inctl_setrouter(struct ifnet *ifp, struct ifreq *ifr)
578*aca3beaaSApple OSS Distributions {
579*aca3beaaSApple OSS Distributions int error = 0, intval;
580*aca3beaaSApple OSS Distributions
581*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
582*aca3beaaSApple OSS Distributions
583*aca3beaaSApple OSS Distributions /* Router mode isn't valid for loopback */
584*aca3beaaSApple OSS Distributions if (ifp->if_flags & IFF_LOOPBACK) {
585*aca3beaaSApple OSS Distributions return ENODEV;
586*aca3beaaSApple OSS Distributions }
587*aca3beaaSApple OSS Distributions
588*aca3beaaSApple OSS Distributions bcopy(&ifr->ifr_intval, &intval, sizeof(intval));
589*aca3beaaSApple OSS Distributions switch (intval) {
590*aca3beaaSApple OSS Distributions case 0:
591*aca3beaaSApple OSS Distributions case 1:
592*aca3beaaSApple OSS Distributions break;
593*aca3beaaSApple OSS Distributions default:
594*aca3beaaSApple OSS Distributions return EINVAL;
595*aca3beaaSApple OSS Distributions }
596*aca3beaaSApple OSS Distributions ifnet_lock_exclusive(ifp);
597*aca3beaaSApple OSS Distributions if (intval != 0) {
598*aca3beaaSApple OSS Distributions if_set_eflags(ifp, IFEF_IPV4_ROUTER);
599*aca3beaaSApple OSS Distributions if_clear_eflags(ifp, (IFEF_ARPLL | IFEF_AUTOCONFIGURING));
600*aca3beaaSApple OSS Distributions } else {
601*aca3beaaSApple OSS Distributions if_clear_eflags(ifp, IFEF_IPV4_ROUTER);
602*aca3beaaSApple OSS Distributions }
603*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
604*aca3beaaSApple OSS Distributions
605*aca3beaaSApple OSS Distributions /* purge all IPv4 addresses configured on this interface */
606*aca3beaaSApple OSS Distributions in_purgeaddrs(ifp);
607*aca3beaaSApple OSS Distributions
608*aca3beaaSApple OSS Distributions return error;
609*aca3beaaSApple OSS Distributions }
610*aca3beaaSApple OSS Distributions
611*aca3beaaSApple OSS Distributions /*
612*aca3beaaSApple OSS Distributions * Caller passes in the ioctl data pointer directly via "ifr", with the
613*aca3beaaSApple OSS Distributions * expectation that this routine always uses bcopy() or other byte-aligned
614*aca3beaaSApple OSS Distributions * memory accesses.
615*aca3beaaSApple OSS Distributions */
616*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_ifaddr(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)617*aca3beaaSApple OSS Distributions inctl_ifaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
618*aca3beaaSApple OSS Distributions struct ifreq *ifr)
619*aca3beaaSApple OSS Distributions {
620*aca3beaaSApple OSS Distributions struct kev_in_data in_event_data;
621*aca3beaaSApple OSS Distributions struct kev_msg ev_msg;
622*aca3beaaSApple OSS Distributions struct sockaddr_in addr;
623*aca3beaaSApple OSS Distributions struct ifaddr *ifa;
624*aca3beaaSApple OSS Distributions int error = 0;
625*aca3beaaSApple OSS Distributions
626*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
627*aca3beaaSApple OSS Distributions
628*aca3beaaSApple OSS Distributions bzero(&in_event_data, sizeof(struct kev_in_data));
629*aca3beaaSApple OSS Distributions bzero(&ev_msg, sizeof(struct kev_msg));
630*aca3beaaSApple OSS Distributions
631*aca3beaaSApple OSS Distributions switch (cmd) {
632*aca3beaaSApple OSS Distributions case SIOCGIFADDR: /* struct ifreq */
633*aca3beaaSApple OSS Distributions if (ia == NULL) {
634*aca3beaaSApple OSS Distributions error = EADDRNOTAVAIL;
635*aca3beaaSApple OSS Distributions break;
636*aca3beaaSApple OSS Distributions }
637*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
638*aca3beaaSApple OSS Distributions bcopy(&ia->ia_addr, &ifr->ifr_addr, sizeof(addr));
639*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
640*aca3beaaSApple OSS Distributions break;
641*aca3beaaSApple OSS Distributions
642*aca3beaaSApple OSS Distributions case SIOCSIFADDR: /* struct ifreq */
643*aca3beaaSApple OSS Distributions VERIFY(ia != NULL);
644*aca3beaaSApple OSS Distributions bcopy(&ifr->ifr_addr, &addr, sizeof(addr));
645*aca3beaaSApple OSS Distributions /*
646*aca3beaaSApple OSS Distributions * If this is a new address, the reference count for the
647*aca3beaaSApple OSS Distributions * hash table has been taken at creation time above.
648*aca3beaaSApple OSS Distributions */
649*aca3beaaSApple OSS Distributions error = in_ifinit(ifp, ia, &addr, 1);
650*aca3beaaSApple OSS Distributions if (error == 0) {
651*aca3beaaSApple OSS Distributions (void) ifnet_notify_address(ifp, AF_INET);
652*aca3beaaSApple OSS Distributions }
653*aca3beaaSApple OSS Distributions break;
654*aca3beaaSApple OSS Distributions
655*aca3beaaSApple OSS Distributions case SIOCAIFADDR: { /* struct {if,in_}aliasreq */
656*aca3beaaSApple OSS Distributions struct in_aliasreq *ifra = (struct in_aliasreq *)ifr;
657*aca3beaaSApple OSS Distributions struct sockaddr_in broadaddr, mask;
658*aca3beaaSApple OSS Distributions int hostIsNew, maskIsNew;
659*aca3beaaSApple OSS Distributions
660*aca3beaaSApple OSS Distributions VERIFY(ia != NULL);
661*aca3beaaSApple OSS Distributions bcopy(&ifra->ifra_addr, &addr, sizeof(addr));
662*aca3beaaSApple OSS Distributions bcopy(&ifra->ifra_broadaddr, &broadaddr, sizeof(broadaddr));
663*aca3beaaSApple OSS Distributions bcopy(&ifra->ifra_mask, &mask, sizeof(mask));
664*aca3beaaSApple OSS Distributions
665*aca3beaaSApple OSS Distributions maskIsNew = 0;
666*aca3beaaSApple OSS Distributions hostIsNew = 1;
667*aca3beaaSApple OSS Distributions error = 0;
668*aca3beaaSApple OSS Distributions
669*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
670*aca3beaaSApple OSS Distributions if (ia->ia_addr.sin_family == AF_INET) {
671*aca3beaaSApple OSS Distributions if (addr.sin_len == 0) {
672*aca3beaaSApple OSS Distributions addr = ia->ia_addr;
673*aca3beaaSApple OSS Distributions hostIsNew = 0;
674*aca3beaaSApple OSS Distributions } else if (addr.sin_addr.s_addr ==
675*aca3beaaSApple OSS Distributions ia->ia_addr.sin_addr.s_addr) {
676*aca3beaaSApple OSS Distributions hostIsNew = 0;
677*aca3beaaSApple OSS Distributions }
678*aca3beaaSApple OSS Distributions }
679*aca3beaaSApple OSS Distributions if (mask.sin_len != 0) {
680*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
681*aca3beaaSApple OSS Distributions in_ifscrub(ifp, ia, 0);
682*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
683*aca3beaaSApple OSS Distributions ia->ia_sockmask.sin_len = sizeof(struct sockaddr_in);
684*aca3beaaSApple OSS Distributions ia->ia_sockmask.sin_family = AF_INET;
685*aca3beaaSApple OSS Distributions ia->ia_sockmask.sin_port = 0;
686*aca3beaaSApple OSS Distributions ia->ia_sockmask.sin_addr = mask.sin_addr;
687*aca3beaaSApple OSS Distributions bzero(&ia->ia_sockmask.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
688*aca3beaaSApple OSS Distributions ia->ia_subnetmask =
689*aca3beaaSApple OSS Distributions ntohl(ia->ia_sockmask.sin_addr.s_addr);
690*aca3beaaSApple OSS Distributions maskIsNew = 1;
691*aca3beaaSApple OSS Distributions }
692*aca3beaaSApple OSS Distributions if ((ifp->if_flags & IFF_POINTOPOINT) &&
693*aca3beaaSApple OSS Distributions (broadaddr.sin_family == AF_INET)) {
694*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
695*aca3beaaSApple OSS Distributions in_ifscrub(ifp, ia, 0);
696*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
697*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_family = AF_INET;
698*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
699*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_port = 0;
700*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_addr = broadaddr.sin_addr;
701*aca3beaaSApple OSS Distributions bzero(&ia->ia_dstaddr.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
702*aca3beaaSApple OSS Distributions maskIsNew = 1; /* We lie; but the effect's the same */
703*aca3beaaSApple OSS Distributions }
704*aca3beaaSApple OSS Distributions if (addr.sin_family == AF_INET && (hostIsNew || maskIsNew)) {
705*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
706*aca3beaaSApple OSS Distributions error = in_ifinit(ifp, ia, &addr, 0);
707*aca3beaaSApple OSS Distributions } else {
708*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
709*aca3beaaSApple OSS Distributions }
710*aca3beaaSApple OSS Distributions if (error == 0) {
711*aca3beaaSApple OSS Distributions (void) ifnet_notify_address(ifp, AF_INET);
712*aca3beaaSApple OSS Distributions }
713*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
714*aca3beaaSApple OSS Distributions if ((ifp->if_flags & IFF_BROADCAST) &&
715*aca3beaaSApple OSS Distributions (broadaddr.sin_family == AF_INET)) {
716*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_family = AF_INET;
717*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
718*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_port = 0;
719*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_addr = broadaddr.sin_addr;
720*aca3beaaSApple OSS Distributions bzero(&ia->ia_broadaddr.sin_zero, sizeof(ia->ia_broadaddr.sin_zero));
721*aca3beaaSApple OSS Distributions }
722*aca3beaaSApple OSS Distributions
723*aca3beaaSApple OSS Distributions /*
724*aca3beaaSApple OSS Distributions * Report event.
725*aca3beaaSApple OSS Distributions */
726*aca3beaaSApple OSS Distributions if ((error == 0) || (error == EEXIST)) {
727*aca3beaaSApple OSS Distributions ev_msg.vendor_code = KEV_VENDOR_APPLE;
728*aca3beaaSApple OSS Distributions ev_msg.kev_class = KEV_NETWORK_CLASS;
729*aca3beaaSApple OSS Distributions ev_msg.kev_subclass = KEV_INET_SUBCLASS;
730*aca3beaaSApple OSS Distributions
731*aca3beaaSApple OSS Distributions if (hostIsNew) {
732*aca3beaaSApple OSS Distributions ev_msg.event_code = KEV_INET_NEW_ADDR;
733*aca3beaaSApple OSS Distributions } else {
734*aca3beaaSApple OSS Distributions ev_msg.event_code = KEV_INET_CHANGED_ADDR;
735*aca3beaaSApple OSS Distributions }
736*aca3beaaSApple OSS Distributions
737*aca3beaaSApple OSS Distributions if (ia->ia_ifa.ifa_dstaddr) {
738*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr =
739*aca3beaaSApple OSS Distributions ((struct sockaddr_in *)(void *)ia->
740*aca3beaaSApple OSS Distributions ia_ifa.ifa_dstaddr)->sin_addr;
741*aca3beaaSApple OSS Distributions } else {
742*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
743*aca3beaaSApple OSS Distributions }
744*aca3beaaSApple OSS Distributions in_event_data.ia_addr = ia->ia_addr.sin_addr;
745*aca3beaaSApple OSS Distributions in_event_data.ia_net = ia->ia_net;
746*aca3beaaSApple OSS Distributions in_event_data.ia_netmask = ia->ia_netmask;
747*aca3beaaSApple OSS Distributions in_event_data.ia_subnet = ia->ia_subnet;
748*aca3beaaSApple OSS Distributions in_event_data.ia_subnetmask = ia->ia_subnetmask;
749*aca3beaaSApple OSS Distributions in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
750*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
751*aca3beaaSApple OSS Distributions (void) strlcpy(&in_event_data.link_data.if_name[0],
752*aca3beaaSApple OSS Distributions ifp->if_name, IFNAMSIZ);
753*aca3beaaSApple OSS Distributions in_event_data.link_data.if_family = ifp->if_family;
754*aca3beaaSApple OSS Distributions in_event_data.link_data.if_unit = ifp->if_unit;
755*aca3beaaSApple OSS Distributions
756*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_ptr = &in_event_data;
757*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
758*aca3beaaSApple OSS Distributions ev_msg.dv[1].data_length = 0;
759*aca3beaaSApple OSS Distributions
760*aca3beaaSApple OSS Distributions dlil_post_complete_msg(ifp, &ev_msg);
761*aca3beaaSApple OSS Distributions } else {
762*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
763*aca3beaaSApple OSS Distributions }
764*aca3beaaSApple OSS Distributions break;
765*aca3beaaSApple OSS Distributions }
766*aca3beaaSApple OSS Distributions
767*aca3beaaSApple OSS Distributions case SIOCDIFADDR: /* struct ifreq */
768*aca3beaaSApple OSS Distributions VERIFY(ia != NULL);
769*aca3beaaSApple OSS Distributions error = ifnet_ioctl(ifp, PF_INET, SIOCDIFADDR, ia);
770*aca3beaaSApple OSS Distributions if (error == EOPNOTSUPP) {
771*aca3beaaSApple OSS Distributions error = 0;
772*aca3beaaSApple OSS Distributions }
773*aca3beaaSApple OSS Distributions if (error != 0) {
774*aca3beaaSApple OSS Distributions break;
775*aca3beaaSApple OSS Distributions }
776*aca3beaaSApple OSS Distributions
777*aca3beaaSApple OSS Distributions /* Fill out the kernel event information */
778*aca3beaaSApple OSS Distributions ev_msg.vendor_code = KEV_VENDOR_APPLE;
779*aca3beaaSApple OSS Distributions ev_msg.kev_class = KEV_NETWORK_CLASS;
780*aca3beaaSApple OSS Distributions ev_msg.kev_subclass = KEV_INET_SUBCLASS;
781*aca3beaaSApple OSS Distributions
782*aca3beaaSApple OSS Distributions ev_msg.event_code = KEV_INET_ADDR_DELETED;
783*aca3beaaSApple OSS Distributions
784*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
785*aca3beaaSApple OSS Distributions if (ia->ia_ifa.ifa_dstaddr) {
786*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr = ((struct sockaddr_in *)
787*aca3beaaSApple OSS Distributions (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
788*aca3beaaSApple OSS Distributions } else {
789*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
790*aca3beaaSApple OSS Distributions }
791*aca3beaaSApple OSS Distributions in_event_data.ia_addr = ia->ia_addr.sin_addr;
792*aca3beaaSApple OSS Distributions in_event_data.ia_net = ia->ia_net;
793*aca3beaaSApple OSS Distributions in_event_data.ia_netmask = ia->ia_netmask;
794*aca3beaaSApple OSS Distributions in_event_data.ia_subnet = ia->ia_subnet;
795*aca3beaaSApple OSS Distributions in_event_data.ia_subnetmask = ia->ia_subnetmask;
796*aca3beaaSApple OSS Distributions in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
797*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
798*aca3beaaSApple OSS Distributions (void) strlcpy(&in_event_data.link_data.if_name[0],
799*aca3beaaSApple OSS Distributions ifp->if_name, IFNAMSIZ);
800*aca3beaaSApple OSS Distributions in_event_data.link_data.if_family = ifp->if_family;
801*aca3beaaSApple OSS Distributions in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
802*aca3beaaSApple OSS Distributions
803*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_ptr = &in_event_data;
804*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
805*aca3beaaSApple OSS Distributions ev_msg.dv[1].data_length = 0;
806*aca3beaaSApple OSS Distributions
807*aca3beaaSApple OSS Distributions ifa = &ia->ia_ifa;
808*aca3beaaSApple OSS Distributions lck_rw_lock_exclusive(&in_ifaddr_rwlock);
809*aca3beaaSApple OSS Distributions /* Release ia_link reference */
810*aca3beaaSApple OSS Distributions IFA_REMREF(ifa);
811*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
812*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
813*aca3beaaSApple OSS Distributions if (IA_IS_HASHED(ia)) {
814*aca3beaaSApple OSS Distributions in_iahash_remove(ia);
815*aca3beaaSApple OSS Distributions }
816*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
817*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
818*aca3beaaSApple OSS Distributions
819*aca3beaaSApple OSS Distributions /*
820*aca3beaaSApple OSS Distributions * in_ifscrub kills the interface route.
821*aca3beaaSApple OSS Distributions */
822*aca3beaaSApple OSS Distributions in_ifscrub(ifp, ia, 0);
823*aca3beaaSApple OSS Distributions ifnet_lock_exclusive(ifp);
824*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
825*aca3beaaSApple OSS Distributions /* if_detach_ifa() releases ifa_link reference */
826*aca3beaaSApple OSS Distributions if_detach_ifa(ifp, ifa);
827*aca3beaaSApple OSS Distributions /* Our reference to this address is dropped at the bottom */
828*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
829*aca3beaaSApple OSS Distributions
830*aca3beaaSApple OSS Distributions /* invalidate route caches */
831*aca3beaaSApple OSS Distributions routegenid_inet_update();
832*aca3beaaSApple OSS Distributions
833*aca3beaaSApple OSS Distributions /*
834*aca3beaaSApple OSS Distributions * If the interface supports multicast, and no address is left,
835*aca3beaaSApple OSS Distributions * remove the "all hosts" multicast group from that interface.
836*aca3beaaSApple OSS Distributions */
837*aca3beaaSApple OSS Distributions if ((ifp->if_flags & IFF_MULTICAST) ||
838*aca3beaaSApple OSS Distributions ifp->if_allhostsinm != NULL) {
839*aca3beaaSApple OSS Distributions TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
840*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
841*aca3beaaSApple OSS Distributions if (ifa->ifa_addr->sa_family == AF_INET) {
842*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
843*aca3beaaSApple OSS Distributions break;
844*aca3beaaSApple OSS Distributions }
845*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
846*aca3beaaSApple OSS Distributions }
847*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
848*aca3beaaSApple OSS Distributions
849*aca3beaaSApple OSS Distributions lck_mtx_lock(&ifp->if_addrconfig_lock);
850*aca3beaaSApple OSS Distributions if (ifa == NULL && ifp->if_allhostsinm != NULL) {
851*aca3beaaSApple OSS Distributions struct in_multi *inm = ifp->if_allhostsinm;
852*aca3beaaSApple OSS Distributions ifp->if_allhostsinm = NULL;
853*aca3beaaSApple OSS Distributions
854*aca3beaaSApple OSS Distributions in_delmulti(inm);
855*aca3beaaSApple OSS Distributions /* release the reference for allhostsinm */
856*aca3beaaSApple OSS Distributions INM_REMREF(inm);
857*aca3beaaSApple OSS Distributions }
858*aca3beaaSApple OSS Distributions lck_mtx_unlock(&ifp->if_addrconfig_lock);
859*aca3beaaSApple OSS Distributions } else {
860*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
861*aca3beaaSApple OSS Distributions }
862*aca3beaaSApple OSS Distributions
863*aca3beaaSApple OSS Distributions /* Post the kernel event */
864*aca3beaaSApple OSS Distributions dlil_post_complete_msg(ifp, &ev_msg);
865*aca3beaaSApple OSS Distributions
866*aca3beaaSApple OSS Distributions /*
867*aca3beaaSApple OSS Distributions * See if there is any IPV4 address left and if so,
868*aca3beaaSApple OSS Distributions * reconfigure KDP to use current primary address.
869*aca3beaaSApple OSS Distributions */
870*aca3beaaSApple OSS Distributions ifa = ifa_ifpgetprimary(ifp, AF_INET);
871*aca3beaaSApple OSS Distributions if (ifa != NULL) {
872*aca3beaaSApple OSS Distributions /*
873*aca3beaaSApple OSS Distributions * NOTE: SIOCSIFADDR is defined with struct ifreq
874*aca3beaaSApple OSS Distributions * as parameter, but here we are sending it down
875*aca3beaaSApple OSS Distributions * to the interface with a pointer to struct ifaddr,
876*aca3beaaSApple OSS Distributions * for legacy reasons.
877*aca3beaaSApple OSS Distributions */
878*aca3beaaSApple OSS Distributions error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa);
879*aca3beaaSApple OSS Distributions if (error == EOPNOTSUPP) {
880*aca3beaaSApple OSS Distributions error = 0;
881*aca3beaaSApple OSS Distributions }
882*aca3beaaSApple OSS Distributions
883*aca3beaaSApple OSS Distributions /* Release reference from ifa_ifpgetprimary() */
884*aca3beaaSApple OSS Distributions IFA_REMREF(ifa);
885*aca3beaaSApple OSS Distributions }
886*aca3beaaSApple OSS Distributions (void) ifnet_notify_address(ifp, AF_INET);
887*aca3beaaSApple OSS Distributions break;
888*aca3beaaSApple OSS Distributions
889*aca3beaaSApple OSS Distributions default:
890*aca3beaaSApple OSS Distributions VERIFY(0);
891*aca3beaaSApple OSS Distributions /* NOTREACHED */
892*aca3beaaSApple OSS Distributions }
893*aca3beaaSApple OSS Distributions
894*aca3beaaSApple OSS Distributions return error;
895*aca3beaaSApple OSS Distributions }
896*aca3beaaSApple OSS Distributions
897*aca3beaaSApple OSS Distributions /*
898*aca3beaaSApple OSS Distributions * Caller passes in the ioctl data pointer directly via "ifr", with the
899*aca3beaaSApple OSS Distributions * expectation that this routine always uses bcopy() or other byte-aligned
900*aca3beaaSApple OSS Distributions * memory accesses.
901*aca3beaaSApple OSS Distributions */
902*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_ifdstaddr(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)903*aca3beaaSApple OSS Distributions inctl_ifdstaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
904*aca3beaaSApple OSS Distributions struct ifreq *ifr)
905*aca3beaaSApple OSS Distributions {
906*aca3beaaSApple OSS Distributions struct kev_in_data in_event_data;
907*aca3beaaSApple OSS Distributions struct kev_msg ev_msg;
908*aca3beaaSApple OSS Distributions struct sockaddr_in dstaddr;
909*aca3beaaSApple OSS Distributions int error = 0;
910*aca3beaaSApple OSS Distributions
911*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
912*aca3beaaSApple OSS Distributions
913*aca3beaaSApple OSS Distributions if (!(ifp->if_flags & IFF_POINTOPOINT)) {
914*aca3beaaSApple OSS Distributions return EINVAL;
915*aca3beaaSApple OSS Distributions }
916*aca3beaaSApple OSS Distributions
917*aca3beaaSApple OSS Distributions bzero(&in_event_data, sizeof(struct kev_in_data));
918*aca3beaaSApple OSS Distributions bzero(&ev_msg, sizeof(struct kev_msg));
919*aca3beaaSApple OSS Distributions
920*aca3beaaSApple OSS Distributions switch (cmd) {
921*aca3beaaSApple OSS Distributions case SIOCGIFDSTADDR: /* struct ifreq */
922*aca3beaaSApple OSS Distributions if (ia == NULL) {
923*aca3beaaSApple OSS Distributions error = EADDRNOTAVAIL;
924*aca3beaaSApple OSS Distributions break;
925*aca3beaaSApple OSS Distributions }
926*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
927*aca3beaaSApple OSS Distributions bcopy(&ia->ia_dstaddr, &ifr->ifr_dstaddr, sizeof(dstaddr));
928*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
929*aca3beaaSApple OSS Distributions break;
930*aca3beaaSApple OSS Distributions
931*aca3beaaSApple OSS Distributions case SIOCSIFDSTADDR: /* struct ifreq */
932*aca3beaaSApple OSS Distributions VERIFY(ia != NULL);
933*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
934*aca3beaaSApple OSS Distributions dstaddr = ia->ia_dstaddr;
935*aca3beaaSApple OSS Distributions
936*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_family = AF_INET;
937*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
938*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_port = 0;
939*aca3beaaSApple OSS Distributions bcopy(&(SIN(&ifr->ifr_dstaddr)->sin_addr),
940*aca3beaaSApple OSS Distributions &ia->ia_dstaddr.sin_addr, sizeof(ia->ia_dstaddr.sin_addr));
941*aca3beaaSApple OSS Distributions bzero(&ia->ia_dstaddr.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
942*aca3beaaSApple OSS Distributions
943*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
944*aca3beaaSApple OSS Distributions /*
945*aca3beaaSApple OSS Distributions * NOTE: SIOCSIFDSTADDR is defined with struct ifreq
946*aca3beaaSApple OSS Distributions * as parameter, but here we are sending it down
947*aca3beaaSApple OSS Distributions * to the interface with a pointer to struct ifaddr,
948*aca3beaaSApple OSS Distributions * for legacy reasons.
949*aca3beaaSApple OSS Distributions */
950*aca3beaaSApple OSS Distributions error = ifnet_ioctl(ifp, PF_INET, SIOCSIFDSTADDR, ia);
951*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
952*aca3beaaSApple OSS Distributions if (error == EOPNOTSUPP) {
953*aca3beaaSApple OSS Distributions error = 0;
954*aca3beaaSApple OSS Distributions }
955*aca3beaaSApple OSS Distributions if (error != 0) {
956*aca3beaaSApple OSS Distributions ia->ia_dstaddr = dstaddr;
957*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
958*aca3beaaSApple OSS Distributions break;
959*aca3beaaSApple OSS Distributions }
960*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
961*aca3beaaSApple OSS Distributions
962*aca3beaaSApple OSS Distributions ev_msg.vendor_code = KEV_VENDOR_APPLE;
963*aca3beaaSApple OSS Distributions ev_msg.kev_class = KEV_NETWORK_CLASS;
964*aca3beaaSApple OSS Distributions ev_msg.kev_subclass = KEV_INET_SUBCLASS;
965*aca3beaaSApple OSS Distributions
966*aca3beaaSApple OSS Distributions ev_msg.event_code = KEV_INET_SIFDSTADDR;
967*aca3beaaSApple OSS Distributions
968*aca3beaaSApple OSS Distributions if (ia->ia_ifa.ifa_dstaddr) {
969*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr = ((struct sockaddr_in *)
970*aca3beaaSApple OSS Distributions (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
971*aca3beaaSApple OSS Distributions } else {
972*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
973*aca3beaaSApple OSS Distributions }
974*aca3beaaSApple OSS Distributions
975*aca3beaaSApple OSS Distributions in_event_data.ia_addr = ia->ia_addr.sin_addr;
976*aca3beaaSApple OSS Distributions in_event_data.ia_net = ia->ia_net;
977*aca3beaaSApple OSS Distributions in_event_data.ia_netmask = ia->ia_netmask;
978*aca3beaaSApple OSS Distributions in_event_data.ia_subnet = ia->ia_subnet;
979*aca3beaaSApple OSS Distributions in_event_data.ia_subnetmask = ia->ia_subnetmask;
980*aca3beaaSApple OSS Distributions in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
981*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
982*aca3beaaSApple OSS Distributions (void) strlcpy(&in_event_data.link_data.if_name[0],
983*aca3beaaSApple OSS Distributions ifp->if_name, IFNAMSIZ);
984*aca3beaaSApple OSS Distributions in_event_data.link_data.if_family = ifp->if_family;
985*aca3beaaSApple OSS Distributions in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
986*aca3beaaSApple OSS Distributions
987*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_ptr = &in_event_data;
988*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
989*aca3beaaSApple OSS Distributions ev_msg.dv[1].data_length = 0;
990*aca3beaaSApple OSS Distributions
991*aca3beaaSApple OSS Distributions dlil_post_complete_msg(ifp, &ev_msg);
992*aca3beaaSApple OSS Distributions
993*aca3beaaSApple OSS Distributions lck_mtx_lock(rnh_lock);
994*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
995*aca3beaaSApple OSS Distributions if (ia->ia_flags & IFA_ROUTE) {
996*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&dstaddr;
997*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
998*aca3beaaSApple OSS Distributions rtinit_locked(&(ia->ia_ifa), RTM_DELETE, RTF_HOST);
999*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1000*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_dstaddr =
1001*aca3beaaSApple OSS Distributions (struct sockaddr *)&ia->ia_dstaddr;
1002*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1003*aca3beaaSApple OSS Distributions rtinit_locked(&(ia->ia_ifa), RTM_ADD,
1004*aca3beaaSApple OSS Distributions RTF_HOST | RTF_UP);
1005*aca3beaaSApple OSS Distributions } else {
1006*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1007*aca3beaaSApple OSS Distributions }
1008*aca3beaaSApple OSS Distributions lck_mtx_unlock(rnh_lock);
1009*aca3beaaSApple OSS Distributions break;
1010*aca3beaaSApple OSS Distributions
1011*aca3beaaSApple OSS Distributions
1012*aca3beaaSApple OSS Distributions
1013*aca3beaaSApple OSS Distributions default:
1014*aca3beaaSApple OSS Distributions VERIFY(0);
1015*aca3beaaSApple OSS Distributions /* NOTREACHED */
1016*aca3beaaSApple OSS Distributions }
1017*aca3beaaSApple OSS Distributions
1018*aca3beaaSApple OSS Distributions return error;
1019*aca3beaaSApple OSS Distributions }
1020*aca3beaaSApple OSS Distributions
1021*aca3beaaSApple OSS Distributions /*
1022*aca3beaaSApple OSS Distributions * Caller passes in the ioctl data pointer directly via "ifr", with the
1023*aca3beaaSApple OSS Distributions * expectation that this routine always uses bcopy() or other byte-aligned
1024*aca3beaaSApple OSS Distributions * memory accesses.
1025*aca3beaaSApple OSS Distributions */
1026*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_ifbrdaddr(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)1027*aca3beaaSApple OSS Distributions inctl_ifbrdaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
1028*aca3beaaSApple OSS Distributions struct ifreq *ifr)
1029*aca3beaaSApple OSS Distributions {
1030*aca3beaaSApple OSS Distributions struct kev_in_data in_event_data;
1031*aca3beaaSApple OSS Distributions struct kev_msg ev_msg;
1032*aca3beaaSApple OSS Distributions int error = 0;
1033*aca3beaaSApple OSS Distributions
1034*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
1035*aca3beaaSApple OSS Distributions
1036*aca3beaaSApple OSS Distributions if (ia == NULL) {
1037*aca3beaaSApple OSS Distributions return EADDRNOTAVAIL;
1038*aca3beaaSApple OSS Distributions }
1039*aca3beaaSApple OSS Distributions
1040*aca3beaaSApple OSS Distributions if (!(ifp->if_flags & IFF_BROADCAST)) {
1041*aca3beaaSApple OSS Distributions return EINVAL;
1042*aca3beaaSApple OSS Distributions }
1043*aca3beaaSApple OSS Distributions
1044*aca3beaaSApple OSS Distributions bzero(&in_event_data, sizeof(struct kev_in_data));
1045*aca3beaaSApple OSS Distributions bzero(&ev_msg, sizeof(struct kev_msg));
1046*aca3beaaSApple OSS Distributions
1047*aca3beaaSApple OSS Distributions switch (cmd) {
1048*aca3beaaSApple OSS Distributions case SIOCGIFBRDADDR: /* struct ifreq */
1049*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1050*aca3beaaSApple OSS Distributions bcopy(&ia->ia_broadaddr, &ifr->ifr_broadaddr,
1051*aca3beaaSApple OSS Distributions sizeof(struct sockaddr_in));
1052*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1053*aca3beaaSApple OSS Distributions break;
1054*aca3beaaSApple OSS Distributions
1055*aca3beaaSApple OSS Distributions case SIOCSIFBRDADDR: /* struct ifreq */
1056*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1057*aca3beaaSApple OSS Distributions
1058*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_family = AF_INET;
1059*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
1060*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_port = 0;
1061*aca3beaaSApple OSS Distributions bcopy(&(SIN(&ifr->ifr_broadaddr)->sin_addr),
1062*aca3beaaSApple OSS Distributions &ia->ia_broadaddr.sin_addr, sizeof(ia->ia_broadaddr.sin_addr));
1063*aca3beaaSApple OSS Distributions bzero(&ia->ia_broadaddr.sin_zero, sizeof(ia->ia_broadaddr.sin_zero));
1064*aca3beaaSApple OSS Distributions
1065*aca3beaaSApple OSS Distributions ev_msg.vendor_code = KEV_VENDOR_APPLE;
1066*aca3beaaSApple OSS Distributions ev_msg.kev_class = KEV_NETWORK_CLASS;
1067*aca3beaaSApple OSS Distributions ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1068*aca3beaaSApple OSS Distributions
1069*aca3beaaSApple OSS Distributions ev_msg.event_code = KEV_INET_SIFBRDADDR;
1070*aca3beaaSApple OSS Distributions
1071*aca3beaaSApple OSS Distributions if (ia->ia_ifa.ifa_dstaddr) {
1072*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr = ((struct sockaddr_in *)
1073*aca3beaaSApple OSS Distributions (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
1074*aca3beaaSApple OSS Distributions } else {
1075*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1076*aca3beaaSApple OSS Distributions }
1077*aca3beaaSApple OSS Distributions in_event_data.ia_addr = ia->ia_addr.sin_addr;
1078*aca3beaaSApple OSS Distributions in_event_data.ia_net = ia->ia_net;
1079*aca3beaaSApple OSS Distributions in_event_data.ia_netmask = ia->ia_netmask;
1080*aca3beaaSApple OSS Distributions in_event_data.ia_subnet = ia->ia_subnet;
1081*aca3beaaSApple OSS Distributions in_event_data.ia_subnetmask = ia->ia_subnetmask;
1082*aca3beaaSApple OSS Distributions in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
1083*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1084*aca3beaaSApple OSS Distributions (void) strlcpy(&in_event_data.link_data.if_name[0],
1085*aca3beaaSApple OSS Distributions ifp->if_name, IFNAMSIZ);
1086*aca3beaaSApple OSS Distributions in_event_data.link_data.if_family = ifp->if_family;
1087*aca3beaaSApple OSS Distributions in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
1088*aca3beaaSApple OSS Distributions
1089*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_ptr = &in_event_data;
1090*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1091*aca3beaaSApple OSS Distributions ev_msg.dv[1].data_length = 0;
1092*aca3beaaSApple OSS Distributions
1093*aca3beaaSApple OSS Distributions dlil_post_complete_msg(ifp, &ev_msg);
1094*aca3beaaSApple OSS Distributions break;
1095*aca3beaaSApple OSS Distributions
1096*aca3beaaSApple OSS Distributions default:
1097*aca3beaaSApple OSS Distributions VERIFY(0);
1098*aca3beaaSApple OSS Distributions /* NOTREACHED */
1099*aca3beaaSApple OSS Distributions }
1100*aca3beaaSApple OSS Distributions
1101*aca3beaaSApple OSS Distributions return error;
1102*aca3beaaSApple OSS Distributions }
1103*aca3beaaSApple OSS Distributions
1104*aca3beaaSApple OSS Distributions /*
1105*aca3beaaSApple OSS Distributions * Caller passes in the ioctl data pointer directly via "ifr", with the
1106*aca3beaaSApple OSS Distributions * expectation that this routine always uses bcopy() or other byte-aligned
1107*aca3beaaSApple OSS Distributions * memory accesses.
1108*aca3beaaSApple OSS Distributions */
1109*aca3beaaSApple OSS Distributions static __attribute__((noinline)) int
inctl_ifnetmask(struct ifnet * ifp,struct in_ifaddr * ia,u_long cmd,struct ifreq * ifr)1110*aca3beaaSApple OSS Distributions inctl_ifnetmask(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
1111*aca3beaaSApple OSS Distributions struct ifreq *ifr)
1112*aca3beaaSApple OSS Distributions {
1113*aca3beaaSApple OSS Distributions struct kev_in_data in_event_data;
1114*aca3beaaSApple OSS Distributions struct kev_msg ev_msg;
1115*aca3beaaSApple OSS Distributions struct sockaddr_in mask;
1116*aca3beaaSApple OSS Distributions int error = 0;
1117*aca3beaaSApple OSS Distributions
1118*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
1119*aca3beaaSApple OSS Distributions
1120*aca3beaaSApple OSS Distributions bzero(&in_event_data, sizeof(struct kev_in_data));
1121*aca3beaaSApple OSS Distributions bzero(&ev_msg, sizeof(struct kev_msg));
1122*aca3beaaSApple OSS Distributions
1123*aca3beaaSApple OSS Distributions switch (cmd) {
1124*aca3beaaSApple OSS Distributions case SIOCGIFNETMASK: /* struct ifreq */
1125*aca3beaaSApple OSS Distributions if (ia == NULL) {
1126*aca3beaaSApple OSS Distributions error = EADDRNOTAVAIL;
1127*aca3beaaSApple OSS Distributions break;
1128*aca3beaaSApple OSS Distributions }
1129*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1130*aca3beaaSApple OSS Distributions bcopy(&ia->ia_sockmask, &ifr->ifr_addr, sizeof(mask));
1131*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1132*aca3beaaSApple OSS Distributions break;
1133*aca3beaaSApple OSS Distributions
1134*aca3beaaSApple OSS Distributions case SIOCSIFNETMASK: { /* struct ifreq */
1135*aca3beaaSApple OSS Distributions in_addr_t i;
1136*aca3beaaSApple OSS Distributions
1137*aca3beaaSApple OSS Distributions bcopy(&ifr->ifr_addr, &mask, sizeof(mask));
1138*aca3beaaSApple OSS Distributions i = mask.sin_addr.s_addr;
1139*aca3beaaSApple OSS Distributions
1140*aca3beaaSApple OSS Distributions VERIFY(ia != NULL);
1141*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1142*aca3beaaSApple OSS Distributions ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
1143*aca3beaaSApple OSS Distributions ev_msg.vendor_code = KEV_VENDOR_APPLE;
1144*aca3beaaSApple OSS Distributions ev_msg.kev_class = KEV_NETWORK_CLASS;
1145*aca3beaaSApple OSS Distributions ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1146*aca3beaaSApple OSS Distributions
1147*aca3beaaSApple OSS Distributions ev_msg.event_code = KEV_INET_SIFNETMASK;
1148*aca3beaaSApple OSS Distributions
1149*aca3beaaSApple OSS Distributions if (ia->ia_ifa.ifa_dstaddr) {
1150*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr = ((struct sockaddr_in *)
1151*aca3beaaSApple OSS Distributions (void *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
1152*aca3beaaSApple OSS Distributions } else {
1153*aca3beaaSApple OSS Distributions in_event_data.ia_dstaddr.s_addr = INADDR_ANY;
1154*aca3beaaSApple OSS Distributions }
1155*aca3beaaSApple OSS Distributions in_event_data.ia_addr = ia->ia_addr.sin_addr;
1156*aca3beaaSApple OSS Distributions in_event_data.ia_net = ia->ia_net;
1157*aca3beaaSApple OSS Distributions in_event_data.ia_netmask = ia->ia_netmask;
1158*aca3beaaSApple OSS Distributions in_event_data.ia_subnet = ia->ia_subnet;
1159*aca3beaaSApple OSS Distributions in_event_data.ia_subnetmask = ia->ia_subnetmask;
1160*aca3beaaSApple OSS Distributions in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
1161*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1162*aca3beaaSApple OSS Distributions (void) strlcpy(&in_event_data.link_data.if_name[0],
1163*aca3beaaSApple OSS Distributions ifp->if_name, IFNAMSIZ);
1164*aca3beaaSApple OSS Distributions in_event_data.link_data.if_family = ifp->if_family;
1165*aca3beaaSApple OSS Distributions in_event_data.link_data.if_unit = (u_int32_t)ifp->if_unit;
1166*aca3beaaSApple OSS Distributions
1167*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_ptr = &in_event_data;
1168*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1169*aca3beaaSApple OSS Distributions ev_msg.dv[1].data_length = 0;
1170*aca3beaaSApple OSS Distributions
1171*aca3beaaSApple OSS Distributions dlil_post_complete_msg(ifp, &ev_msg);
1172*aca3beaaSApple OSS Distributions break;
1173*aca3beaaSApple OSS Distributions }
1174*aca3beaaSApple OSS Distributions
1175*aca3beaaSApple OSS Distributions default:
1176*aca3beaaSApple OSS Distributions VERIFY(0);
1177*aca3beaaSApple OSS Distributions /* NOTREACHED */
1178*aca3beaaSApple OSS Distributions }
1179*aca3beaaSApple OSS Distributions
1180*aca3beaaSApple OSS Distributions return error;
1181*aca3beaaSApple OSS Distributions }
1182*aca3beaaSApple OSS Distributions
1183*aca3beaaSApple OSS Distributions /*
1184*aca3beaaSApple OSS Distributions * Generic INET control operations (ioctl's).
1185*aca3beaaSApple OSS Distributions *
1186*aca3beaaSApple OSS Distributions * ifp is NULL if not an interface-specific ioctl.
1187*aca3beaaSApple OSS Distributions *
1188*aca3beaaSApple OSS Distributions * Most of the routines called to handle the ioctls would end up being
1189*aca3beaaSApple OSS Distributions * tail-call optimized, which unfortunately causes this routine to
1190*aca3beaaSApple OSS Distributions * consume too much stack space; this is the reason for the "noinline"
1191*aca3beaaSApple OSS Distributions * attribute used on those routines.
1192*aca3beaaSApple OSS Distributions *
1193*aca3beaaSApple OSS Distributions * If called directly from within the networking stack (as opposed to via
1194*aca3beaaSApple OSS Distributions * pru_control), the socket parameter may be NULL.
1195*aca3beaaSApple OSS Distributions */
1196*aca3beaaSApple OSS Distributions int
in_control(struct socket * so,u_long cmd,caddr_t data,struct ifnet * ifp,struct proc * p)1197*aca3beaaSApple OSS Distributions in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
1198*aca3beaaSApple OSS Distributions struct proc *p)
1199*aca3beaaSApple OSS Distributions {
1200*aca3beaaSApple OSS Distributions struct ifreq *ifr = (struct ifreq *)(void *)data;
1201*aca3beaaSApple OSS Distributions struct sockaddr_in addr, dstaddr;
1202*aca3beaaSApple OSS Distributions struct sockaddr_in sin, *sa = NULL;
1203*aca3beaaSApple OSS Distributions boolean_t privileged = (proc_suser(p) == 0);
1204*aca3beaaSApple OSS Distributions boolean_t so_unlocked = FALSE;
1205*aca3beaaSApple OSS Distributions struct in_ifaddr *ia = NULL;
1206*aca3beaaSApple OSS Distributions struct ifaddr *ifa;
1207*aca3beaaSApple OSS Distributions int error = 0;
1208*aca3beaaSApple OSS Distributions int intval;
1209*aca3beaaSApple OSS Distributions
1210*aca3beaaSApple OSS Distributions /* In case it's NULL, make sure it came from the kernel */
1211*aca3beaaSApple OSS Distributions VERIFY(so != NULL || p == kernproc);
1212*aca3beaaSApple OSS Distributions
1213*aca3beaaSApple OSS Distributions /*
1214*aca3beaaSApple OSS Distributions * ioctls which don't require ifp, but require socket.
1215*aca3beaaSApple OSS Distributions */
1216*aca3beaaSApple OSS Distributions switch (cmd) {
1217*aca3beaaSApple OSS Distributions case SIOCGASSOCIDS32: /* struct so_aidreq32 */
1218*aca3beaaSApple OSS Distributions case SIOCGASSOCIDS64: /* struct so_aidreq64 */
1219*aca3beaaSApple OSS Distributions return inctl_associd(so, cmd, data);
1220*aca3beaaSApple OSS Distributions /* NOTREACHED */
1221*aca3beaaSApple OSS Distributions
1222*aca3beaaSApple OSS Distributions case SIOCGCONNIDS32: /* struct so_cidreq32 */
1223*aca3beaaSApple OSS Distributions case SIOCGCONNIDS64: /* struct so_cidreq64 */
1224*aca3beaaSApple OSS Distributions return inctl_connid(so, cmd, data);
1225*aca3beaaSApple OSS Distributions /* NOTREACHED */
1226*aca3beaaSApple OSS Distributions
1227*aca3beaaSApple OSS Distributions case SIOCGCONNINFO32: /* struct so_cinforeq32 */
1228*aca3beaaSApple OSS Distributions case SIOCGCONNINFO64: /* struct so_cinforeq64 */
1229*aca3beaaSApple OSS Distributions return inctl_conninfo(so, cmd, data);
1230*aca3beaaSApple OSS Distributions /* NOTREACHED */
1231*aca3beaaSApple OSS Distributions }
1232*aca3beaaSApple OSS Distributions
1233*aca3beaaSApple OSS Distributions /*
1234*aca3beaaSApple OSS Distributions * The rest of ioctls require ifp; reject if we don't have one;
1235*aca3beaaSApple OSS Distributions * return ENXIO to be consistent with ifioctl().
1236*aca3beaaSApple OSS Distributions */
1237*aca3beaaSApple OSS Distributions if (ifp == NULL) {
1238*aca3beaaSApple OSS Distributions return ENXIO;
1239*aca3beaaSApple OSS Distributions }
1240*aca3beaaSApple OSS Distributions
1241*aca3beaaSApple OSS Distributions /*
1242*aca3beaaSApple OSS Distributions * ioctls which require ifp but not interface address.
1243*aca3beaaSApple OSS Distributions */
1244*aca3beaaSApple OSS Distributions switch (cmd) {
1245*aca3beaaSApple OSS Distributions case SIOCAUTOADDR: /* struct ifreq */
1246*aca3beaaSApple OSS Distributions if (!privileged) {
1247*aca3beaaSApple OSS Distributions return EPERM;
1248*aca3beaaSApple OSS Distributions }
1249*aca3beaaSApple OSS Distributions return inctl_autoaddr(ifp, ifr);
1250*aca3beaaSApple OSS Distributions /* NOTREACHED */
1251*aca3beaaSApple OSS Distributions
1252*aca3beaaSApple OSS Distributions case SIOCARPIPLL: /* struct ifreq */
1253*aca3beaaSApple OSS Distributions if (!privileged) {
1254*aca3beaaSApple OSS Distributions return EPERM;
1255*aca3beaaSApple OSS Distributions }
1256*aca3beaaSApple OSS Distributions return inctl_arpipll(ifp, ifr);
1257*aca3beaaSApple OSS Distributions /* NOTREACHED */
1258*aca3beaaSApple OSS Distributions
1259*aca3beaaSApple OSS Distributions case SIOCGETROUTERMODE: /* struct ifreq */
1260*aca3beaaSApple OSS Distributions intval = (ifp->if_eflags & IFEF_IPV4_ROUTER) != 0 ? 1 : 0;
1261*aca3beaaSApple OSS Distributions bcopy(&intval, &ifr->ifr_intval, sizeof(intval));
1262*aca3beaaSApple OSS Distributions return 0;
1263*aca3beaaSApple OSS Distributions /* NOTREACHED */
1264*aca3beaaSApple OSS Distributions
1265*aca3beaaSApple OSS Distributions case SIOCSETROUTERMODE: /* struct ifreq */
1266*aca3beaaSApple OSS Distributions if (!privileged) {
1267*aca3beaaSApple OSS Distributions return EPERM;
1268*aca3beaaSApple OSS Distributions }
1269*aca3beaaSApple OSS Distributions return inctl_setrouter(ifp, ifr);
1270*aca3beaaSApple OSS Distributions /* NOTREACHED */
1271*aca3beaaSApple OSS Distributions
1272*aca3beaaSApple OSS Distributions case SIOCPROTOATTACH: /* struct ifreq */
1273*aca3beaaSApple OSS Distributions if (!privileged) {
1274*aca3beaaSApple OSS Distributions return EPERM;
1275*aca3beaaSApple OSS Distributions }
1276*aca3beaaSApple OSS Distributions return in_domifattach(ifp);
1277*aca3beaaSApple OSS Distributions /* NOTREACHED */
1278*aca3beaaSApple OSS Distributions
1279*aca3beaaSApple OSS Distributions case SIOCPROTODETACH: /* struct ifreq */
1280*aca3beaaSApple OSS Distributions if (!privileged) {
1281*aca3beaaSApple OSS Distributions return EPERM;
1282*aca3beaaSApple OSS Distributions }
1283*aca3beaaSApple OSS Distributions
1284*aca3beaaSApple OSS Distributions /*
1285*aca3beaaSApple OSS Distributions * If an IPv4 address is still present, refuse to detach.
1286*aca3beaaSApple OSS Distributions */
1287*aca3beaaSApple OSS Distributions ifnet_lock_shared(ifp);
1288*aca3beaaSApple OSS Distributions TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1289*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
1290*aca3beaaSApple OSS Distributions if (ifa->ifa_addr->sa_family == AF_INET) {
1291*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
1292*aca3beaaSApple OSS Distributions break;
1293*aca3beaaSApple OSS Distributions }
1294*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
1295*aca3beaaSApple OSS Distributions }
1296*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
1297*aca3beaaSApple OSS Distributions return (ifa == NULL) ? proto_unplumb(PF_INET, ifp) : EBUSY;
1298*aca3beaaSApple OSS Distributions /* NOTREACHED */
1299*aca3beaaSApple OSS Distributions }
1300*aca3beaaSApple OSS Distributions
1301*aca3beaaSApple OSS Distributions /*
1302*aca3beaaSApple OSS Distributions * ioctls which require interface address; obtain sockaddr_in.
1303*aca3beaaSApple OSS Distributions */
1304*aca3beaaSApple OSS Distributions switch (cmd) {
1305*aca3beaaSApple OSS Distributions case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1306*aca3beaaSApple OSS Distributions if (!privileged) {
1307*aca3beaaSApple OSS Distributions return EPERM;
1308*aca3beaaSApple OSS Distributions }
1309*aca3beaaSApple OSS Distributions bcopy(&((struct in_aliasreq *)(void *)data)->ifra_addr,
1310*aca3beaaSApple OSS Distributions &sin, sizeof(sin));
1311*aca3beaaSApple OSS Distributions sa = &sin;
1312*aca3beaaSApple OSS Distributions break;
1313*aca3beaaSApple OSS Distributions
1314*aca3beaaSApple OSS Distributions case SIOCDIFADDR: /* struct ifreq */
1315*aca3beaaSApple OSS Distributions case SIOCSIFADDR: /* struct ifreq */
1316*aca3beaaSApple OSS Distributions case SIOCSIFDSTADDR: /* struct ifreq */
1317*aca3beaaSApple OSS Distributions case SIOCSIFNETMASK: /* struct ifreq */
1318*aca3beaaSApple OSS Distributions case SIOCSIFBRDADDR: /* struct ifreq */
1319*aca3beaaSApple OSS Distributions if (!privileged) {
1320*aca3beaaSApple OSS Distributions return EPERM;
1321*aca3beaaSApple OSS Distributions }
1322*aca3beaaSApple OSS Distributions OS_FALLTHROUGH;
1323*aca3beaaSApple OSS Distributions case SIOCGIFADDR: /* struct ifreq */
1324*aca3beaaSApple OSS Distributions case SIOCGIFDSTADDR: /* struct ifreq */
1325*aca3beaaSApple OSS Distributions case SIOCGIFNETMASK: /* struct ifreq */
1326*aca3beaaSApple OSS Distributions case SIOCGIFBRDADDR: /* struct ifreq */
1327*aca3beaaSApple OSS Distributions bcopy(&ifr->ifr_addr, &sin, sizeof(sin));
1328*aca3beaaSApple OSS Distributions sa = &sin;
1329*aca3beaaSApple OSS Distributions break;
1330*aca3beaaSApple OSS Distributions }
1331*aca3beaaSApple OSS Distributions
1332*aca3beaaSApple OSS Distributions /*
1333*aca3beaaSApple OSS Distributions * Find address for this interface, if it exists.
1334*aca3beaaSApple OSS Distributions *
1335*aca3beaaSApple OSS Distributions * If an alias address was specified, find that one instead of
1336*aca3beaaSApple OSS Distributions * the first one on the interface, if possible.
1337*aca3beaaSApple OSS Distributions */
1338*aca3beaaSApple OSS Distributions VERIFY(ia == NULL);
1339*aca3beaaSApple OSS Distributions if (sa != NULL) {
1340*aca3beaaSApple OSS Distributions struct in_ifaddr *iap;
1341*aca3beaaSApple OSS Distributions
1342*aca3beaaSApple OSS Distributions /*
1343*aca3beaaSApple OSS Distributions * Any failures from this point on must take into account
1344*aca3beaaSApple OSS Distributions * a non-NULL "ia" with an outstanding reference count, and
1345*aca3beaaSApple OSS Distributions * therefore requires IFA_REMREF. Jump to "done" label
1346*aca3beaaSApple OSS Distributions * instead of calling return if "ia" is valid.
1347*aca3beaaSApple OSS Distributions */
1348*aca3beaaSApple OSS Distributions lck_rw_lock_shared(&in_ifaddr_rwlock);
1349*aca3beaaSApple OSS Distributions TAILQ_FOREACH(iap, INADDR_HASH(sa->sin_addr.s_addr), ia_hash) {
1350*aca3beaaSApple OSS Distributions IFA_LOCK(&iap->ia_ifa);
1351*aca3beaaSApple OSS Distributions if (iap->ia_ifp == ifp &&
1352*aca3beaaSApple OSS Distributions iap->ia_addr.sin_addr.s_addr ==
1353*aca3beaaSApple OSS Distributions sa->sin_addr.s_addr) {
1354*aca3beaaSApple OSS Distributions ia = iap;
1355*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(&iap->ia_ifa);
1356*aca3beaaSApple OSS Distributions IFA_UNLOCK(&iap->ia_ifa);
1357*aca3beaaSApple OSS Distributions break;
1358*aca3beaaSApple OSS Distributions }
1359*aca3beaaSApple OSS Distributions IFA_UNLOCK(&iap->ia_ifa);
1360*aca3beaaSApple OSS Distributions }
1361*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
1362*aca3beaaSApple OSS Distributions
1363*aca3beaaSApple OSS Distributions if (ia == NULL) {
1364*aca3beaaSApple OSS Distributions ifnet_lock_shared(ifp);
1365*aca3beaaSApple OSS Distributions TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1366*aca3beaaSApple OSS Distributions iap = ifatoia(ifa);
1367*aca3beaaSApple OSS Distributions IFA_LOCK(&iap->ia_ifa);
1368*aca3beaaSApple OSS Distributions if (iap->ia_addr.sin_family == AF_INET) {
1369*aca3beaaSApple OSS Distributions ia = iap;
1370*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(&iap->ia_ifa);
1371*aca3beaaSApple OSS Distributions IFA_UNLOCK(&iap->ia_ifa);
1372*aca3beaaSApple OSS Distributions break;
1373*aca3beaaSApple OSS Distributions }
1374*aca3beaaSApple OSS Distributions IFA_UNLOCK(&iap->ia_ifa);
1375*aca3beaaSApple OSS Distributions }
1376*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
1377*aca3beaaSApple OSS Distributions }
1378*aca3beaaSApple OSS Distributions }
1379*aca3beaaSApple OSS Distributions
1380*aca3beaaSApple OSS Distributions /*
1381*aca3beaaSApple OSS Distributions * Unlock the socket since ifnet_ioctl() may be invoked by
1382*aca3beaaSApple OSS Distributions * one of the ioctl handlers below. Socket will be re-locked
1383*aca3beaaSApple OSS Distributions * prior to returning.
1384*aca3beaaSApple OSS Distributions */
1385*aca3beaaSApple OSS Distributions if (so != NULL) {
1386*aca3beaaSApple OSS Distributions socket_unlock(so, 0);
1387*aca3beaaSApple OSS Distributions so_unlocked = TRUE;
1388*aca3beaaSApple OSS Distributions }
1389*aca3beaaSApple OSS Distributions
1390*aca3beaaSApple OSS Distributions switch (cmd) {
1391*aca3beaaSApple OSS Distributions case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1392*aca3beaaSApple OSS Distributions case SIOCDIFADDR: /* struct ifreq */
1393*aca3beaaSApple OSS Distributions if (cmd == SIOCAIFADDR) {
1394*aca3beaaSApple OSS Distributions bcopy(&((struct in_aliasreq *)(void *)data)->
1395*aca3beaaSApple OSS Distributions ifra_addr, &addr, sizeof(addr));
1396*aca3beaaSApple OSS Distributions bcopy(&((struct in_aliasreq *)(void *)data)->
1397*aca3beaaSApple OSS Distributions ifra_dstaddr, &dstaddr, sizeof(dstaddr));
1398*aca3beaaSApple OSS Distributions } else {
1399*aca3beaaSApple OSS Distributions VERIFY(cmd == SIOCDIFADDR);
1400*aca3beaaSApple OSS Distributions bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
1401*aca3beaaSApple OSS Distributions &addr, sizeof(addr));
1402*aca3beaaSApple OSS Distributions bzero(&dstaddr, sizeof(dstaddr));
1403*aca3beaaSApple OSS Distributions }
1404*aca3beaaSApple OSS Distributions
1405*aca3beaaSApple OSS Distributions if (addr.sin_family == AF_INET) {
1406*aca3beaaSApple OSS Distributions struct in_ifaddr *oia;
1407*aca3beaaSApple OSS Distributions
1408*aca3beaaSApple OSS Distributions lck_rw_lock_shared(&in_ifaddr_rwlock);
1409*aca3beaaSApple OSS Distributions for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
1410*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1411*aca3beaaSApple OSS Distributions if (ia->ia_ifp == ifp &&
1412*aca3beaaSApple OSS Distributions ia->ia_addr.sin_addr.s_addr ==
1413*aca3beaaSApple OSS Distributions addr.sin_addr.s_addr) {
1414*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(&ia->ia_ifa);
1415*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1416*aca3beaaSApple OSS Distributions break;
1417*aca3beaaSApple OSS Distributions }
1418*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1419*aca3beaaSApple OSS Distributions }
1420*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
1421*aca3beaaSApple OSS Distributions if (oia != NULL) {
1422*aca3beaaSApple OSS Distributions IFA_REMREF(&oia->ia_ifa);
1423*aca3beaaSApple OSS Distributions }
1424*aca3beaaSApple OSS Distributions if ((ifp->if_flags & IFF_POINTOPOINT) &&
1425*aca3beaaSApple OSS Distributions (cmd == SIOCAIFADDR) &&
1426*aca3beaaSApple OSS Distributions (dstaddr.sin_addr.s_addr == INADDR_ANY)) {
1427*aca3beaaSApple OSS Distributions error = EDESTADDRREQ;
1428*aca3beaaSApple OSS Distributions goto done;
1429*aca3beaaSApple OSS Distributions }
1430*aca3beaaSApple OSS Distributions } else if (cmd == SIOCAIFADDR) {
1431*aca3beaaSApple OSS Distributions error = EINVAL;
1432*aca3beaaSApple OSS Distributions goto done;
1433*aca3beaaSApple OSS Distributions }
1434*aca3beaaSApple OSS Distributions if (cmd == SIOCDIFADDR) {
1435*aca3beaaSApple OSS Distributions if (ia == NULL) {
1436*aca3beaaSApple OSS Distributions error = EADDRNOTAVAIL;
1437*aca3beaaSApple OSS Distributions goto done;
1438*aca3beaaSApple OSS Distributions }
1439*aca3beaaSApple OSS Distributions
1440*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1441*aca3beaaSApple OSS Distributions /*
1442*aca3beaaSApple OSS Distributions * Avoid the race condition seen when two
1443*aca3beaaSApple OSS Distributions * threads process SIOCDIFADDR command
1444*aca3beaaSApple OSS Distributions * at the same time.
1445*aca3beaaSApple OSS Distributions */
1446*aca3beaaSApple OSS Distributions while (ia->ia_ifa.ifa_debug & IFD_DETACHING) {
1447*aca3beaaSApple OSS Distributions os_log(OS_LOG_DEFAULT,
1448*aca3beaaSApple OSS Distributions "Another thread is already attempting to "
1449*aca3beaaSApple OSS Distributions "delete IPv4 address: %s on interface %s. "
1450*aca3beaaSApple OSS Distributions "Go to sleep and check again after the operation is done",
1451*aca3beaaSApple OSS Distributions inet_ntoa(sa->sin_addr), ia->ia_ifp->if_xname);
1452*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_del_waiters++;
1453*aca3beaaSApple OSS Distributions (void) msleep(ia->ia_ifa.ifa_del_wc, &ia->ia_ifa.ifa_lock, (PZERO - 1),
1454*aca3beaaSApple OSS Distributions __func__, NULL);
1455*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1456*aca3beaaSApple OSS Distributions }
1457*aca3beaaSApple OSS Distributions
1458*aca3beaaSApple OSS Distributions if ((ia->ia_ifa.ifa_debug & IFD_ATTACHED) == 0) {
1459*aca3beaaSApple OSS Distributions error = EADDRNOTAVAIL;
1460*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1461*aca3beaaSApple OSS Distributions goto done;
1462*aca3beaaSApple OSS Distributions }
1463*aca3beaaSApple OSS Distributions
1464*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_debug |= IFD_DETACHING;
1465*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1466*aca3beaaSApple OSS Distributions }
1467*aca3beaaSApple OSS Distributions
1468*aca3beaaSApple OSS Distributions OS_FALLTHROUGH;
1469*aca3beaaSApple OSS Distributions case SIOCSIFADDR: /* struct ifreq */
1470*aca3beaaSApple OSS Distributions case SIOCSIFDSTADDR: /* struct ifreq */
1471*aca3beaaSApple OSS Distributions case SIOCSIFNETMASK: /* struct ifreq */
1472*aca3beaaSApple OSS Distributions if (cmd == SIOCAIFADDR) {
1473*aca3beaaSApple OSS Distributions /* fell thru from above; just repeat it */
1474*aca3beaaSApple OSS Distributions bcopy(&((struct in_aliasreq *)(void *)data)->
1475*aca3beaaSApple OSS Distributions ifra_addr, &addr, sizeof(addr));
1476*aca3beaaSApple OSS Distributions } else {
1477*aca3beaaSApple OSS Distributions VERIFY(cmd == SIOCDIFADDR || cmd == SIOCSIFADDR ||
1478*aca3beaaSApple OSS Distributions cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR);
1479*aca3beaaSApple OSS Distributions bcopy(&((struct ifreq *)(void *)data)->ifr_addr,
1480*aca3beaaSApple OSS Distributions &addr, sizeof(addr));
1481*aca3beaaSApple OSS Distributions }
1482*aca3beaaSApple OSS Distributions
1483*aca3beaaSApple OSS Distributions if (addr.sin_family != AF_INET && cmd == SIOCSIFADDR) {
1484*aca3beaaSApple OSS Distributions error = EINVAL;
1485*aca3beaaSApple OSS Distributions goto done;
1486*aca3beaaSApple OSS Distributions }
1487*aca3beaaSApple OSS Distributions
1488*aca3beaaSApple OSS Distributions if ((cmd == SIOCAIFADDR || cmd == SIOCSIFADDR) &&
1489*aca3beaaSApple OSS Distributions (IN_MULTICAST(ntohl(addr.sin_addr.s_addr)) ||
1490*aca3beaaSApple OSS Distributions addr.sin_addr.s_addr == INADDR_BROADCAST ||
1491*aca3beaaSApple OSS Distributions addr.sin_addr.s_addr == INADDR_ANY)) {
1492*aca3beaaSApple OSS Distributions error = EINVAL;
1493*aca3beaaSApple OSS Distributions goto done;
1494*aca3beaaSApple OSS Distributions }
1495*aca3beaaSApple OSS Distributions
1496*aca3beaaSApple OSS Distributions if (ia == NULL) {
1497*aca3beaaSApple OSS Distributions ia = in_ifaddr_alloc(Z_WAITOK);
1498*aca3beaaSApple OSS Distributions if (ia == NULL) {
1499*aca3beaaSApple OSS Distributions error = ENOBUFS;
1500*aca3beaaSApple OSS Distributions goto done;
1501*aca3beaaSApple OSS Distributions }
1502*aca3beaaSApple OSS Distributions ifnet_lock_exclusive(ifp);
1503*aca3beaaSApple OSS Distributions ifa = &ia->ia_ifa;
1504*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
1505*aca3beaaSApple OSS Distributions /* Hold a reference for this routine */
1506*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(ifa);
1507*aca3beaaSApple OSS Distributions IA_HASH_INIT(ia);
1508*aca3beaaSApple OSS Distributions ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
1509*aca3beaaSApple OSS Distributions ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
1510*aca3beaaSApple OSS Distributions ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
1511*aca3beaaSApple OSS Distributions ia->ia_sockmask.sin_len = offsetof(struct sockaddr_in, sin_zero);
1512*aca3beaaSApple OSS Distributions if (ifp->if_flags & IFF_BROADCAST) {
1513*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
1514*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_family = AF_INET;
1515*aca3beaaSApple OSS Distributions }
1516*aca3beaaSApple OSS Distributions ia->ia_ifp = ifp;
1517*aca3beaaSApple OSS Distributions if (!(ifp->if_flags & IFF_LOOPBACK)) {
1518*aca3beaaSApple OSS Distributions in_interfaces++;
1519*aca3beaaSApple OSS Distributions }
1520*aca3beaaSApple OSS Distributions /* if_attach_ifa() holds a reference for ifa_link */
1521*aca3beaaSApple OSS Distributions if_attach_ifa(ifp, ifa);
1522*aca3beaaSApple OSS Distributions /*
1523*aca3beaaSApple OSS Distributions * If we have to go through in_ifinit(), make sure
1524*aca3beaaSApple OSS Distributions * to avoid installing route(s) based on this address
1525*aca3beaaSApple OSS Distributions * via PFC_IFUP event, before the link resolver (ARP)
1526*aca3beaaSApple OSS Distributions * initializes it.
1527*aca3beaaSApple OSS Distributions */
1528*aca3beaaSApple OSS Distributions if (cmd == SIOCAIFADDR || cmd == SIOCSIFADDR) {
1529*aca3beaaSApple OSS Distributions ifa->ifa_debug |= IFD_NOTREADY;
1530*aca3beaaSApple OSS Distributions }
1531*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
1532*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
1533*aca3beaaSApple OSS Distributions lck_rw_lock_exclusive(&in_ifaddr_rwlock);
1534*aca3beaaSApple OSS Distributions /* Hold a reference for ia_link */
1535*aca3beaaSApple OSS Distributions IFA_ADDREF(ifa);
1536*aca3beaaSApple OSS Distributions TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
1537*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
1538*aca3beaaSApple OSS Distributions /* discard error */
1539*aca3beaaSApple OSS Distributions (void) in_domifattach(ifp);
1540*aca3beaaSApple OSS Distributions error = 0;
1541*aca3beaaSApple OSS Distributions }
1542*aca3beaaSApple OSS Distributions break;
1543*aca3beaaSApple OSS Distributions }
1544*aca3beaaSApple OSS Distributions
1545*aca3beaaSApple OSS Distributions switch (cmd) {
1546*aca3beaaSApple OSS Distributions case SIOCGIFDSTADDR: /* struct ifreq */
1547*aca3beaaSApple OSS Distributions case SIOCSIFDSTADDR: /* struct ifreq */
1548*aca3beaaSApple OSS Distributions error = inctl_ifdstaddr(ifp, ia, cmd, ifr);
1549*aca3beaaSApple OSS Distributions break;
1550*aca3beaaSApple OSS Distributions
1551*aca3beaaSApple OSS Distributions case SIOCGIFBRDADDR: /* struct ifreq */
1552*aca3beaaSApple OSS Distributions case SIOCSIFBRDADDR: /* struct ifreq */
1553*aca3beaaSApple OSS Distributions error = inctl_ifbrdaddr(ifp, ia, cmd, ifr);
1554*aca3beaaSApple OSS Distributions break;
1555*aca3beaaSApple OSS Distributions
1556*aca3beaaSApple OSS Distributions case SIOCGIFNETMASK: /* struct ifreq */
1557*aca3beaaSApple OSS Distributions case SIOCSIFNETMASK: /* struct ifreq */
1558*aca3beaaSApple OSS Distributions error = inctl_ifnetmask(ifp, ia, cmd, ifr);
1559*aca3beaaSApple OSS Distributions break;
1560*aca3beaaSApple OSS Distributions
1561*aca3beaaSApple OSS Distributions case SIOCGIFADDR: /* struct ifreq */
1562*aca3beaaSApple OSS Distributions case SIOCSIFADDR: /* struct ifreq */
1563*aca3beaaSApple OSS Distributions case SIOCAIFADDR: /* struct {if,in_}aliasreq */
1564*aca3beaaSApple OSS Distributions case SIOCDIFADDR: /* struct ifreq */
1565*aca3beaaSApple OSS Distributions error = inctl_ifaddr(ifp, ia, cmd, ifr);
1566*aca3beaaSApple OSS Distributions break;
1567*aca3beaaSApple OSS Distributions
1568*aca3beaaSApple OSS Distributions default:
1569*aca3beaaSApple OSS Distributions error = EOPNOTSUPP;
1570*aca3beaaSApple OSS Distributions break;
1571*aca3beaaSApple OSS Distributions }
1572*aca3beaaSApple OSS Distributions
1573*aca3beaaSApple OSS Distributions done:
1574*aca3beaaSApple OSS Distributions if (ia != NULL) {
1575*aca3beaaSApple OSS Distributions if (cmd == SIOCDIFADDR) {
1576*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1577*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_debug &= ~IFD_DETACHING;
1578*aca3beaaSApple OSS Distributions if (ia->ia_ifa.ifa_del_waiters > 0) {
1579*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_del_waiters = 0;
1580*aca3beaaSApple OSS Distributions wakeup(ia->ia_ifa.ifa_del_wc);
1581*aca3beaaSApple OSS Distributions }
1582*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1583*aca3beaaSApple OSS Distributions }
1584*aca3beaaSApple OSS Distributions IFA_REMREF(&ia->ia_ifa);
1585*aca3beaaSApple OSS Distributions }
1586*aca3beaaSApple OSS Distributions if (so_unlocked) {
1587*aca3beaaSApple OSS Distributions socket_lock(so, 0);
1588*aca3beaaSApple OSS Distributions }
1589*aca3beaaSApple OSS Distributions
1590*aca3beaaSApple OSS Distributions return error;
1591*aca3beaaSApple OSS Distributions }
1592*aca3beaaSApple OSS Distributions
1593*aca3beaaSApple OSS Distributions /*
1594*aca3beaaSApple OSS Distributions * Delete any existing route for an interface.
1595*aca3beaaSApple OSS Distributions */
1596*aca3beaaSApple OSS Distributions void
in_ifscrub(struct ifnet * ifp,struct in_ifaddr * ia,int locked)1597*aca3beaaSApple OSS Distributions in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, int locked)
1598*aca3beaaSApple OSS Distributions {
1599*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1600*aca3beaaSApple OSS Distributions if ((ia->ia_flags & IFA_ROUTE) == 0) {
1601*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1602*aca3beaaSApple OSS Distributions return;
1603*aca3beaaSApple OSS Distributions }
1604*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1605*aca3beaaSApple OSS Distributions if (!locked) {
1606*aca3beaaSApple OSS Distributions lck_mtx_lock(rnh_lock);
1607*aca3beaaSApple OSS Distributions }
1608*aca3beaaSApple OSS Distributions if (ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) {
1609*aca3beaaSApple OSS Distributions rtinit_locked(&(ia->ia_ifa), RTM_DELETE, RTF_HOST);
1610*aca3beaaSApple OSS Distributions } else {
1611*aca3beaaSApple OSS Distributions rtinit_locked(&(ia->ia_ifa), RTM_DELETE, 0);
1612*aca3beaaSApple OSS Distributions }
1613*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1614*aca3beaaSApple OSS Distributions ia->ia_flags &= ~IFA_ROUTE;
1615*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1616*aca3beaaSApple OSS Distributions if (!locked) {
1617*aca3beaaSApple OSS Distributions lck_mtx_unlock(rnh_lock);
1618*aca3beaaSApple OSS Distributions }
1619*aca3beaaSApple OSS Distributions }
1620*aca3beaaSApple OSS Distributions
1621*aca3beaaSApple OSS Distributions /*
1622*aca3beaaSApple OSS Distributions * Caller must hold in_ifaddr_rwlock as writer.
1623*aca3beaaSApple OSS Distributions */
1624*aca3beaaSApple OSS Distributions static void
in_iahash_remove(struct in_ifaddr * ia)1625*aca3beaaSApple OSS Distributions in_iahash_remove(struct in_ifaddr *ia)
1626*aca3beaaSApple OSS Distributions {
1627*aca3beaaSApple OSS Distributions LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1628*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1629*aca3beaaSApple OSS Distributions
1630*aca3beaaSApple OSS Distributions if (!IA_IS_HASHED(ia)) {
1631*aca3beaaSApple OSS Distributions panic("attempt to remove wrong ia %p from hash table", ia);
1632*aca3beaaSApple OSS Distributions /* NOTREACHED */
1633*aca3beaaSApple OSS Distributions }
1634*aca3beaaSApple OSS Distributions TAILQ_REMOVE(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
1635*aca3beaaSApple OSS Distributions IA_HASH_INIT(ia);
1636*aca3beaaSApple OSS Distributions if (IFA_REMREF_LOCKED(&ia->ia_ifa) == NULL) {
1637*aca3beaaSApple OSS Distributions panic("%s: unexpected (missing) refcnt ifa=%p", __func__,
1638*aca3beaaSApple OSS Distributions &ia->ia_ifa);
1639*aca3beaaSApple OSS Distributions /* NOTREACHED */
1640*aca3beaaSApple OSS Distributions }
1641*aca3beaaSApple OSS Distributions }
1642*aca3beaaSApple OSS Distributions
1643*aca3beaaSApple OSS Distributions /*
1644*aca3beaaSApple OSS Distributions * Caller must hold in_ifaddr_rwlock as writer.
1645*aca3beaaSApple OSS Distributions */
1646*aca3beaaSApple OSS Distributions static void
in_iahash_insert(struct in_ifaddr * ia)1647*aca3beaaSApple OSS Distributions in_iahash_insert(struct in_ifaddr *ia)
1648*aca3beaaSApple OSS Distributions {
1649*aca3beaaSApple OSS Distributions LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1650*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1651*aca3beaaSApple OSS Distributions
1652*aca3beaaSApple OSS Distributions if (ia->ia_addr.sin_family != AF_INET) {
1653*aca3beaaSApple OSS Distributions panic("attempt to insert wrong ia %p into hash table", ia);
1654*aca3beaaSApple OSS Distributions /* NOTREACHED */
1655*aca3beaaSApple OSS Distributions } else if (IA_IS_HASHED(ia)) {
1656*aca3beaaSApple OSS Distributions panic("attempt to double-insert ia %p into hash table", ia);
1657*aca3beaaSApple OSS Distributions /* NOTREACHED */
1658*aca3beaaSApple OSS Distributions }
1659*aca3beaaSApple OSS Distributions TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1660*aca3beaaSApple OSS Distributions ia, ia_hash);
1661*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(&ia->ia_ifa);
1662*aca3beaaSApple OSS Distributions }
1663*aca3beaaSApple OSS Distributions
1664*aca3beaaSApple OSS Distributions /*
1665*aca3beaaSApple OSS Distributions * Some point to point interfaces that are tunnels borrow the address from
1666*aca3beaaSApple OSS Distributions * an underlying interface (e.g. VPN server). In order for source address
1667*aca3beaaSApple OSS Distributions * selection logic to find the underlying interface first, we add the address
1668*aca3beaaSApple OSS Distributions * of borrowing point to point interfaces at the end of the list.
1669*aca3beaaSApple OSS Distributions * (see rdar://6733789)
1670*aca3beaaSApple OSS Distributions *
1671*aca3beaaSApple OSS Distributions * Caller must hold in_ifaddr_rwlock as writer.
1672*aca3beaaSApple OSS Distributions */
1673*aca3beaaSApple OSS Distributions static void
in_iahash_insert_ptp(struct in_ifaddr * ia)1674*aca3beaaSApple OSS Distributions in_iahash_insert_ptp(struct in_ifaddr *ia)
1675*aca3beaaSApple OSS Distributions {
1676*aca3beaaSApple OSS Distributions struct in_ifaddr *tmp_ifa;
1677*aca3beaaSApple OSS Distributions struct ifnet *tmp_ifp;
1678*aca3beaaSApple OSS Distributions
1679*aca3beaaSApple OSS Distributions LCK_RW_ASSERT(&in_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
1680*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1681*aca3beaaSApple OSS Distributions
1682*aca3beaaSApple OSS Distributions if (ia->ia_addr.sin_family != AF_INET) {
1683*aca3beaaSApple OSS Distributions panic("attempt to insert wrong ia %p into hash table", ia);
1684*aca3beaaSApple OSS Distributions /* NOTREACHED */
1685*aca3beaaSApple OSS Distributions } else if (IA_IS_HASHED(ia)) {
1686*aca3beaaSApple OSS Distributions panic("attempt to double-insert ia %p into hash table", ia);
1687*aca3beaaSApple OSS Distributions /* NOTREACHED */
1688*aca3beaaSApple OSS Distributions }
1689*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1690*aca3beaaSApple OSS Distributions TAILQ_FOREACH(tmp_ifa, INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1691*aca3beaaSApple OSS Distributions ia_hash) {
1692*aca3beaaSApple OSS Distributions IFA_LOCK(&tmp_ifa->ia_ifa);
1693*aca3beaaSApple OSS Distributions /* ia->ia_addr won't change, so check without lock */
1694*aca3beaaSApple OSS Distributions if (IA_SIN(tmp_ifa)->sin_addr.s_addr ==
1695*aca3beaaSApple OSS Distributions ia->ia_addr.sin_addr.s_addr) {
1696*aca3beaaSApple OSS Distributions IFA_UNLOCK(&tmp_ifa->ia_ifa);
1697*aca3beaaSApple OSS Distributions break;
1698*aca3beaaSApple OSS Distributions }
1699*aca3beaaSApple OSS Distributions IFA_UNLOCK(&tmp_ifa->ia_ifa);
1700*aca3beaaSApple OSS Distributions }
1701*aca3beaaSApple OSS Distributions tmp_ifp = (tmp_ifa == NULL) ? NULL : tmp_ifa->ia_ifp;
1702*aca3beaaSApple OSS Distributions
1703*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1704*aca3beaaSApple OSS Distributions if (tmp_ifp == NULL) {
1705*aca3beaaSApple OSS Distributions TAILQ_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1706*aca3beaaSApple OSS Distributions ia, ia_hash);
1707*aca3beaaSApple OSS Distributions } else {
1708*aca3beaaSApple OSS Distributions TAILQ_INSERT_TAIL(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
1709*aca3beaaSApple OSS Distributions ia, ia_hash);
1710*aca3beaaSApple OSS Distributions }
1711*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(&ia->ia_ifa);
1712*aca3beaaSApple OSS Distributions }
1713*aca3beaaSApple OSS Distributions
1714*aca3beaaSApple OSS Distributions /*
1715*aca3beaaSApple OSS Distributions * Initialize an interface's internet address
1716*aca3beaaSApple OSS Distributions * and routing table entry.
1717*aca3beaaSApple OSS Distributions */
1718*aca3beaaSApple OSS Distributions static int
in_ifinit(struct ifnet * ifp,struct in_ifaddr * ia,struct sockaddr_in * sin,int scrub)1719*aca3beaaSApple OSS Distributions in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
1720*aca3beaaSApple OSS Distributions int scrub)
1721*aca3beaaSApple OSS Distributions {
1722*aca3beaaSApple OSS Distributions u_int32_t i = ntohl(sin->sin_addr.s_addr);
1723*aca3beaaSApple OSS Distributions struct sockaddr_in oldaddr;
1724*aca3beaaSApple OSS Distributions int flags = RTF_UP, error;
1725*aca3beaaSApple OSS Distributions struct ifaddr *ifa0;
1726*aca3beaaSApple OSS Distributions unsigned int cmd;
1727*aca3beaaSApple OSS Distributions int oldremoved = 0;
1728*aca3beaaSApple OSS Distributions
1729*aca3beaaSApple OSS Distributions /* Take an extra reference for this routine */
1730*aca3beaaSApple OSS Distributions IFA_ADDREF(&ia->ia_ifa);
1731*aca3beaaSApple OSS Distributions
1732*aca3beaaSApple OSS Distributions lck_rw_lock_exclusive(&in_ifaddr_rwlock);
1733*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1734*aca3beaaSApple OSS Distributions oldaddr = ia->ia_addr;
1735*aca3beaaSApple OSS Distributions if (IA_IS_HASHED(ia)) {
1736*aca3beaaSApple OSS Distributions oldremoved = 1;
1737*aca3beaaSApple OSS Distributions in_iahash_remove(ia);
1738*aca3beaaSApple OSS Distributions }
1739*aca3beaaSApple OSS Distributions ia->ia_addr = *sin;
1740*aca3beaaSApple OSS Distributions /*
1741*aca3beaaSApple OSS Distributions * Interface addresses should not contain port or sin_zero information.
1742*aca3beaaSApple OSS Distributions */
1743*aca3beaaSApple OSS Distributions SIN(&ia->ia_addr)->sin_family = AF_INET;
1744*aca3beaaSApple OSS Distributions SIN(&ia->ia_addr)->sin_len = sizeof(struct sockaddr_in);
1745*aca3beaaSApple OSS Distributions SIN(&ia->ia_addr)->sin_port = 0;
1746*aca3beaaSApple OSS Distributions bzero(&SIN(&ia->ia_addr)->sin_zero, sizeof(sin->sin_zero));
1747*aca3beaaSApple OSS Distributions if ((ifp->if_flags & IFF_POINTOPOINT)) {
1748*aca3beaaSApple OSS Distributions in_iahash_insert_ptp(ia);
1749*aca3beaaSApple OSS Distributions } else {
1750*aca3beaaSApple OSS Distributions in_iahash_insert(ia);
1751*aca3beaaSApple OSS Distributions }
1752*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1753*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
1754*aca3beaaSApple OSS Distributions
1755*aca3beaaSApple OSS Distributions /*
1756*aca3beaaSApple OSS Distributions * Give the interface a chance to initialize if this is its first
1757*aca3beaaSApple OSS Distributions * address, and to validate the address if necessary. Send down
1758*aca3beaaSApple OSS Distributions * SIOCSIFADDR for first address, and SIOCAIFADDR for alias(es).
1759*aca3beaaSApple OSS Distributions * We find the first IPV4 address assigned to it and check if this
1760*aca3beaaSApple OSS Distributions * is the same as the one passed into this routine.
1761*aca3beaaSApple OSS Distributions */
1762*aca3beaaSApple OSS Distributions ifa0 = ifa_ifpgetprimary(ifp, AF_INET);
1763*aca3beaaSApple OSS Distributions cmd = (&ia->ia_ifa == ifa0) ? SIOCSIFADDR : SIOCAIFADDR;
1764*aca3beaaSApple OSS Distributions error = ifnet_ioctl(ifp, PF_INET, cmd, ia);
1765*aca3beaaSApple OSS Distributions if (error == EOPNOTSUPP) {
1766*aca3beaaSApple OSS Distributions error = 0;
1767*aca3beaaSApple OSS Distributions }
1768*aca3beaaSApple OSS Distributions /*
1769*aca3beaaSApple OSS Distributions * If we've just sent down SIOCAIFADDR, send another ioctl down
1770*aca3beaaSApple OSS Distributions * for SIOCSIFADDR for the first IPV4 address of the interface,
1771*aca3beaaSApple OSS Distributions * because an address change on one of the addresses will result
1772*aca3beaaSApple OSS Distributions * in the removal of the previous first IPV4 address. KDP needs
1773*aca3beaaSApple OSS Distributions * be reconfigured with the current primary IPV4 address.
1774*aca3beaaSApple OSS Distributions */
1775*aca3beaaSApple OSS Distributions if (error == 0 && cmd == SIOCAIFADDR) {
1776*aca3beaaSApple OSS Distributions /*
1777*aca3beaaSApple OSS Distributions * NOTE: SIOCSIFADDR is defined with struct ifreq
1778*aca3beaaSApple OSS Distributions * as parameter, but here we are sending it down
1779*aca3beaaSApple OSS Distributions * to the interface with a pointer to struct ifaddr,
1780*aca3beaaSApple OSS Distributions * for legacy reasons.
1781*aca3beaaSApple OSS Distributions */
1782*aca3beaaSApple OSS Distributions error = ifnet_ioctl(ifp, PF_INET, SIOCSIFADDR, ifa0);
1783*aca3beaaSApple OSS Distributions if (error == EOPNOTSUPP) {
1784*aca3beaaSApple OSS Distributions error = 0;
1785*aca3beaaSApple OSS Distributions }
1786*aca3beaaSApple OSS Distributions }
1787*aca3beaaSApple OSS Distributions
1788*aca3beaaSApple OSS Distributions /* Release reference from ifa_ifpgetprimary() */
1789*aca3beaaSApple OSS Distributions IFA_REMREF(ifa0);
1790*aca3beaaSApple OSS Distributions
1791*aca3beaaSApple OSS Distributions if (error) {
1792*aca3beaaSApple OSS Distributions lck_rw_lock_exclusive(&in_ifaddr_rwlock);
1793*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1794*aca3beaaSApple OSS Distributions if (IA_IS_HASHED(ia)) {
1795*aca3beaaSApple OSS Distributions in_iahash_remove(ia);
1796*aca3beaaSApple OSS Distributions }
1797*aca3beaaSApple OSS Distributions ia->ia_addr = oldaddr;
1798*aca3beaaSApple OSS Distributions if (oldremoved) {
1799*aca3beaaSApple OSS Distributions if ((ifp->if_flags & IFF_POINTOPOINT)) {
1800*aca3beaaSApple OSS Distributions in_iahash_insert_ptp(ia);
1801*aca3beaaSApple OSS Distributions } else {
1802*aca3beaaSApple OSS Distributions in_iahash_insert(ia);
1803*aca3beaaSApple OSS Distributions }
1804*aca3beaaSApple OSS Distributions }
1805*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1806*aca3beaaSApple OSS Distributions lck_rw_done(&in_ifaddr_rwlock);
1807*aca3beaaSApple OSS Distributions /* Release extra reference taken above */
1808*aca3beaaSApple OSS Distributions IFA_REMREF(&ia->ia_ifa);
1809*aca3beaaSApple OSS Distributions return error;
1810*aca3beaaSApple OSS Distributions }
1811*aca3beaaSApple OSS Distributions lck_mtx_lock(rnh_lock);
1812*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1813*aca3beaaSApple OSS Distributions /*
1814*aca3beaaSApple OSS Distributions * Address has been initialized by the link resolver (ARP)
1815*aca3beaaSApple OSS Distributions * via ifnet_ioctl() above; it may now generate route(s).
1816*aca3beaaSApple OSS Distributions */
1817*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_debug &= ~IFD_NOTREADY;
1818*aca3beaaSApple OSS Distributions if (scrub) {
1819*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
1820*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1821*aca3beaaSApple OSS Distributions in_ifscrub(ifp, ia, 1);
1822*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1823*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1824*aca3beaaSApple OSS Distributions }
1825*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
1826*aca3beaaSApple OSS Distributions if (IN_CLASSA(i)) {
1827*aca3beaaSApple OSS Distributions ia->ia_netmask = IN_CLASSA_NET;
1828*aca3beaaSApple OSS Distributions } else if (IN_CLASSB(i)) {
1829*aca3beaaSApple OSS Distributions ia->ia_netmask = IN_CLASSB_NET;
1830*aca3beaaSApple OSS Distributions } else {
1831*aca3beaaSApple OSS Distributions ia->ia_netmask = IN_CLASSC_NET;
1832*aca3beaaSApple OSS Distributions }
1833*aca3beaaSApple OSS Distributions /*
1834*aca3beaaSApple OSS Distributions * The subnet mask usually includes at least the standard network part,
1835*aca3beaaSApple OSS Distributions * but may may be smaller in the case of supernetting.
1836*aca3beaaSApple OSS Distributions * If it is set, we believe it.
1837*aca3beaaSApple OSS Distributions */
1838*aca3beaaSApple OSS Distributions if (ia->ia_subnetmask == 0) {
1839*aca3beaaSApple OSS Distributions ia->ia_subnetmask = ia->ia_netmask;
1840*aca3beaaSApple OSS Distributions ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
1841*aca3beaaSApple OSS Distributions } else {
1842*aca3beaaSApple OSS Distributions ia->ia_netmask &= ia->ia_subnetmask;
1843*aca3beaaSApple OSS Distributions }
1844*aca3beaaSApple OSS Distributions ia->ia_net = i & ia->ia_netmask;
1845*aca3beaaSApple OSS Distributions ia->ia_subnet = i & ia->ia_subnetmask;
1846*aca3beaaSApple OSS Distributions in_socktrim(&ia->ia_sockmask);
1847*aca3beaaSApple OSS Distributions /*
1848*aca3beaaSApple OSS Distributions * Add route for the network.
1849*aca3beaaSApple OSS Distributions */
1850*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_metric = ifp->if_metric;
1851*aca3beaaSApple OSS Distributions if (ifp->if_flags & IFF_BROADCAST) {
1852*aca3beaaSApple OSS Distributions ia->ia_broadaddr.sin_addr.s_addr =
1853*aca3beaaSApple OSS Distributions htonl(ia->ia_subnet | ~ia->ia_subnetmask);
1854*aca3beaaSApple OSS Distributions ia->ia_netbroadcast.s_addr =
1855*aca3beaaSApple OSS Distributions htonl(ia->ia_net | ~ia->ia_netmask);
1856*aca3beaaSApple OSS Distributions } else if (ifp->if_flags & IFF_LOOPBACK) {
1857*aca3beaaSApple OSS Distributions ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1858*aca3beaaSApple OSS Distributions flags |= RTF_HOST;
1859*aca3beaaSApple OSS Distributions } else if (ifp->if_flags & IFF_POINTOPOINT) {
1860*aca3beaaSApple OSS Distributions if (ia->ia_dstaddr.sin_family != AF_INET) {
1861*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1862*aca3beaaSApple OSS Distributions lck_mtx_unlock(rnh_lock);
1863*aca3beaaSApple OSS Distributions /* Release extra reference taken above */
1864*aca3beaaSApple OSS Distributions IFA_REMREF(&ia->ia_ifa);
1865*aca3beaaSApple OSS Distributions return 0;
1866*aca3beaaSApple OSS Distributions }
1867*aca3beaaSApple OSS Distributions ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
1868*aca3beaaSApple OSS Distributions flags |= RTF_HOST;
1869*aca3beaaSApple OSS Distributions }
1870*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1871*aca3beaaSApple OSS Distributions
1872*aca3beaaSApple OSS Distributions if ((error = rtinit_locked(&(ia->ia_ifa), RTM_ADD, flags)) == 0) {
1873*aca3beaaSApple OSS Distributions IFA_LOCK(&ia->ia_ifa);
1874*aca3beaaSApple OSS Distributions ia->ia_flags |= IFA_ROUTE;
1875*aca3beaaSApple OSS Distributions IFA_UNLOCK(&ia->ia_ifa);
1876*aca3beaaSApple OSS Distributions }
1877*aca3beaaSApple OSS Distributions lck_mtx_unlock(rnh_lock);
1878*aca3beaaSApple OSS Distributions
1879*aca3beaaSApple OSS Distributions /* XXX check if the subnet route points to the same interface */
1880*aca3beaaSApple OSS Distributions if (error == EEXIST) {
1881*aca3beaaSApple OSS Distributions error = 0;
1882*aca3beaaSApple OSS Distributions }
1883*aca3beaaSApple OSS Distributions
1884*aca3beaaSApple OSS Distributions /*
1885*aca3beaaSApple OSS Distributions * If the interface supports multicast, join the "all hosts"
1886*aca3beaaSApple OSS Distributions * multicast group on that interface.
1887*aca3beaaSApple OSS Distributions */
1888*aca3beaaSApple OSS Distributions if (ifp->if_flags & IFF_MULTICAST) {
1889*aca3beaaSApple OSS Distributions struct in_addr addr;
1890*aca3beaaSApple OSS Distributions
1891*aca3beaaSApple OSS Distributions lck_mtx_lock(&ifp->if_addrconfig_lock);
1892*aca3beaaSApple OSS Distributions addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
1893*aca3beaaSApple OSS Distributions if (ifp->if_allhostsinm == NULL) {
1894*aca3beaaSApple OSS Distributions struct in_multi *inm;
1895*aca3beaaSApple OSS Distributions inm = in_addmulti(&addr, ifp);
1896*aca3beaaSApple OSS Distributions
1897*aca3beaaSApple OSS Distributions if (inm != NULL) {
1898*aca3beaaSApple OSS Distributions /*
1899*aca3beaaSApple OSS Distributions * Keep the reference on inm added by
1900*aca3beaaSApple OSS Distributions * in_addmulti above for storing the
1901*aca3beaaSApple OSS Distributions * pointer in allhostsinm.
1902*aca3beaaSApple OSS Distributions */
1903*aca3beaaSApple OSS Distributions ifp->if_allhostsinm = inm;
1904*aca3beaaSApple OSS Distributions } else {
1905*aca3beaaSApple OSS Distributions printf("%s: failed to add membership to "
1906*aca3beaaSApple OSS Distributions "all-hosts multicast address on %s\n",
1907*aca3beaaSApple OSS Distributions __func__, if_name(ifp));
1908*aca3beaaSApple OSS Distributions }
1909*aca3beaaSApple OSS Distributions }
1910*aca3beaaSApple OSS Distributions lck_mtx_unlock(&ifp->if_addrconfig_lock);
1911*aca3beaaSApple OSS Distributions }
1912*aca3beaaSApple OSS Distributions
1913*aca3beaaSApple OSS Distributions /* Release extra reference taken above */
1914*aca3beaaSApple OSS Distributions IFA_REMREF(&ia->ia_ifa);
1915*aca3beaaSApple OSS Distributions
1916*aca3beaaSApple OSS Distributions if (error == 0) {
1917*aca3beaaSApple OSS Distributions /* invalidate route caches */
1918*aca3beaaSApple OSS Distributions routegenid_inet_update();
1919*aca3beaaSApple OSS Distributions }
1920*aca3beaaSApple OSS Distributions
1921*aca3beaaSApple OSS Distributions return error;
1922*aca3beaaSApple OSS Distributions }
1923*aca3beaaSApple OSS Distributions
1924*aca3beaaSApple OSS Distributions /*
1925*aca3beaaSApple OSS Distributions * Return TRUE if the address might be a local broadcast address.
1926*aca3beaaSApple OSS Distributions */
1927*aca3beaaSApple OSS Distributions boolean_t
in_broadcast(struct in_addr in,struct ifnet * ifp)1928*aca3beaaSApple OSS Distributions in_broadcast(struct in_addr in, struct ifnet *ifp)
1929*aca3beaaSApple OSS Distributions {
1930*aca3beaaSApple OSS Distributions struct ifaddr *ifa;
1931*aca3beaaSApple OSS Distributions u_int32_t t;
1932*aca3beaaSApple OSS Distributions
1933*aca3beaaSApple OSS Distributions if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) {
1934*aca3beaaSApple OSS Distributions return TRUE;
1935*aca3beaaSApple OSS Distributions }
1936*aca3beaaSApple OSS Distributions if (!(ifp->if_flags & IFF_BROADCAST)) {
1937*aca3beaaSApple OSS Distributions return FALSE;
1938*aca3beaaSApple OSS Distributions }
1939*aca3beaaSApple OSS Distributions t = ntohl(in.s_addr);
1940*aca3beaaSApple OSS Distributions
1941*aca3beaaSApple OSS Distributions /*
1942*aca3beaaSApple OSS Distributions * Look through the list of addresses for a match
1943*aca3beaaSApple OSS Distributions * with a broadcast address.
1944*aca3beaaSApple OSS Distributions */
1945*aca3beaaSApple OSS Distributions #define ia ((struct in_ifaddr *)ifa)
1946*aca3beaaSApple OSS Distributions ifnet_lock_shared(ifp);
1947*aca3beaaSApple OSS Distributions TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1948*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
1949*aca3beaaSApple OSS Distributions if (ifa->ifa_addr->sa_family == AF_INET &&
1950*aca3beaaSApple OSS Distributions (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
1951*aca3beaaSApple OSS Distributions in.s_addr == ia->ia_netbroadcast.s_addr ||
1952*aca3beaaSApple OSS Distributions /*
1953*aca3beaaSApple OSS Distributions * Check for old-style (host 0) broadcast.
1954*aca3beaaSApple OSS Distributions */
1955*aca3beaaSApple OSS Distributions t == ia->ia_subnet || t == ia->ia_net) &&
1956*aca3beaaSApple OSS Distributions /*
1957*aca3beaaSApple OSS Distributions * Check for an all one subnetmask. These
1958*aca3beaaSApple OSS Distributions * only exist when an interface gets a secondary
1959*aca3beaaSApple OSS Distributions * address.
1960*aca3beaaSApple OSS Distributions */
1961*aca3beaaSApple OSS Distributions ia->ia_subnetmask != (u_int32_t)0xffffffff) {
1962*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
1963*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
1964*aca3beaaSApple OSS Distributions return TRUE;
1965*aca3beaaSApple OSS Distributions }
1966*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
1967*aca3beaaSApple OSS Distributions }
1968*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
1969*aca3beaaSApple OSS Distributions return FALSE;
1970*aca3beaaSApple OSS Distributions #undef ia
1971*aca3beaaSApple OSS Distributions }
1972*aca3beaaSApple OSS Distributions
1973*aca3beaaSApple OSS Distributions void
in_purgeaddrs(struct ifnet * ifp)1974*aca3beaaSApple OSS Distributions in_purgeaddrs(struct ifnet *ifp)
1975*aca3beaaSApple OSS Distributions {
1976*aca3beaaSApple OSS Distributions struct ifaddr **ifap;
1977*aca3beaaSApple OSS Distributions int err, i;
1978*aca3beaaSApple OSS Distributions
1979*aca3beaaSApple OSS Distributions VERIFY(ifp != NULL);
1980*aca3beaaSApple OSS Distributions
1981*aca3beaaSApple OSS Distributions /*
1982*aca3beaaSApple OSS Distributions * Be nice, and try the civilized way first. If we can't get
1983*aca3beaaSApple OSS Distributions * rid of them this way, then do it the rough way. We must
1984*aca3beaaSApple OSS Distributions * only get here during detach time, after the ifnet has been
1985*aca3beaaSApple OSS Distributions * removed from the global list and arrays.
1986*aca3beaaSApple OSS Distributions */
1987*aca3beaaSApple OSS Distributions err = ifnet_get_address_list_family_internal(ifp, &ifap, AF_INET, 1,
1988*aca3beaaSApple OSS Distributions M_WAITOK, 0);
1989*aca3beaaSApple OSS Distributions if (err == 0 && ifap != NULL) {
1990*aca3beaaSApple OSS Distributions struct ifreq ifr;
1991*aca3beaaSApple OSS Distributions
1992*aca3beaaSApple OSS Distributions bzero(&ifr, sizeof(ifr));
1993*aca3beaaSApple OSS Distributions (void) snprintf(ifr.ifr_name, sizeof(ifr.ifr_name),
1994*aca3beaaSApple OSS Distributions "%s", if_name(ifp));
1995*aca3beaaSApple OSS Distributions
1996*aca3beaaSApple OSS Distributions for (i = 0; ifap[i] != NULL; i++) {
1997*aca3beaaSApple OSS Distributions struct ifaddr *ifa;
1998*aca3beaaSApple OSS Distributions
1999*aca3beaaSApple OSS Distributions ifa = ifap[i];
2000*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
2001*aca3beaaSApple OSS Distributions bcopy(ifa->ifa_addr, &ifr.ifr_addr,
2002*aca3beaaSApple OSS Distributions sizeof(struct sockaddr_in));
2003*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2004*aca3beaaSApple OSS Distributions err = in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
2005*aca3beaaSApple OSS Distributions kernproc);
2006*aca3beaaSApple OSS Distributions /* if we lost the race, ignore it */
2007*aca3beaaSApple OSS Distributions if (err == EADDRNOTAVAIL) {
2008*aca3beaaSApple OSS Distributions err = 0;
2009*aca3beaaSApple OSS Distributions }
2010*aca3beaaSApple OSS Distributions if (err != 0) {
2011*aca3beaaSApple OSS Distributions char s_addr[MAX_IPv4_STR_LEN];
2012*aca3beaaSApple OSS Distributions char s_dstaddr[MAX_IPv4_STR_LEN];
2013*aca3beaaSApple OSS Distributions struct in_addr *s, *d;
2014*aca3beaaSApple OSS Distributions
2015*aca3beaaSApple OSS Distributions IFA_LOCK(ifa);
2016*aca3beaaSApple OSS Distributions s = &((struct sockaddr_in *)
2017*aca3beaaSApple OSS Distributions (void *)ifa->ifa_addr)->sin_addr;
2018*aca3beaaSApple OSS Distributions d = &((struct sockaddr_in *)
2019*aca3beaaSApple OSS Distributions (void *)ifa->ifa_dstaddr)->sin_addr;
2020*aca3beaaSApple OSS Distributions (void) inet_ntop(AF_INET, &s->s_addr, s_addr,
2021*aca3beaaSApple OSS Distributions sizeof(s_addr));
2022*aca3beaaSApple OSS Distributions (void) inet_ntop(AF_INET, &d->s_addr, s_dstaddr,
2023*aca3beaaSApple OSS Distributions sizeof(s_dstaddr));
2024*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2025*aca3beaaSApple OSS Distributions
2026*aca3beaaSApple OSS Distributions printf("%s: SIOCDIFADDR ifp=%s ifa_addr=%s "
2027*aca3beaaSApple OSS Distributions "ifa_dstaddr=%s (err=%d)\n", __func__,
2028*aca3beaaSApple OSS Distributions ifp->if_xname, s_addr, s_dstaddr, err);
2029*aca3beaaSApple OSS Distributions }
2030*aca3beaaSApple OSS Distributions }
2031*aca3beaaSApple OSS Distributions ifnet_free_address_list(ifap);
2032*aca3beaaSApple OSS Distributions } else if (err != 0 && err != ENXIO) {
2033*aca3beaaSApple OSS Distributions printf("%s: error retrieving list of AF_INET addresses for "
2034*aca3beaaSApple OSS Distributions "ifp=%s (err=%d)\n", __func__, ifp->if_xname, err);
2035*aca3beaaSApple OSS Distributions }
2036*aca3beaaSApple OSS Distributions }
2037*aca3beaaSApple OSS Distributions
2038*aca3beaaSApple OSS Distributions /*
2039*aca3beaaSApple OSS Distributions * Called as part of ip_init
2040*aca3beaaSApple OSS Distributions */
2041*aca3beaaSApple OSS Distributions void
in_ifaddr_init(void)2042*aca3beaaSApple OSS Distributions in_ifaddr_init(void)
2043*aca3beaaSApple OSS Distributions {
2044*aca3beaaSApple OSS Distributions size_t inifa_size = (inifa_debug == 0) ? sizeof(struct in_ifaddr) :
2045*aca3beaaSApple OSS Distributions sizeof(struct in_ifaddr_dbg);
2046*aca3beaaSApple OSS Distributions
2047*aca3beaaSApple OSS Distributions in_multi_init();
2048*aca3beaaSApple OSS Distributions
2049*aca3beaaSApple OSS Distributions inifa_zone = zone_create(INIFA_ZONE_NAME, inifa_size, ZC_NONE);
2050*aca3beaaSApple OSS Distributions
2051*aca3beaaSApple OSS Distributions TAILQ_INIT(&inifa_trash_head);
2052*aca3beaaSApple OSS Distributions }
2053*aca3beaaSApple OSS Distributions
2054*aca3beaaSApple OSS Distributions static struct in_ifaddr *
in_ifaddr_alloc(zalloc_flags_t how)2055*aca3beaaSApple OSS Distributions in_ifaddr_alloc(zalloc_flags_t how)
2056*aca3beaaSApple OSS Distributions {
2057*aca3beaaSApple OSS Distributions struct in_ifaddr *inifa;
2058*aca3beaaSApple OSS Distributions
2059*aca3beaaSApple OSS Distributions inifa = zalloc_flags(inifa_zone, Z_ZERO | how);
2060*aca3beaaSApple OSS Distributions if (inifa != NULL) {
2061*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_free = in_ifaddr_free;
2062*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_debug |= IFD_ALLOC;
2063*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_del_wc = &inifa->ia_ifa.ifa_debug;
2064*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_del_waiters = 0;
2065*aca3beaaSApple OSS Distributions ifa_lock_init(&inifa->ia_ifa);
2066*aca3beaaSApple OSS Distributions if (inifa_debug != 0) {
2067*aca3beaaSApple OSS Distributions struct in_ifaddr_dbg *inifa_dbg =
2068*aca3beaaSApple OSS Distributions (struct in_ifaddr_dbg *)inifa;
2069*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_debug |= IFD_DEBUG;
2070*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_trace = in_ifaddr_trace;
2071*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_attached = in_ifaddr_attached;
2072*aca3beaaSApple OSS Distributions inifa->ia_ifa.ifa_detached = in_ifaddr_detached;
2073*aca3beaaSApple OSS Distributions ctrace_record(&inifa_dbg->inifa_alloc);
2074*aca3beaaSApple OSS Distributions }
2075*aca3beaaSApple OSS Distributions }
2076*aca3beaaSApple OSS Distributions return inifa;
2077*aca3beaaSApple OSS Distributions }
2078*aca3beaaSApple OSS Distributions
2079*aca3beaaSApple OSS Distributions static void
in_ifaddr_free(struct ifaddr * ifa)2080*aca3beaaSApple OSS Distributions in_ifaddr_free(struct ifaddr *ifa)
2081*aca3beaaSApple OSS Distributions {
2082*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(ifa);
2083*aca3beaaSApple OSS Distributions
2084*aca3beaaSApple OSS Distributions if (ifa->ifa_refcnt != 0) {
2085*aca3beaaSApple OSS Distributions panic("%s: ifa %p bad ref cnt", __func__, ifa);
2086*aca3beaaSApple OSS Distributions /* NOTREACHED */
2087*aca3beaaSApple OSS Distributions }
2088*aca3beaaSApple OSS Distributions if (!(ifa->ifa_debug & IFD_ALLOC)) {
2089*aca3beaaSApple OSS Distributions panic("%s: ifa %p cannot be freed", __func__, ifa);
2090*aca3beaaSApple OSS Distributions /* NOTREACHED */
2091*aca3beaaSApple OSS Distributions }
2092*aca3beaaSApple OSS Distributions if (ifa->ifa_debug & IFD_DEBUG) {
2093*aca3beaaSApple OSS Distributions struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2094*aca3beaaSApple OSS Distributions ctrace_record(&inifa_dbg->inifa_free);
2095*aca3beaaSApple OSS Distributions bcopy(&inifa_dbg->inifa, &inifa_dbg->inifa_old,
2096*aca3beaaSApple OSS Distributions sizeof(struct in_ifaddr));
2097*aca3beaaSApple OSS Distributions if (ifa->ifa_debug & IFD_TRASHED) {
2098*aca3beaaSApple OSS Distributions /* Become a regular mutex, just in case */
2099*aca3beaaSApple OSS Distributions IFA_CONVERT_LOCK(ifa);
2100*aca3beaaSApple OSS Distributions lck_mtx_lock(&inifa_trash_lock);
2101*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&inifa_trash_head, inifa_dbg,
2102*aca3beaaSApple OSS Distributions inifa_trash_link);
2103*aca3beaaSApple OSS Distributions lck_mtx_unlock(&inifa_trash_lock);
2104*aca3beaaSApple OSS Distributions ifa->ifa_debug &= ~IFD_TRASHED;
2105*aca3beaaSApple OSS Distributions }
2106*aca3beaaSApple OSS Distributions }
2107*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2108*aca3beaaSApple OSS Distributions ifa_lock_destroy(ifa);
2109*aca3beaaSApple OSS Distributions bzero(ifa, sizeof(struct in_ifaddr));
2110*aca3beaaSApple OSS Distributions zfree(inifa_zone, ifa);
2111*aca3beaaSApple OSS Distributions }
2112*aca3beaaSApple OSS Distributions
2113*aca3beaaSApple OSS Distributions static void
in_ifaddr_attached(struct ifaddr * ifa)2114*aca3beaaSApple OSS Distributions in_ifaddr_attached(struct ifaddr *ifa)
2115*aca3beaaSApple OSS Distributions {
2116*aca3beaaSApple OSS Distributions struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2117*aca3beaaSApple OSS Distributions
2118*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(ifa);
2119*aca3beaaSApple OSS Distributions
2120*aca3beaaSApple OSS Distributions if (!(ifa->ifa_debug & IFD_DEBUG)) {
2121*aca3beaaSApple OSS Distributions panic("%s: ifa %p has no debug structure", __func__, ifa);
2122*aca3beaaSApple OSS Distributions /* NOTREACHED */
2123*aca3beaaSApple OSS Distributions }
2124*aca3beaaSApple OSS Distributions if (ifa->ifa_debug & IFD_TRASHED) {
2125*aca3beaaSApple OSS Distributions /* Become a regular mutex, just in case */
2126*aca3beaaSApple OSS Distributions IFA_CONVERT_LOCK(ifa);
2127*aca3beaaSApple OSS Distributions lck_mtx_lock(&inifa_trash_lock);
2128*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&inifa_trash_head, inifa_dbg, inifa_trash_link);
2129*aca3beaaSApple OSS Distributions lck_mtx_unlock(&inifa_trash_lock);
2130*aca3beaaSApple OSS Distributions ifa->ifa_debug &= ~IFD_TRASHED;
2131*aca3beaaSApple OSS Distributions }
2132*aca3beaaSApple OSS Distributions }
2133*aca3beaaSApple OSS Distributions
2134*aca3beaaSApple OSS Distributions static void
in_ifaddr_detached(struct ifaddr * ifa)2135*aca3beaaSApple OSS Distributions in_ifaddr_detached(struct ifaddr *ifa)
2136*aca3beaaSApple OSS Distributions {
2137*aca3beaaSApple OSS Distributions struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2138*aca3beaaSApple OSS Distributions
2139*aca3beaaSApple OSS Distributions IFA_LOCK_ASSERT_HELD(ifa);
2140*aca3beaaSApple OSS Distributions
2141*aca3beaaSApple OSS Distributions if (!(ifa->ifa_debug & IFD_DEBUG)) {
2142*aca3beaaSApple OSS Distributions panic("%s: ifa %p has no debug structure", __func__, ifa);
2143*aca3beaaSApple OSS Distributions /* NOTREACHED */
2144*aca3beaaSApple OSS Distributions } else if (ifa->ifa_debug & IFD_TRASHED) {
2145*aca3beaaSApple OSS Distributions panic("%s: ifa %p is already in trash list", __func__, ifa);
2146*aca3beaaSApple OSS Distributions /* NOTREACHED */
2147*aca3beaaSApple OSS Distributions }
2148*aca3beaaSApple OSS Distributions ifa->ifa_debug |= IFD_TRASHED;
2149*aca3beaaSApple OSS Distributions /* Become a regular mutex, just in case */
2150*aca3beaaSApple OSS Distributions IFA_CONVERT_LOCK(ifa);
2151*aca3beaaSApple OSS Distributions lck_mtx_lock(&inifa_trash_lock);
2152*aca3beaaSApple OSS Distributions TAILQ_INSERT_TAIL(&inifa_trash_head, inifa_dbg, inifa_trash_link);
2153*aca3beaaSApple OSS Distributions lck_mtx_unlock(&inifa_trash_lock);
2154*aca3beaaSApple OSS Distributions }
2155*aca3beaaSApple OSS Distributions
2156*aca3beaaSApple OSS Distributions static void
in_ifaddr_trace(struct ifaddr * ifa,int refhold)2157*aca3beaaSApple OSS Distributions in_ifaddr_trace(struct ifaddr *ifa, int refhold)
2158*aca3beaaSApple OSS Distributions {
2159*aca3beaaSApple OSS Distributions struct in_ifaddr_dbg *inifa_dbg = (struct in_ifaddr_dbg *)ifa;
2160*aca3beaaSApple OSS Distributions ctrace_t *tr;
2161*aca3beaaSApple OSS Distributions u_int32_t idx;
2162*aca3beaaSApple OSS Distributions u_int16_t *cnt;
2163*aca3beaaSApple OSS Distributions
2164*aca3beaaSApple OSS Distributions if (!(ifa->ifa_debug & IFD_DEBUG)) {
2165*aca3beaaSApple OSS Distributions panic("%s: ifa %p has no debug structure", __func__, ifa);
2166*aca3beaaSApple OSS Distributions /* NOTREACHED */
2167*aca3beaaSApple OSS Distributions }
2168*aca3beaaSApple OSS Distributions if (refhold) {
2169*aca3beaaSApple OSS Distributions cnt = &inifa_dbg->inifa_refhold_cnt;
2170*aca3beaaSApple OSS Distributions tr = inifa_dbg->inifa_refhold;
2171*aca3beaaSApple OSS Distributions } else {
2172*aca3beaaSApple OSS Distributions cnt = &inifa_dbg->inifa_refrele_cnt;
2173*aca3beaaSApple OSS Distributions tr = inifa_dbg->inifa_refrele;
2174*aca3beaaSApple OSS Distributions }
2175*aca3beaaSApple OSS Distributions
2176*aca3beaaSApple OSS Distributions idx = atomic_add_16_ov(cnt, 1) % INIFA_TRACE_HIST_SIZE;
2177*aca3beaaSApple OSS Distributions ctrace_record(&tr[idx]);
2178*aca3beaaSApple OSS Distributions }
2179*aca3beaaSApple OSS Distributions
2180*aca3beaaSApple OSS Distributions /*
2181*aca3beaaSApple OSS Distributions * Handle SIOCGASSOCIDS ioctl for PF_INET domain.
2182*aca3beaaSApple OSS Distributions */
2183*aca3beaaSApple OSS Distributions static int
in_getassocids(struct socket * so,uint32_t * cnt,user_addr_t aidp)2184*aca3beaaSApple OSS Distributions in_getassocids(struct socket *so, uint32_t *cnt, user_addr_t aidp)
2185*aca3beaaSApple OSS Distributions {
2186*aca3beaaSApple OSS Distributions struct inpcb *inp = sotoinpcb(so);
2187*aca3beaaSApple OSS Distributions sae_associd_t aid;
2188*aca3beaaSApple OSS Distributions
2189*aca3beaaSApple OSS Distributions if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) {
2190*aca3beaaSApple OSS Distributions return EINVAL;
2191*aca3beaaSApple OSS Distributions }
2192*aca3beaaSApple OSS Distributions
2193*aca3beaaSApple OSS Distributions /* INPCB has no concept of association */
2194*aca3beaaSApple OSS Distributions aid = SAE_ASSOCID_ANY;
2195*aca3beaaSApple OSS Distributions *cnt = 0;
2196*aca3beaaSApple OSS Distributions
2197*aca3beaaSApple OSS Distributions /* just asking how many there are? */
2198*aca3beaaSApple OSS Distributions if (aidp == USER_ADDR_NULL) {
2199*aca3beaaSApple OSS Distributions return 0;
2200*aca3beaaSApple OSS Distributions }
2201*aca3beaaSApple OSS Distributions
2202*aca3beaaSApple OSS Distributions return copyout(&aid, aidp, sizeof(aid));
2203*aca3beaaSApple OSS Distributions }
2204*aca3beaaSApple OSS Distributions
2205*aca3beaaSApple OSS Distributions /*
2206*aca3beaaSApple OSS Distributions * Handle SIOCGCONNIDS ioctl for PF_INET domain.
2207*aca3beaaSApple OSS Distributions */
2208*aca3beaaSApple OSS Distributions static int
in_getconnids(struct socket * so,sae_associd_t aid,uint32_t * cnt,user_addr_t cidp)2209*aca3beaaSApple OSS Distributions in_getconnids(struct socket *so, sae_associd_t aid, uint32_t *cnt,
2210*aca3beaaSApple OSS Distributions user_addr_t cidp)
2211*aca3beaaSApple OSS Distributions {
2212*aca3beaaSApple OSS Distributions struct inpcb *inp = sotoinpcb(so);
2213*aca3beaaSApple OSS Distributions sae_connid_t cid;
2214*aca3beaaSApple OSS Distributions
2215*aca3beaaSApple OSS Distributions if (inp == NULL || inp->inp_state == INPCB_STATE_DEAD) {
2216*aca3beaaSApple OSS Distributions return EINVAL;
2217*aca3beaaSApple OSS Distributions }
2218*aca3beaaSApple OSS Distributions
2219*aca3beaaSApple OSS Distributions if (aid != SAE_ASSOCID_ANY && aid != SAE_ASSOCID_ALL) {
2220*aca3beaaSApple OSS Distributions return EINVAL;
2221*aca3beaaSApple OSS Distributions }
2222*aca3beaaSApple OSS Distributions
2223*aca3beaaSApple OSS Distributions /* if connected, return 1 connection count */
2224*aca3beaaSApple OSS Distributions *cnt = ((so->so_state & SS_ISCONNECTED) ? 1 : 0);
2225*aca3beaaSApple OSS Distributions
2226*aca3beaaSApple OSS Distributions /* just asking how many there are? */
2227*aca3beaaSApple OSS Distributions if (cidp == USER_ADDR_NULL) {
2228*aca3beaaSApple OSS Distributions return 0;
2229*aca3beaaSApple OSS Distributions }
2230*aca3beaaSApple OSS Distributions
2231*aca3beaaSApple OSS Distributions /* if INPCB is connected, assign it connid 1 */
2232*aca3beaaSApple OSS Distributions cid = ((*cnt != 0) ? 1 : SAE_CONNID_ANY);
2233*aca3beaaSApple OSS Distributions
2234*aca3beaaSApple OSS Distributions return copyout(&cid, cidp, sizeof(cid));
2235*aca3beaaSApple OSS Distributions }
2236*aca3beaaSApple OSS Distributions
2237*aca3beaaSApple OSS Distributions /*
2238*aca3beaaSApple OSS Distributions * Handle SIOCGCONNINFO ioctl for PF_INET domain.
2239*aca3beaaSApple OSS Distributions */
2240*aca3beaaSApple OSS Distributions int
in_getconninfo(struct socket * so,sae_connid_t cid,uint32_t * flags,uint32_t * ifindex,int32_t * soerror,user_addr_t src,socklen_t * src_len,user_addr_t dst,socklen_t * dst_len,uint32_t * aux_type,user_addr_t aux_data,uint32_t * aux_len)2241*aca3beaaSApple OSS Distributions in_getconninfo(struct socket *so, sae_connid_t cid, uint32_t *flags,
2242*aca3beaaSApple OSS Distributions uint32_t *ifindex, int32_t *soerror, user_addr_t src, socklen_t *src_len,
2243*aca3beaaSApple OSS Distributions user_addr_t dst, socklen_t *dst_len, uint32_t *aux_type,
2244*aca3beaaSApple OSS Distributions user_addr_t aux_data, uint32_t *aux_len)
2245*aca3beaaSApple OSS Distributions {
2246*aca3beaaSApple OSS Distributions struct inpcb *inp = sotoinpcb(so);
2247*aca3beaaSApple OSS Distributions struct sockaddr_in sin;
2248*aca3beaaSApple OSS Distributions struct ifnet *ifp = NULL;
2249*aca3beaaSApple OSS Distributions int error = 0;
2250*aca3beaaSApple OSS Distributions u_int32_t copy_len = 0;
2251*aca3beaaSApple OSS Distributions
2252*aca3beaaSApple OSS Distributions /*
2253*aca3beaaSApple OSS Distributions * Don't test for INPCB_STATE_DEAD since this may be called
2254*aca3beaaSApple OSS Distributions * after SOF_PCBCLEARING is set, e.g. after tcp_close().
2255*aca3beaaSApple OSS Distributions */
2256*aca3beaaSApple OSS Distributions if (inp == NULL) {
2257*aca3beaaSApple OSS Distributions error = EINVAL;
2258*aca3beaaSApple OSS Distributions goto out;
2259*aca3beaaSApple OSS Distributions }
2260*aca3beaaSApple OSS Distributions
2261*aca3beaaSApple OSS Distributions if (cid != SAE_CONNID_ANY && cid != SAE_CONNID_ALL && cid != 1) {
2262*aca3beaaSApple OSS Distributions error = EINVAL;
2263*aca3beaaSApple OSS Distributions goto out;
2264*aca3beaaSApple OSS Distributions }
2265*aca3beaaSApple OSS Distributions
2266*aca3beaaSApple OSS Distributions ifp = inp->inp_last_outifp;
2267*aca3beaaSApple OSS Distributions *ifindex = ((ifp != NULL) ? ifp->if_index : 0);
2268*aca3beaaSApple OSS Distributions *soerror = so->so_error;
2269*aca3beaaSApple OSS Distributions *flags = 0;
2270*aca3beaaSApple OSS Distributions if (so->so_state & SS_ISCONNECTED) {
2271*aca3beaaSApple OSS Distributions *flags |= (CIF_CONNECTED | CIF_PREFERRED);
2272*aca3beaaSApple OSS Distributions }
2273*aca3beaaSApple OSS Distributions if (inp->inp_flags & INP_BOUND_IF) {
2274*aca3beaaSApple OSS Distributions *flags |= CIF_BOUND_IF;
2275*aca3beaaSApple OSS Distributions }
2276*aca3beaaSApple OSS Distributions if (!(inp->inp_flags & INP_INADDR_ANY)) {
2277*aca3beaaSApple OSS Distributions *flags |= CIF_BOUND_IP;
2278*aca3beaaSApple OSS Distributions }
2279*aca3beaaSApple OSS Distributions if (!(inp->inp_flags & INP_ANONPORT)) {
2280*aca3beaaSApple OSS Distributions *flags |= CIF_BOUND_PORT;
2281*aca3beaaSApple OSS Distributions }
2282*aca3beaaSApple OSS Distributions
2283*aca3beaaSApple OSS Distributions bzero(&sin, sizeof(sin));
2284*aca3beaaSApple OSS Distributions sin.sin_len = sizeof(sin);
2285*aca3beaaSApple OSS Distributions sin.sin_family = AF_INET;
2286*aca3beaaSApple OSS Distributions
2287*aca3beaaSApple OSS Distributions /* source address and port */
2288*aca3beaaSApple OSS Distributions sin.sin_port = inp->inp_lport;
2289*aca3beaaSApple OSS Distributions sin.sin_addr.s_addr = inp->inp_laddr.s_addr;
2290*aca3beaaSApple OSS Distributions if (*src_len == 0) {
2291*aca3beaaSApple OSS Distributions *src_len = sin.sin_len;
2292*aca3beaaSApple OSS Distributions } else {
2293*aca3beaaSApple OSS Distributions if (src != USER_ADDR_NULL) {
2294*aca3beaaSApple OSS Distributions copy_len = min(*src_len, sizeof(sin));
2295*aca3beaaSApple OSS Distributions error = copyout(&sin, src, copy_len);
2296*aca3beaaSApple OSS Distributions if (error != 0) {
2297*aca3beaaSApple OSS Distributions goto out;
2298*aca3beaaSApple OSS Distributions }
2299*aca3beaaSApple OSS Distributions *src_len = copy_len;
2300*aca3beaaSApple OSS Distributions }
2301*aca3beaaSApple OSS Distributions }
2302*aca3beaaSApple OSS Distributions
2303*aca3beaaSApple OSS Distributions /* destination address and port */
2304*aca3beaaSApple OSS Distributions sin.sin_port = inp->inp_fport;
2305*aca3beaaSApple OSS Distributions sin.sin_addr.s_addr = inp->inp_faddr.s_addr;
2306*aca3beaaSApple OSS Distributions if (*dst_len == 0) {
2307*aca3beaaSApple OSS Distributions *dst_len = sin.sin_len;
2308*aca3beaaSApple OSS Distributions } else {
2309*aca3beaaSApple OSS Distributions if (dst != USER_ADDR_NULL) {
2310*aca3beaaSApple OSS Distributions copy_len = min(*dst_len, sizeof(sin));
2311*aca3beaaSApple OSS Distributions error = copyout(&sin, dst, copy_len);
2312*aca3beaaSApple OSS Distributions if (error != 0) {
2313*aca3beaaSApple OSS Distributions goto out;
2314*aca3beaaSApple OSS Distributions }
2315*aca3beaaSApple OSS Distributions *dst_len = copy_len;
2316*aca3beaaSApple OSS Distributions }
2317*aca3beaaSApple OSS Distributions }
2318*aca3beaaSApple OSS Distributions
2319*aca3beaaSApple OSS Distributions if (SOCK_PROTO(so) == IPPROTO_TCP) {
2320*aca3beaaSApple OSS Distributions struct conninfo_tcp tcp_ci;
2321*aca3beaaSApple OSS Distributions
2322*aca3beaaSApple OSS Distributions *aux_type = CIAUX_TCP;
2323*aca3beaaSApple OSS Distributions if (*aux_len == 0) {
2324*aca3beaaSApple OSS Distributions *aux_len = sizeof(tcp_ci);
2325*aca3beaaSApple OSS Distributions } else {
2326*aca3beaaSApple OSS Distributions if (aux_data != USER_ADDR_NULL) {
2327*aca3beaaSApple OSS Distributions copy_len = min(*aux_len, sizeof(tcp_ci));
2328*aca3beaaSApple OSS Distributions bzero(&tcp_ci, sizeof(tcp_ci));
2329*aca3beaaSApple OSS Distributions tcp_getconninfo(so, &tcp_ci);
2330*aca3beaaSApple OSS Distributions error = copyout(&tcp_ci, aux_data, copy_len);
2331*aca3beaaSApple OSS Distributions if (error != 0) {
2332*aca3beaaSApple OSS Distributions goto out;
2333*aca3beaaSApple OSS Distributions }
2334*aca3beaaSApple OSS Distributions *aux_len = copy_len;
2335*aca3beaaSApple OSS Distributions }
2336*aca3beaaSApple OSS Distributions }
2337*aca3beaaSApple OSS Distributions } else {
2338*aca3beaaSApple OSS Distributions *aux_type = 0;
2339*aca3beaaSApple OSS Distributions *aux_len = 0;
2340*aca3beaaSApple OSS Distributions }
2341*aca3beaaSApple OSS Distributions
2342*aca3beaaSApple OSS Distributions out:
2343*aca3beaaSApple OSS Distributions return error;
2344*aca3beaaSApple OSS Distributions }
2345*aca3beaaSApple OSS Distributions
2346*aca3beaaSApple OSS Distributions struct in_llentry {
2347*aca3beaaSApple OSS Distributions struct llentry base;
2348*aca3beaaSApple OSS Distributions };
2349*aca3beaaSApple OSS Distributions
2350*aca3beaaSApple OSS Distributions #define IN_LLTBL_DEFAULT_HSIZE 32
2351*aca3beaaSApple OSS Distributions #define IN_LLTBL_HASH(k, h) \
2352*aca3beaaSApple OSS Distributions ((((((((k) >> 8) ^ (k)) >> 8) ^ (k)) >> 8) ^ (k)) & ((h) - 1))
2353*aca3beaaSApple OSS Distributions
2354*aca3beaaSApple OSS Distributions /*
2355*aca3beaaSApple OSS Distributions * Do actual deallocation of @lle.
2356*aca3beaaSApple OSS Distributions */
2357*aca3beaaSApple OSS Distributions static void
in_lltable_destroy_lle_unlocked(struct llentry * lle)2358*aca3beaaSApple OSS Distributions in_lltable_destroy_lle_unlocked(struct llentry *lle)
2359*aca3beaaSApple OSS Distributions {
2360*aca3beaaSApple OSS Distributions LLE_LOCK_DESTROY(lle);
2361*aca3beaaSApple OSS Distributions LLE_REQ_DESTROY(lle);
2362*aca3beaaSApple OSS Distributions struct in_llentry *in_lle = (struct in_llentry *)lle;
2363*aca3beaaSApple OSS Distributions kfree_type(struct in_llentry, in_lle);
2364*aca3beaaSApple OSS Distributions }
2365*aca3beaaSApple OSS Distributions
2366*aca3beaaSApple OSS Distributions /*
2367*aca3beaaSApple OSS Distributions * Called by LLE_FREE_LOCKED when number of references
2368*aca3beaaSApple OSS Distributions * drops to zero.
2369*aca3beaaSApple OSS Distributions */
2370*aca3beaaSApple OSS Distributions static void
in_lltable_destroy_lle(struct llentry * lle)2371*aca3beaaSApple OSS Distributions in_lltable_destroy_lle(struct llentry *lle)
2372*aca3beaaSApple OSS Distributions {
2373*aca3beaaSApple OSS Distributions LLE_WUNLOCK(lle);
2374*aca3beaaSApple OSS Distributions in_lltable_destroy_lle_unlocked(lle);
2375*aca3beaaSApple OSS Distributions }
2376*aca3beaaSApple OSS Distributions
2377*aca3beaaSApple OSS Distributions static struct llentry *
in_lltable_new(struct in_addr addr4,uint16_t flags)2378*aca3beaaSApple OSS Distributions in_lltable_new(struct in_addr addr4, uint16_t flags)
2379*aca3beaaSApple OSS Distributions {
2380*aca3beaaSApple OSS Distributions #pragma unused(flags)
2381*aca3beaaSApple OSS Distributions struct in_llentry *lle;
2382*aca3beaaSApple OSS Distributions
2383*aca3beaaSApple OSS Distributions lle = kalloc_type(struct in_llentry, Z_NOWAIT | Z_ZERO);
2384*aca3beaaSApple OSS Distributions if (lle == NULL) { /* NB: caller generates msg */
2385*aca3beaaSApple OSS Distributions return NULL;
2386*aca3beaaSApple OSS Distributions }
2387*aca3beaaSApple OSS Distributions
2388*aca3beaaSApple OSS Distributions /*
2389*aca3beaaSApple OSS Distributions * For IPv4 this will trigger "arpresolve" to generate
2390*aca3beaaSApple OSS Distributions * an ARP request.
2391*aca3beaaSApple OSS Distributions */
2392*aca3beaaSApple OSS Distributions lle->base.la_expire = net_uptime(); /* mark expired */
2393*aca3beaaSApple OSS Distributions lle->base.r_l3addr.addr4 = addr4;
2394*aca3beaaSApple OSS Distributions lle->base.lle_refcnt = 1;
2395*aca3beaaSApple OSS Distributions lle->base.lle_free = in_lltable_destroy_lle;
2396*aca3beaaSApple OSS Distributions
2397*aca3beaaSApple OSS Distributions LLE_LOCK_INIT(&lle->base);
2398*aca3beaaSApple OSS Distributions LLE_REQ_INIT(&lle->base);
2399*aca3beaaSApple OSS Distributions //callout_init(&lle->base.lle_timer, 1);
2400*aca3beaaSApple OSS Distributions
2401*aca3beaaSApple OSS Distributions return &lle->base;
2402*aca3beaaSApple OSS Distributions }
2403*aca3beaaSApple OSS Distributions
2404*aca3beaaSApple OSS Distributions #define IN_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
2405*aca3beaaSApple OSS Distributions ((((d).s_addr ^ (a).s_addr) & (m).s_addr)) == 0 )
2406*aca3beaaSApple OSS Distributions
2407*aca3beaaSApple OSS Distributions static int
in_lltable_match_prefix(const struct sockaddr * saddr,const struct sockaddr * smask,uint16_t flags,struct llentry * lle)2408*aca3beaaSApple OSS Distributions in_lltable_match_prefix(const struct sockaddr *saddr,
2409*aca3beaaSApple OSS Distributions const struct sockaddr *smask, uint16_t flags, struct llentry *lle)
2410*aca3beaaSApple OSS Distributions {
2411*aca3beaaSApple OSS Distributions struct in_addr addr, mask, lle_addr;
2412*aca3beaaSApple OSS Distributions
2413*aca3beaaSApple OSS Distributions addr = ((const struct sockaddr_in *)(const void *)saddr)->sin_addr;
2414*aca3beaaSApple OSS Distributions mask = ((const struct sockaddr_in *)(const void *)smask)->sin_addr;
2415*aca3beaaSApple OSS Distributions lle_addr.s_addr = ntohl(lle->r_l3addr.addr4.s_addr);
2416*aca3beaaSApple OSS Distributions
2417*aca3beaaSApple OSS Distributions if (IN_ARE_MASKED_ADDR_EQUAL(lle_addr, addr, mask) == 0) {
2418*aca3beaaSApple OSS Distributions return 0;
2419*aca3beaaSApple OSS Distributions }
2420*aca3beaaSApple OSS Distributions
2421*aca3beaaSApple OSS Distributions if (lle->la_flags & LLE_IFADDR) {
2422*aca3beaaSApple OSS Distributions /*
2423*aca3beaaSApple OSS Distributions * Delete LLE_IFADDR records IFF address & flag matches.
2424*aca3beaaSApple OSS Distributions * Note that addr is the interface address within prefix
2425*aca3beaaSApple OSS Distributions * being matched.
2426*aca3beaaSApple OSS Distributions * Note also we should handle 'ifdown' cases without removing
2427*aca3beaaSApple OSS Distributions * ifaddr macs.
2428*aca3beaaSApple OSS Distributions */
2429*aca3beaaSApple OSS Distributions if (addr.s_addr == lle_addr.s_addr && (flags & LLE_STATIC) != 0) {
2430*aca3beaaSApple OSS Distributions return 1;
2431*aca3beaaSApple OSS Distributions }
2432*aca3beaaSApple OSS Distributions return 0;
2433*aca3beaaSApple OSS Distributions }
2434*aca3beaaSApple OSS Distributions
2435*aca3beaaSApple OSS Distributions /* flags & LLE_STATIC means deleting both dynamic and static entries */
2436*aca3beaaSApple OSS Distributions if ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC)) {
2437*aca3beaaSApple OSS Distributions return 1;
2438*aca3beaaSApple OSS Distributions }
2439*aca3beaaSApple OSS Distributions
2440*aca3beaaSApple OSS Distributions return 0;
2441*aca3beaaSApple OSS Distributions }
2442*aca3beaaSApple OSS Distributions
2443*aca3beaaSApple OSS Distributions static void
in_lltable_free_entry(struct lltable * llt,struct llentry * lle)2444*aca3beaaSApple OSS Distributions in_lltable_free_entry(struct lltable *llt, struct llentry *lle)
2445*aca3beaaSApple OSS Distributions {
2446*aca3beaaSApple OSS Distributions struct ifnet *ifp;
2447*aca3beaaSApple OSS Distributions size_t pkts_dropped;
2448*aca3beaaSApple OSS Distributions
2449*aca3beaaSApple OSS Distributions LLE_WLOCK_ASSERT(lle);
2450*aca3beaaSApple OSS Distributions KASSERT(llt != NULL, ("lltable is NULL"));
2451*aca3beaaSApple OSS Distributions
2452*aca3beaaSApple OSS Distributions /* Unlink entry from table if not already */
2453*aca3beaaSApple OSS Distributions if ((lle->la_flags & LLE_LINKED) != 0) {
2454*aca3beaaSApple OSS Distributions ifp = llt->llt_ifp;
2455*aca3beaaSApple OSS Distributions IF_AFDATA_WLOCK_ASSERT(ifp, llt->llt_af);
2456*aca3beaaSApple OSS Distributions lltable_unlink_entry(llt, lle);
2457*aca3beaaSApple OSS Distributions }
2458*aca3beaaSApple OSS Distributions
2459*aca3beaaSApple OSS Distributions #if 0
2460*aca3beaaSApple OSS Distributions /* cancel timer */
2461*aca3beaaSApple OSS Distributions if (callout_stop(&lle->lle_timer) > 0) {
2462*aca3beaaSApple OSS Distributions LLE_REMREF(lle);
2463*aca3beaaSApple OSS Distributions }
2464*aca3beaaSApple OSS Distributions #endif
2465*aca3beaaSApple OSS Distributions /* Drop hold queue */
2466*aca3beaaSApple OSS Distributions pkts_dropped = llentry_free(lle);
2467*aca3beaaSApple OSS Distributions arpstat.dropped += pkts_dropped;
2468*aca3beaaSApple OSS Distributions }
2469*aca3beaaSApple OSS Distributions
2470*aca3beaaSApple OSS Distributions
2471*aca3beaaSApple OSS Distributions static int
in_lltable_rtcheck(struct ifnet * ifp,uint16_t flags,const struct sockaddr * l3addr)2472*aca3beaaSApple OSS Distributions in_lltable_rtcheck(struct ifnet *ifp, uint16_t flags, const struct sockaddr *l3addr)
2473*aca3beaaSApple OSS Distributions {
2474*aca3beaaSApple OSS Distributions #pragma unused(flags)
2475*aca3beaaSApple OSS Distributions struct rtentry *rt;
2476*aca3beaaSApple OSS Distributions
2477*aca3beaaSApple OSS Distributions KASSERT(l3addr->sa_family == AF_INET,
2478*aca3beaaSApple OSS Distributions ("sin_family %d", l3addr->sa_family));
2479*aca3beaaSApple OSS Distributions
2480*aca3beaaSApple OSS Distributions /* XXX rtalloc1 should take a const param */
2481*aca3beaaSApple OSS Distributions rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
2482*aca3beaaSApple OSS Distributions if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
2483*aca3beaaSApple OSS Distributions log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
2484*aca3beaaSApple OSS Distributions inet_ntoa(((const struct sockaddr_in *)(const void *)l3addr)->sin_addr));
2485*aca3beaaSApple OSS Distributions if (rt != NULL) {
2486*aca3beaaSApple OSS Distributions rtfree_locked(rt);
2487*aca3beaaSApple OSS Distributions }
2488*aca3beaaSApple OSS Distributions return EINVAL;
2489*aca3beaaSApple OSS Distributions }
2490*aca3beaaSApple OSS Distributions rtfree_locked(rt);
2491*aca3beaaSApple OSS Distributions return 0;
2492*aca3beaaSApple OSS Distributions }
2493*aca3beaaSApple OSS Distributions
2494*aca3beaaSApple OSS Distributions static inline uint32_t
in_lltable_hash_dst(const struct in_addr dst,uint32_t hsize)2495*aca3beaaSApple OSS Distributions in_lltable_hash_dst(const struct in_addr dst, uint32_t hsize)
2496*aca3beaaSApple OSS Distributions {
2497*aca3beaaSApple OSS Distributions return IN_LLTBL_HASH(dst.s_addr, hsize);
2498*aca3beaaSApple OSS Distributions }
2499*aca3beaaSApple OSS Distributions
2500*aca3beaaSApple OSS Distributions static uint32_t
in_lltable_hash(const struct llentry * lle,uint32_t hsize)2501*aca3beaaSApple OSS Distributions in_lltable_hash(const struct llentry *lle, uint32_t hsize)
2502*aca3beaaSApple OSS Distributions {
2503*aca3beaaSApple OSS Distributions return in_lltable_hash_dst(lle->r_l3addr.addr4, hsize);
2504*aca3beaaSApple OSS Distributions }
2505*aca3beaaSApple OSS Distributions
2506*aca3beaaSApple OSS Distributions
2507*aca3beaaSApple OSS Distributions static void
in_lltable_fill_sa_entry(const struct llentry * lle,struct sockaddr * sa)2508*aca3beaaSApple OSS Distributions in_lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
2509*aca3beaaSApple OSS Distributions {
2510*aca3beaaSApple OSS Distributions struct sockaddr_in *sin;
2511*aca3beaaSApple OSS Distributions
2512*aca3beaaSApple OSS Distributions sin = (struct sockaddr_in *)(void *)sa;
2513*aca3beaaSApple OSS Distributions bzero(sin, sizeof(*sin));
2514*aca3beaaSApple OSS Distributions sin->sin_family = AF_INET;
2515*aca3beaaSApple OSS Distributions sin->sin_len = sizeof(*sin);
2516*aca3beaaSApple OSS Distributions sin->sin_addr = lle->r_l3addr.addr4;
2517*aca3beaaSApple OSS Distributions }
2518*aca3beaaSApple OSS Distributions
2519*aca3beaaSApple OSS Distributions static inline struct llentry *
in_lltable_find_dst(struct lltable * llt,struct in_addr dst)2520*aca3beaaSApple OSS Distributions in_lltable_find_dst(struct lltable *llt, struct in_addr dst)
2521*aca3beaaSApple OSS Distributions {
2522*aca3beaaSApple OSS Distributions struct llentry *lle;
2523*aca3beaaSApple OSS Distributions struct llentries *lleh;
2524*aca3beaaSApple OSS Distributions u_int hashidx;
2525*aca3beaaSApple OSS Distributions
2526*aca3beaaSApple OSS Distributions hashidx = in_lltable_hash_dst(dst, llt->llt_hsize);
2527*aca3beaaSApple OSS Distributions lleh = &llt->lle_head[hashidx];
2528*aca3beaaSApple OSS Distributions LIST_FOREACH(lle, lleh, lle_next) {
2529*aca3beaaSApple OSS Distributions if (lle->la_flags & LLE_DELETED) {
2530*aca3beaaSApple OSS Distributions continue;
2531*aca3beaaSApple OSS Distributions }
2532*aca3beaaSApple OSS Distributions if (lle->r_l3addr.addr4.s_addr == dst.s_addr) {
2533*aca3beaaSApple OSS Distributions break;
2534*aca3beaaSApple OSS Distributions }
2535*aca3beaaSApple OSS Distributions }
2536*aca3beaaSApple OSS Distributions
2537*aca3beaaSApple OSS Distributions return lle;
2538*aca3beaaSApple OSS Distributions }
2539*aca3beaaSApple OSS Distributions
2540*aca3beaaSApple OSS Distributions static void
in_lltable_delete_entry(struct lltable * llt,struct llentry * lle)2541*aca3beaaSApple OSS Distributions in_lltable_delete_entry(struct lltable *llt, struct llentry *lle)
2542*aca3beaaSApple OSS Distributions {
2543*aca3beaaSApple OSS Distributions #pragma unused(llt)
2544*aca3beaaSApple OSS Distributions lle->la_flags |= LLE_DELETED;
2545*aca3beaaSApple OSS Distributions //EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED);
2546*aca3beaaSApple OSS Distributions #ifdef DIAGNOSTIC
2547*aca3beaaSApple OSS Distributions log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
2548*aca3beaaSApple OSS Distributions #endif
2549*aca3beaaSApple OSS Distributions llentry_free(lle);
2550*aca3beaaSApple OSS Distributions }
2551*aca3beaaSApple OSS Distributions
2552*aca3beaaSApple OSS Distributions static struct llentry *
in_lltable_alloc(struct lltable * llt,uint16_t flags,const struct sockaddr * l3addr)2553*aca3beaaSApple OSS Distributions in_lltable_alloc(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr)
2554*aca3beaaSApple OSS Distributions {
2555*aca3beaaSApple OSS Distributions const struct sockaddr_in *sin = (const struct sockaddr_in *) (const void *)l3addr;
2556*aca3beaaSApple OSS Distributions struct ifnet *ifp = llt->llt_ifp;
2557*aca3beaaSApple OSS Distributions struct llentry *lle;
2558*aca3beaaSApple OSS Distributions
2559*aca3beaaSApple OSS Distributions KASSERT(l3addr->sa_family == AF_INET,
2560*aca3beaaSApple OSS Distributions ("sin_family %d", l3addr->sa_family));
2561*aca3beaaSApple OSS Distributions
2562*aca3beaaSApple OSS Distributions /*
2563*aca3beaaSApple OSS Distributions * A route that covers the given address must have
2564*aca3beaaSApple OSS Distributions * been installed 1st because we are doing a resolution,
2565*aca3beaaSApple OSS Distributions * verify this.
2566*aca3beaaSApple OSS Distributions */
2567*aca3beaaSApple OSS Distributions if (!(flags & LLE_IFADDR) &&
2568*aca3beaaSApple OSS Distributions in_lltable_rtcheck(ifp, flags, l3addr) != 0) {
2569*aca3beaaSApple OSS Distributions return NULL;
2570*aca3beaaSApple OSS Distributions }
2571*aca3beaaSApple OSS Distributions
2572*aca3beaaSApple OSS Distributions lle = in_lltable_new(sin->sin_addr, flags);
2573*aca3beaaSApple OSS Distributions if (lle == NULL) {
2574*aca3beaaSApple OSS Distributions log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
2575*aca3beaaSApple OSS Distributions return NULL;
2576*aca3beaaSApple OSS Distributions }
2577*aca3beaaSApple OSS Distributions lle->la_flags = flags & ~LLE_CREATE;
2578*aca3beaaSApple OSS Distributions if (flags & LLE_STATIC) {
2579*aca3beaaSApple OSS Distributions lle->r_flags |= RLLE_VALID;
2580*aca3beaaSApple OSS Distributions }
2581*aca3beaaSApple OSS Distributions if ((flags & LLE_IFADDR) == LLE_IFADDR) {
2582*aca3beaaSApple OSS Distributions lltable_set_entry_addr(ifp, lle, LLADDR(SDL(ifp->if_lladdr->ifa_addr)));
2583*aca3beaaSApple OSS Distributions lle->la_flags |= LLE_STATIC;
2584*aca3beaaSApple OSS Distributions lle->r_flags |= (RLLE_VALID | RLLE_IFADDR);
2585*aca3beaaSApple OSS Distributions }
2586*aca3beaaSApple OSS Distributions return lle;
2587*aca3beaaSApple OSS Distributions }
2588*aca3beaaSApple OSS Distributions
2589*aca3beaaSApple OSS Distributions /*
2590*aca3beaaSApple OSS Distributions * Return NULL if not found or marked for deletion.
2591*aca3beaaSApple OSS Distributions * If found return lle read locked.
2592*aca3beaaSApple OSS Distributions */
2593*aca3beaaSApple OSS Distributions static struct llentry *
in_lltable_lookup(struct lltable * llt,uint16_t flags,const struct sockaddr * l3addr)2594*aca3beaaSApple OSS Distributions in_lltable_lookup(struct lltable *llt, uint16_t flags, const struct sockaddr *l3addr)
2595*aca3beaaSApple OSS Distributions {
2596*aca3beaaSApple OSS Distributions const struct sockaddr_in *sin = (const struct sockaddr_in *)(const void *)l3addr;
2597*aca3beaaSApple OSS Distributions struct llentry *lle;
2598*aca3beaaSApple OSS Distributions
2599*aca3beaaSApple OSS Distributions IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp, llt->llt_af);
2600*aca3beaaSApple OSS Distributions
2601*aca3beaaSApple OSS Distributions KASSERT(l3addr->sa_family == AF_INET,
2602*aca3beaaSApple OSS Distributions ("sin_family %d", l3addr->sa_family));
2603*aca3beaaSApple OSS Distributions lle = in_lltable_find_dst(llt, sin->sin_addr);
2604*aca3beaaSApple OSS Distributions
2605*aca3beaaSApple OSS Distributions if (lle == NULL) {
2606*aca3beaaSApple OSS Distributions return NULL;
2607*aca3beaaSApple OSS Distributions }
2608*aca3beaaSApple OSS Distributions
2609*aca3beaaSApple OSS Distributions KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=
2610*aca3beaaSApple OSS Distributions (LLE_UNLOCKED | LLE_EXCLUSIVE), ("wrong lle request flags: 0x%X",
2611*aca3beaaSApple OSS Distributions flags));
2612*aca3beaaSApple OSS Distributions
2613*aca3beaaSApple OSS Distributions if (flags & LLE_UNLOCKED) {
2614*aca3beaaSApple OSS Distributions return lle;
2615*aca3beaaSApple OSS Distributions }
2616*aca3beaaSApple OSS Distributions
2617*aca3beaaSApple OSS Distributions if (flags & LLE_EXCLUSIVE) {
2618*aca3beaaSApple OSS Distributions LLE_WLOCK(lle);
2619*aca3beaaSApple OSS Distributions } else {
2620*aca3beaaSApple OSS Distributions LLE_RLOCK(lle);
2621*aca3beaaSApple OSS Distributions }
2622*aca3beaaSApple OSS Distributions
2623*aca3beaaSApple OSS Distributions return lle;
2624*aca3beaaSApple OSS Distributions }
2625*aca3beaaSApple OSS Distributions
2626*aca3beaaSApple OSS Distributions static int
in_lltable_dump_entry(struct lltable * llt,struct llentry * lle,struct sysctl_req * wr)2627*aca3beaaSApple OSS Distributions in_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
2628*aca3beaaSApple OSS Distributions struct sysctl_req *wr)
2629*aca3beaaSApple OSS Distributions {
2630*aca3beaaSApple OSS Distributions struct ifnet *ifp = llt->llt_ifp;
2631*aca3beaaSApple OSS Distributions /* XXX stack use */
2632*aca3beaaSApple OSS Distributions struct {
2633*aca3beaaSApple OSS Distributions struct rt_msghdr rtm;
2634*aca3beaaSApple OSS Distributions struct sockaddr_in sin;
2635*aca3beaaSApple OSS Distributions struct sockaddr_dl sdl;
2636*aca3beaaSApple OSS Distributions } arpc;
2637*aca3beaaSApple OSS Distributions struct sockaddr_dl *sdl;
2638*aca3beaaSApple OSS Distributions int error;
2639*aca3beaaSApple OSS Distributions
2640*aca3beaaSApple OSS Distributions bzero(&arpc, sizeof(arpc));
2641*aca3beaaSApple OSS Distributions /* skip deleted entries */
2642*aca3beaaSApple OSS Distributions if ((lle->la_flags & LLE_DELETED) == LLE_DELETED) {
2643*aca3beaaSApple OSS Distributions return 0;
2644*aca3beaaSApple OSS Distributions }
2645*aca3beaaSApple OSS Distributions /* Skip if jailed and not a valid IP of the prison. */
2646*aca3beaaSApple OSS Distributions lltable_fill_sa_entry(lle, (struct sockaddr *)&arpc.sin);
2647*aca3beaaSApple OSS Distributions /*
2648*aca3beaaSApple OSS Distributions * produce a msg made of:
2649*aca3beaaSApple OSS Distributions * struct rt_msghdr;
2650*aca3beaaSApple OSS Distributions * struct sockaddr_in; (IPv4)
2651*aca3beaaSApple OSS Distributions * struct sockaddr_dl;
2652*aca3beaaSApple OSS Distributions */
2653*aca3beaaSApple OSS Distributions arpc.rtm.rtm_msglen = sizeof(arpc);
2654*aca3beaaSApple OSS Distributions arpc.rtm.rtm_version = RTM_VERSION;
2655*aca3beaaSApple OSS Distributions arpc.rtm.rtm_type = RTM_GET;
2656*aca3beaaSApple OSS Distributions arpc.rtm.rtm_flags = RTF_UP;
2657*aca3beaaSApple OSS Distributions arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
2658*aca3beaaSApple OSS Distributions
2659*aca3beaaSApple OSS Distributions /* publish */
2660*aca3beaaSApple OSS Distributions if (lle->la_flags & LLE_PUB) {
2661*aca3beaaSApple OSS Distributions arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
2662*aca3beaaSApple OSS Distributions }
2663*aca3beaaSApple OSS Distributions
2664*aca3beaaSApple OSS Distributions sdl = &arpc.sdl;
2665*aca3beaaSApple OSS Distributions sdl->sdl_family = AF_LINK;
2666*aca3beaaSApple OSS Distributions sdl->sdl_len = sizeof(*sdl);
2667*aca3beaaSApple OSS Distributions sdl->sdl_index = ifp->if_index;
2668*aca3beaaSApple OSS Distributions sdl->sdl_type = ifp->if_type;
2669*aca3beaaSApple OSS Distributions if ((lle->la_flags & LLE_VALID) == LLE_VALID) {
2670*aca3beaaSApple OSS Distributions sdl->sdl_alen = ifp->if_addrlen;
2671*aca3beaaSApple OSS Distributions bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
2672*aca3beaaSApple OSS Distributions } else {
2673*aca3beaaSApple OSS Distributions sdl->sdl_alen = 0;
2674*aca3beaaSApple OSS Distributions bzero(LLADDR(sdl), ifp->if_addrlen);
2675*aca3beaaSApple OSS Distributions }
2676*aca3beaaSApple OSS Distributions
2677*aca3beaaSApple OSS Distributions arpc.rtm.rtm_rmx.rmx_expire =
2678*aca3beaaSApple OSS Distributions lle->la_flags & LLE_STATIC ? 0 : (int32_t)lle->la_expire;
2679*aca3beaaSApple OSS Distributions arpc.rtm.rtm_flags |= (RTF_HOST | RTF_LLDATA);
2680*aca3beaaSApple OSS Distributions if (lle->la_flags & LLE_STATIC) {
2681*aca3beaaSApple OSS Distributions arpc.rtm.rtm_flags |= RTF_STATIC;
2682*aca3beaaSApple OSS Distributions }
2683*aca3beaaSApple OSS Distributions if (lle->la_flags & LLE_IFADDR) {
2684*aca3beaaSApple OSS Distributions arpc.rtm.rtm_flags |= RTF_PINNED;
2685*aca3beaaSApple OSS Distributions }
2686*aca3beaaSApple OSS Distributions arpc.rtm.rtm_flags |= RTF_PINNED;
2687*aca3beaaSApple OSS Distributions arpc.rtm.rtm_index = ifp->if_index;
2688*aca3beaaSApple OSS Distributions error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
2689*aca3beaaSApple OSS Distributions
2690*aca3beaaSApple OSS Distributions return error;
2691*aca3beaaSApple OSS Distributions }
2692*aca3beaaSApple OSS Distributions
2693*aca3beaaSApple OSS Distributions static struct lltable *
in_lltattach(struct ifnet * ifp)2694*aca3beaaSApple OSS Distributions in_lltattach(struct ifnet *ifp)
2695*aca3beaaSApple OSS Distributions {
2696*aca3beaaSApple OSS Distributions struct lltable *llt;
2697*aca3beaaSApple OSS Distributions
2698*aca3beaaSApple OSS Distributions llt = lltable_allocate_htbl(IN_LLTBL_DEFAULT_HSIZE);
2699*aca3beaaSApple OSS Distributions llt->llt_af = AF_INET;
2700*aca3beaaSApple OSS Distributions llt->llt_ifp = ifp;
2701*aca3beaaSApple OSS Distributions
2702*aca3beaaSApple OSS Distributions llt->llt_lookup = in_lltable_lookup;
2703*aca3beaaSApple OSS Distributions llt->llt_alloc_entry = in_lltable_alloc;
2704*aca3beaaSApple OSS Distributions llt->llt_delete_entry = in_lltable_delete_entry;
2705*aca3beaaSApple OSS Distributions llt->llt_dump_entry = in_lltable_dump_entry;
2706*aca3beaaSApple OSS Distributions llt->llt_hash = in_lltable_hash;
2707*aca3beaaSApple OSS Distributions llt->llt_fill_sa_entry = in_lltable_fill_sa_entry;
2708*aca3beaaSApple OSS Distributions llt->llt_free_entry = in_lltable_free_entry;
2709*aca3beaaSApple OSS Distributions llt->llt_match_prefix = in_lltable_match_prefix;
2710*aca3beaaSApple OSS Distributions lltable_link(llt);
2711*aca3beaaSApple OSS Distributions
2712*aca3beaaSApple OSS Distributions return llt;
2713*aca3beaaSApple OSS Distributions }
2714*aca3beaaSApple OSS Distributions
2715*aca3beaaSApple OSS Distributions struct in_ifaddr*
inifa_ifpwithflag(struct ifnet * ifp,uint32_t flag)2716*aca3beaaSApple OSS Distributions inifa_ifpwithflag(struct ifnet * ifp, uint32_t flag)
2717*aca3beaaSApple OSS Distributions {
2718*aca3beaaSApple OSS Distributions struct ifaddr *ifa;
2719*aca3beaaSApple OSS Distributions
2720*aca3beaaSApple OSS Distributions ifnet_lock_shared(ifp);
2721*aca3beaaSApple OSS Distributions TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_link)
2722*aca3beaaSApple OSS Distributions {
2723*aca3beaaSApple OSS Distributions IFA_LOCK_SPIN(ifa);
2724*aca3beaaSApple OSS Distributions if (ifa->ifa_addr->sa_family != AF_INET) {
2725*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2726*aca3beaaSApple OSS Distributions continue;
2727*aca3beaaSApple OSS Distributions }
2728*aca3beaaSApple OSS Distributions if ((((struct in_ifaddr *)ifa)->ia_flags & flag) == flag) {
2729*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(ifa);
2730*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2731*aca3beaaSApple OSS Distributions break;
2732*aca3beaaSApple OSS Distributions }
2733*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2734*aca3beaaSApple OSS Distributions }
2735*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
2736*aca3beaaSApple OSS Distributions
2737*aca3beaaSApple OSS Distributions return (struct in_ifaddr *)ifa;
2738*aca3beaaSApple OSS Distributions }
2739*aca3beaaSApple OSS Distributions
2740*aca3beaaSApple OSS Distributions struct in_ifaddr *
inifa_ifpclatv4(struct ifnet * ifp)2741*aca3beaaSApple OSS Distributions inifa_ifpclatv4(struct ifnet * ifp)
2742*aca3beaaSApple OSS Distributions {
2743*aca3beaaSApple OSS Distributions struct ifaddr *ifa;
2744*aca3beaaSApple OSS Distributions
2745*aca3beaaSApple OSS Distributions ifnet_lock_shared(ifp);
2746*aca3beaaSApple OSS Distributions TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_link)
2747*aca3beaaSApple OSS Distributions {
2748*aca3beaaSApple OSS Distributions uint32_t addr = 0;
2749*aca3beaaSApple OSS Distributions IFA_LOCK_SPIN(ifa);
2750*aca3beaaSApple OSS Distributions if (ifa->ifa_addr->sa_family != AF_INET) {
2751*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2752*aca3beaaSApple OSS Distributions continue;
2753*aca3beaaSApple OSS Distributions }
2754*aca3beaaSApple OSS Distributions
2755*aca3beaaSApple OSS Distributions addr = ntohl(SIN(ifa->ifa_addr)->sin_addr.s_addr);
2756*aca3beaaSApple OSS Distributions if (!IN_LINKLOCAL(addr) &&
2757*aca3beaaSApple OSS Distributions !IN_LOOPBACK(addr)) {
2758*aca3beaaSApple OSS Distributions IFA_ADDREF_LOCKED(ifa);
2759*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2760*aca3beaaSApple OSS Distributions break;
2761*aca3beaaSApple OSS Distributions }
2762*aca3beaaSApple OSS Distributions IFA_UNLOCK(ifa);
2763*aca3beaaSApple OSS Distributions }
2764*aca3beaaSApple OSS Distributions ifnet_lock_done(ifp);
2765*aca3beaaSApple OSS Distributions
2766*aca3beaaSApple OSS Distributions return (struct in_ifaddr *)ifa;
2767*aca3beaaSApple OSS Distributions }
2768*aca3beaaSApple OSS Distributions
2769*aca3beaaSApple OSS Distributions /*
2770*aca3beaaSApple OSS Distributions * IPPROTO_xxx.
2771*aca3beaaSApple OSS Distributions *
2772*aca3beaaSApple OSS Distributions * The switch statement below does nothing at runtime, as it serves as a
2773*aca3beaaSApple OSS Distributions * compile time check to ensure that all of the IPPROTO_xxx constants are
2774*aca3beaaSApple OSS Distributions * unique. This works as long as this routine gets updated each time a
2775*aca3beaaSApple OSS Distributions * new IPPROTO_xxx constant gets added.
2776*aca3beaaSApple OSS Distributions *
2777*aca3beaaSApple OSS Distributions * Any failures at compile time indicates duplicated IPPROTO_xxx values.
2778*aca3beaaSApple OSS Distributions */
2779*aca3beaaSApple OSS Distributions static __attribute__((unused)) void
ipproto_cassert(void)2780*aca3beaaSApple OSS Distributions ipproto_cassert(void)
2781*aca3beaaSApple OSS Distributions {
2782*aca3beaaSApple OSS Distributions /*
2783*aca3beaaSApple OSS Distributions * This is equivalent to _CASSERT() and the compiler wouldn't
2784*aca3beaaSApple OSS Distributions * generate any instructions, thus for compile time only.
2785*aca3beaaSApple OSS Distributions */
2786*aca3beaaSApple OSS Distributions switch ((u_int16_t)0) {
2787*aca3beaaSApple OSS Distributions /* bsd/netinet/in.h */
2788*aca3beaaSApple OSS Distributions case IPPROTO_IP:
2789*aca3beaaSApple OSS Distributions // case IPPROTO_HOPOPTS: // same value as IPPROTO_IP
2790*aca3beaaSApple OSS Distributions case IPPROTO_ICMP:
2791*aca3beaaSApple OSS Distributions case IPPROTO_IGMP:
2792*aca3beaaSApple OSS Distributions case IPPROTO_GGP:
2793*aca3beaaSApple OSS Distributions case IPPROTO_IPV4:
2794*aca3beaaSApple OSS Distributions // #define IPPROTO_IPIP IPPROTO_IPV4
2795*aca3beaaSApple OSS Distributions case IPPROTO_TCP:
2796*aca3beaaSApple OSS Distributions case IPPROTO_ST:
2797*aca3beaaSApple OSS Distributions case IPPROTO_EGP:
2798*aca3beaaSApple OSS Distributions case IPPROTO_PIGP:
2799*aca3beaaSApple OSS Distributions case IPPROTO_RCCMON:
2800*aca3beaaSApple OSS Distributions case IPPROTO_NVPII:
2801*aca3beaaSApple OSS Distributions case IPPROTO_PUP:
2802*aca3beaaSApple OSS Distributions case IPPROTO_ARGUS:
2803*aca3beaaSApple OSS Distributions case IPPROTO_EMCON:
2804*aca3beaaSApple OSS Distributions case IPPROTO_XNET:
2805*aca3beaaSApple OSS Distributions case IPPROTO_CHAOS:
2806*aca3beaaSApple OSS Distributions case IPPROTO_UDP:
2807*aca3beaaSApple OSS Distributions case IPPROTO_MUX:
2808*aca3beaaSApple OSS Distributions case IPPROTO_MEAS:
2809*aca3beaaSApple OSS Distributions case IPPROTO_HMP:
2810*aca3beaaSApple OSS Distributions case IPPROTO_PRM:
2811*aca3beaaSApple OSS Distributions case IPPROTO_IDP:
2812*aca3beaaSApple OSS Distributions case IPPROTO_TRUNK1:
2813*aca3beaaSApple OSS Distributions case IPPROTO_TRUNK2:
2814*aca3beaaSApple OSS Distributions case IPPROTO_LEAF1:
2815*aca3beaaSApple OSS Distributions case IPPROTO_LEAF2:
2816*aca3beaaSApple OSS Distributions case IPPROTO_RDP:
2817*aca3beaaSApple OSS Distributions case IPPROTO_IRTP:
2818*aca3beaaSApple OSS Distributions case IPPROTO_TP:
2819*aca3beaaSApple OSS Distributions case IPPROTO_BLT:
2820*aca3beaaSApple OSS Distributions case IPPROTO_NSP:
2821*aca3beaaSApple OSS Distributions case IPPROTO_INP:
2822*aca3beaaSApple OSS Distributions case IPPROTO_SEP:
2823*aca3beaaSApple OSS Distributions case IPPROTO_3PC:
2824*aca3beaaSApple OSS Distributions case IPPROTO_IDPR:
2825*aca3beaaSApple OSS Distributions case IPPROTO_XTP:
2826*aca3beaaSApple OSS Distributions case IPPROTO_DDP:
2827*aca3beaaSApple OSS Distributions case IPPROTO_CMTP:
2828*aca3beaaSApple OSS Distributions case IPPROTO_TPXX:
2829*aca3beaaSApple OSS Distributions case IPPROTO_IL:
2830*aca3beaaSApple OSS Distributions case IPPROTO_IPV6:
2831*aca3beaaSApple OSS Distributions case IPPROTO_SDRP:
2832*aca3beaaSApple OSS Distributions case IPPROTO_ROUTING:
2833*aca3beaaSApple OSS Distributions case IPPROTO_FRAGMENT:
2834*aca3beaaSApple OSS Distributions case IPPROTO_IDRP:
2835*aca3beaaSApple OSS Distributions case IPPROTO_RSVP:
2836*aca3beaaSApple OSS Distributions case IPPROTO_GRE:
2837*aca3beaaSApple OSS Distributions case IPPROTO_MHRP:
2838*aca3beaaSApple OSS Distributions case IPPROTO_BHA:
2839*aca3beaaSApple OSS Distributions case IPPROTO_ESP:
2840*aca3beaaSApple OSS Distributions case IPPROTO_AH:
2841*aca3beaaSApple OSS Distributions case IPPROTO_INLSP:
2842*aca3beaaSApple OSS Distributions case IPPROTO_SWIPE:
2843*aca3beaaSApple OSS Distributions case IPPROTO_NHRP:
2844*aca3beaaSApple OSS Distributions case IPPROTO_ICMPV6:
2845*aca3beaaSApple OSS Distributions case IPPROTO_NONE:
2846*aca3beaaSApple OSS Distributions case IPPROTO_DSTOPTS:
2847*aca3beaaSApple OSS Distributions case IPPROTO_AHIP:
2848*aca3beaaSApple OSS Distributions case IPPROTO_CFTP:
2849*aca3beaaSApple OSS Distributions case IPPROTO_HELLO:
2850*aca3beaaSApple OSS Distributions case IPPROTO_SATEXPAK:
2851*aca3beaaSApple OSS Distributions case IPPROTO_KRYPTOLAN:
2852*aca3beaaSApple OSS Distributions case IPPROTO_RVD:
2853*aca3beaaSApple OSS Distributions case IPPROTO_IPPC:
2854*aca3beaaSApple OSS Distributions case IPPROTO_ADFS:
2855*aca3beaaSApple OSS Distributions case IPPROTO_SATMON:
2856*aca3beaaSApple OSS Distributions case IPPROTO_VISA:
2857*aca3beaaSApple OSS Distributions case IPPROTO_IPCV:
2858*aca3beaaSApple OSS Distributions case IPPROTO_CPNX:
2859*aca3beaaSApple OSS Distributions case IPPROTO_CPHB:
2860*aca3beaaSApple OSS Distributions case IPPROTO_WSN:
2861*aca3beaaSApple OSS Distributions case IPPROTO_PVP:
2862*aca3beaaSApple OSS Distributions case IPPROTO_BRSATMON:
2863*aca3beaaSApple OSS Distributions case IPPROTO_ND:
2864*aca3beaaSApple OSS Distributions case IPPROTO_WBMON:
2865*aca3beaaSApple OSS Distributions case IPPROTO_WBEXPAK:
2866*aca3beaaSApple OSS Distributions case IPPROTO_EON:
2867*aca3beaaSApple OSS Distributions case IPPROTO_VMTP:
2868*aca3beaaSApple OSS Distributions case IPPROTO_SVMTP:
2869*aca3beaaSApple OSS Distributions case IPPROTO_VINES:
2870*aca3beaaSApple OSS Distributions case IPPROTO_TTP:
2871*aca3beaaSApple OSS Distributions case IPPROTO_IGP:
2872*aca3beaaSApple OSS Distributions case IPPROTO_DGP:
2873*aca3beaaSApple OSS Distributions case IPPROTO_TCF:
2874*aca3beaaSApple OSS Distributions case IPPROTO_IGRP:
2875*aca3beaaSApple OSS Distributions case IPPROTO_OSPFIGP:
2876*aca3beaaSApple OSS Distributions case IPPROTO_SRPC:
2877*aca3beaaSApple OSS Distributions case IPPROTO_LARP:
2878*aca3beaaSApple OSS Distributions case IPPROTO_MTP:
2879*aca3beaaSApple OSS Distributions case IPPROTO_AX25:
2880*aca3beaaSApple OSS Distributions case IPPROTO_IPEIP:
2881*aca3beaaSApple OSS Distributions case IPPROTO_MICP:
2882*aca3beaaSApple OSS Distributions case IPPROTO_SCCSP:
2883*aca3beaaSApple OSS Distributions case IPPROTO_ETHERIP:
2884*aca3beaaSApple OSS Distributions case IPPROTO_ENCAP:
2885*aca3beaaSApple OSS Distributions case IPPROTO_APES:
2886*aca3beaaSApple OSS Distributions case IPPROTO_GMTP:
2887*aca3beaaSApple OSS Distributions case IPPROTO_PIM:
2888*aca3beaaSApple OSS Distributions case IPPROTO_IPCOMP:
2889*aca3beaaSApple OSS Distributions case IPPROTO_PGM:
2890*aca3beaaSApple OSS Distributions case IPPROTO_SCTP:
2891*aca3beaaSApple OSS Distributions case IPPROTO_DIVERT:
2892*aca3beaaSApple OSS Distributions case IPPROTO_RAW:
2893*aca3beaaSApple OSS Distributions case IPPROTO_MAX:
2894*aca3beaaSApple OSS Distributions case IPPROTO_DONE:
2895*aca3beaaSApple OSS Distributions
2896*aca3beaaSApple OSS Distributions /* bsd/netinet/in_private.h */
2897*aca3beaaSApple OSS Distributions case IPPROTO_QUIC:
2898*aca3beaaSApple OSS Distributions ;
2899*aca3beaaSApple OSS Distributions }
2900*aca3beaaSApple OSS Distributions }
2901*aca3beaaSApple OSS Distributions
2902*aca3beaaSApple OSS Distributions static __attribute__((unused)) void
ipsockopt_cassert(void)2903*aca3beaaSApple OSS Distributions ipsockopt_cassert(void)
2904*aca3beaaSApple OSS Distributions {
2905*aca3beaaSApple OSS Distributions switch ((int)0) {
2906*aca3beaaSApple OSS Distributions case 0:
2907*aca3beaaSApple OSS Distributions
2908*aca3beaaSApple OSS Distributions /* bsd/netinet/in.h */
2909*aca3beaaSApple OSS Distributions case IP_OPTIONS:
2910*aca3beaaSApple OSS Distributions case IP_HDRINCL:
2911*aca3beaaSApple OSS Distributions case IP_TOS:
2912*aca3beaaSApple OSS Distributions case IP_TTL:
2913*aca3beaaSApple OSS Distributions case IP_RECVOPTS:
2914*aca3beaaSApple OSS Distributions case IP_RECVRETOPTS:
2915*aca3beaaSApple OSS Distributions case IP_RECVDSTADDR:
2916*aca3beaaSApple OSS Distributions case IP_RETOPTS:
2917*aca3beaaSApple OSS Distributions case IP_MULTICAST_IF:
2918*aca3beaaSApple OSS Distributions case IP_MULTICAST_TTL:
2919*aca3beaaSApple OSS Distributions case IP_MULTICAST_LOOP:
2920*aca3beaaSApple OSS Distributions case IP_ADD_MEMBERSHIP:
2921*aca3beaaSApple OSS Distributions case IP_DROP_MEMBERSHIP:
2922*aca3beaaSApple OSS Distributions case IP_MULTICAST_VIF:
2923*aca3beaaSApple OSS Distributions case IP_RSVP_ON:
2924*aca3beaaSApple OSS Distributions case IP_RSVP_OFF:
2925*aca3beaaSApple OSS Distributions case IP_RSVP_VIF_ON:
2926*aca3beaaSApple OSS Distributions case IP_RSVP_VIF_OFF:
2927*aca3beaaSApple OSS Distributions case IP_PORTRANGE:
2928*aca3beaaSApple OSS Distributions case IP_RECVIF:
2929*aca3beaaSApple OSS Distributions case IP_IPSEC_POLICY:
2930*aca3beaaSApple OSS Distributions case IP_FAITH:
2931*aca3beaaSApple OSS Distributions #ifdef __APPLE__
2932*aca3beaaSApple OSS Distributions case IP_STRIPHDR:
2933*aca3beaaSApple OSS Distributions #endif
2934*aca3beaaSApple OSS Distributions case IP_RECVTTL:
2935*aca3beaaSApple OSS Distributions case IP_BOUND_IF:
2936*aca3beaaSApple OSS Distributions case IP_PKTINFO:
2937*aca3beaaSApple OSS Distributions // #define IP_RECVPKTINFO IP_PKTINFO
2938*aca3beaaSApple OSS Distributions case IP_RECVTOS:
2939*aca3beaaSApple OSS Distributions case IP_DONTFRAG:
2940*aca3beaaSApple OSS Distributions case IP_FW_ADD:
2941*aca3beaaSApple OSS Distributions case IP_FW_DEL:
2942*aca3beaaSApple OSS Distributions case IP_FW_FLUSH:
2943*aca3beaaSApple OSS Distributions case IP_FW_ZERO:
2944*aca3beaaSApple OSS Distributions case IP_FW_GET:
2945*aca3beaaSApple OSS Distributions case IP_FW_RESETLOG:
2946*aca3beaaSApple OSS Distributions case IP_OLD_FW_ADD:
2947*aca3beaaSApple OSS Distributions case IP_OLD_FW_DEL:
2948*aca3beaaSApple OSS Distributions case IP_OLD_FW_FLUSH:
2949*aca3beaaSApple OSS Distributions case IP_OLD_FW_ZERO:
2950*aca3beaaSApple OSS Distributions case IP_OLD_FW_GET:
2951*aca3beaaSApple OSS Distributions case IP_NAT__XXX:
2952*aca3beaaSApple OSS Distributions case IP_OLD_FW_RESETLOG:
2953*aca3beaaSApple OSS Distributions case IP_DUMMYNET_CONFIGURE:
2954*aca3beaaSApple OSS Distributions case IP_DUMMYNET_DEL:
2955*aca3beaaSApple OSS Distributions case IP_DUMMYNET_FLUSH:
2956*aca3beaaSApple OSS Distributions case IP_DUMMYNET_GET:
2957*aca3beaaSApple OSS Distributions case IP_TRAFFIC_MGT_BACKGROUND:
2958*aca3beaaSApple OSS Distributions case IP_MULTICAST_IFINDEX:
2959*aca3beaaSApple OSS Distributions case IP_ADD_SOURCE_MEMBERSHIP:
2960*aca3beaaSApple OSS Distributions case IP_DROP_SOURCE_MEMBERSHIP:
2961*aca3beaaSApple OSS Distributions case IP_BLOCK_SOURCE:
2962*aca3beaaSApple OSS Distributions case IP_UNBLOCK_SOURCE:
2963*aca3beaaSApple OSS Distributions case IP_MSFILTER:
2964*aca3beaaSApple OSS Distributions case MCAST_JOIN_GROUP:
2965*aca3beaaSApple OSS Distributions case MCAST_LEAVE_GROUP:
2966*aca3beaaSApple OSS Distributions case MCAST_JOIN_SOURCE_GROUP:
2967*aca3beaaSApple OSS Distributions case MCAST_LEAVE_SOURCE_GROUP:
2968*aca3beaaSApple OSS Distributions case MCAST_BLOCK_SOURCE:
2969*aca3beaaSApple OSS Distributions case MCAST_UNBLOCK_SOURCE:
2970*aca3beaaSApple OSS Distributions
2971*aca3beaaSApple OSS Distributions /* bsd/netinet/in_private.h */
2972*aca3beaaSApple OSS Distributions case IP_NO_IFT_CELLULAR:
2973*aca3beaaSApple OSS Distributions // #define IP_NO_IFT_PDP IP_NO_IFT_CELLULAR /* deprecated */
2974*aca3beaaSApple OSS Distributions case IP_OUT_IF:
2975*aca3beaaSApple OSS Distributions ;
2976*aca3beaaSApple OSS Distributions }
2977*aca3beaaSApple OSS Distributions }
2978