]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/in_arp.c
xnu-2782.1.97.tar.gz
[apple/xnu.git] / bsd / netinet / in_arp.c
CommitLineData
91447636 1/*
fe8ab488 2 * Copyright (c) 2004-2014 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
39236c6e 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
39236c6e 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
39236c6e 17 *
2d21ac55
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
39236c6e 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
91447636
A
27 */
28/*
29 * Copyright (c) 1982, 1989, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 */
61
62#include <kern/debug.h>
63#include <netinet/in_arp.h>
64#include <sys/types.h>
65#include <sys/param.h>
66#include <sys/kernel_types.h>
67#include <sys/syslog.h>
68#include <sys/systm.h>
69#include <sys/time.h>
70#include <sys/kernel.h>
71#include <sys/mbuf.h>
72#include <sys/sysctl.h>
6d2010ae
A
73#include <sys/mcache.h>
74#include <sys/protosw.h>
91447636
A
75#include <string.h>
76#include <net/if_arp.h>
77#include <net/if_dl.h>
78#include <net/dlil.h>
b7266188 79#include <net/if_types.h>
6d2010ae 80#include <net/if_llreach.h>
91447636 81#include <net/route.h>
39236c6e 82
91447636
A
83#include <netinet/if_ether.h>
84#include <netinet/in_var.h>
b0d623f7 85#include <kern/zalloc.h>
91447636 86
39236c6e 87#define CONST_LLADDR(s) ((const u_char*)((s)->sdl_data + (s)->sdl_nlen))
91447636
A
88
89static const size_t MAX_HW_LEN = 10;
90
b0d623f7
A
91/*
92 * Synchronization notes:
93 *
94 * The global list of ARP entries are stored in llinfo_arp; an entry
95 * gets inserted into the list when the route is created and gets
96 * removed from the list when it is deleted; this is done as part
97 * of RTM_ADD/RTM_RESOLVE/RTM_DELETE in arp_rtrequest().
98 *
99 * Because rnh_lock and rt_lock for the entry are held during those
100 * operations, the same locks (and thus lock ordering) must be used
101 * elsewhere to access the relevant data structure fields:
102 *
103 * la_le.{le_next,le_prev}, la_rt
104 *
105 * - Routing lock (rnh_lock)
106 *
fe8ab488 107 * la_hold, la_asked, la_llreach, la_lastused, la_flags
b0d623f7
A
108 *
109 * - Routing entry lock (rt_lock)
110 *
111 * Due to the dependency on rt_lock, llinfo_arp has the same lifetime
112 * as the route entry itself. When a route is deleted (RTM_DELETE),
113 * it is simply removed from the global list but the memory is not
114 * freed until the route itself is freed.
115 */
39236c6e
A
116struct llinfo_arp {
117 /*
118 * The following are protected by rnh_lock
119 */
120 LIST_ENTRY(llinfo_arp) la_le;
121 struct rtentry *la_rt;
122 /*
123 * The following are protected by rt_lock
124 */
125 struct mbuf *la_hold; /* last packet until resolved/timeout */
126 struct if_llreach *la_llreach; /* link-layer reachability record */
127 u_int64_t la_lastused; /* last used timestamp */
128 u_int32_t la_asked; /* # of requests sent */
129 u_int32_t la_maxtries; /* retry limit */
fe8ab488
A
130 uint32_t la_flags;
131#define LLINFO_RTRFAIL_EVTSENT 0x1 /* sent an ARP event */
39236c6e 132};
91447636
A
133static LIST_HEAD(, llinfo_arp) llinfo_arp;
134
39236c6e
A
135static int arp_timeout_run; /* arp_timeout is scheduled to run */
136static void arp_timeout(void *);
137static void arp_sched_timeout(struct timeval *);
138
139static void arptfree(struct llinfo_arp *, void *);
140static errno_t arp_lookup_route(const struct in_addr *, int,
141 int, route_t *, unsigned int);
142static int arp_getstat SYSCTL_HANDLER_ARGS;
143
144static struct llinfo_arp *arp_llinfo_alloc(int);
145static void arp_llinfo_free(void *);
146static void arp_llinfo_purge(struct rtentry *);
147static void arp_llinfo_get_ri(struct rtentry *, struct rt_reach_info *);
148static void arp_llinfo_get_iflri(struct rtentry *, struct ifnet_llreach_info *);
149
150static __inline void arp_llreach_use(struct llinfo_arp *);
151static __inline int arp_llreach_reachable(struct llinfo_arp *);
152static void arp_llreach_alloc(struct rtentry *, struct ifnet *, void *,
153 unsigned int, boolean_t);
154
155extern int tvtohz(struct timeval *);
156
157static int arpinit_done;
158
159SYSCTL_DECL(_net_link_ether);
160SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "");
161
162/* timer values */
163static int arpt_prune = (5*60*1); /* walk list every 5 minutes */
164SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl,
165 CTLFLAG_RW | CTLFLAG_LOCKED, &arpt_prune, 0, "");
166
167static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
168SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age,
169 CTLFLAG_RW | CTLFLAG_LOCKED, &arpt_keep, 0, "");
170
171static int arpt_down = 20; /* once declared down, don't send for 20 sec */
172SYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time,
173 CTLFLAG_RW | CTLFLAG_LOCKED, &arpt_down, 0, "");
174
175static int arp_llreach_base = (LL_BASE_REACHABLE / 1000); /* seconds */
176SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_llreach_base,
177 CTLFLAG_RW | CTLFLAG_LOCKED, &arp_llreach_base, LL_BASE_REACHABLE,
178 "default ARP link-layer reachability max lifetime (in seconds)");
179
180#define ARP_UNICAST_LIMIT 5 /* # of probes until ARP refresh broadcast */
181static u_int32_t arp_unicast_lim = ARP_UNICAST_LIMIT;
182SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_unicast_lim,
183 CTLFLAG_RW | CTLFLAG_LOCKED, &arp_unicast_lim, ARP_UNICAST_LIMIT,
184 "number of unicast ARP refresh probes before using broadcast");
91447636 185
6d2010ae 186static u_int32_t arp_maxtries = 5;
39236c6e
A
187SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries,
188 CTLFLAG_RW | CTLFLAG_LOCKED, &arp_maxtries, 0, "");
91447636 189
39236c6e
A
190static int useloopback = 1; /* use loopback interface for local traffic */
191SYSCTL_INT(_net_link_ether_inet, OID_AUTO, useloopback,
192 CTLFLAG_RW | CTLFLAG_LOCKED, &useloopback, 0, "");
193
194static int arp_proxyall = 0;
195SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall,
196 CTLFLAG_RW | CTLFLAG_LOCKED, &arp_proxyall, 0, "");
197
198static int arp_sendllconflict = 0;
199SYSCTL_INT(_net_link_ether_inet, OID_AUTO, sendllconflict,
200 CTLFLAG_RW | CTLFLAG_LOCKED, &arp_sendllconflict, 0, "");
91447636 201
39236c6e 202static int log_arp_warnings = 0; /* Thread safe: no accumulated state */
6d2010ae
A
203SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_warnings,
204 CTLFLAG_RW | CTLFLAG_LOCKED,
91447636
A
205 &log_arp_warnings, 0,
206 "log arp warning messages");
207
6d2010ae
A
208static int keep_announcements = 1; /* Thread safe: no aging of state */
209SYSCTL_INT(_net_link_ether_inet, OID_AUTO, keep_announcements,
210 CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
211 &keep_announcements, 0,
212 "keep arp announcements");
213
6d2010ae
A
214static int send_conflicting_probes = 1; /* Thread safe: no accumulated state */
215SYSCTL_INT(_net_link_ether_inet, OID_AUTO, send_conflicting_probes,
216 CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
217 &send_conflicting_probes, 0,
218 "send conflicting link-local arp probes");
219
39236c6e
A
220static int arp_verbose;
221SYSCTL_INT(_net_link_ether_inet, OID_AUTO, verbose,
222 CTLFLAG_RW | CTLFLAG_LOCKED, &arp_verbose, 0, "");
6d2010ae 223
39236c6e 224struct arpstat arpstat;
fe8ab488
A
225SYSCTL_PROC(_net_link_ether_inet, OID_AUTO, stats,
226 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
39236c6e
A
227 0, 0, arp_getstat, "S,arpstat",
228 "ARP statistics (struct arpstat, net/if_arp.h)");
b0d623f7 229
39236c6e
A
230/* these are deprecated (read-only); use net.link.generic.system node instead */
231SYSCTL_INT(_net_link_ether_inet, OID_AUTO, apple_hwcksum_tx,
232 CTLFLAG_RD | CTLFLAG_LOCKED, &hwcksum_tx, 0, "");
91447636 233
39236c6e
A
234SYSCTL_INT(_net_link_ether_inet, OID_AUTO, apple_hwcksum_rx,
235 CTLFLAG_RD | CTLFLAG_LOCKED, &hwcksum_rx, 0, "");
b0d623f7
A
236
237static struct zone *llinfo_arp_zone;
238#define LLINFO_ARP_ZONE_MAX 256 /* maximum elements in zone */
239#define LLINFO_ARP_ZONE_NAME "llinfo_arp" /* name for zone */
240
241void
242arp_init(void)
243{
39236c6e 244 VERIFY(!arpinit_done);
b0d623f7
A
245
246 LIST_INIT(&llinfo_arp);
247
248 llinfo_arp_zone = zinit(sizeof (struct llinfo_arp),
249 LLINFO_ARP_ZONE_MAX * sizeof (struct llinfo_arp), 0,
250 LLINFO_ARP_ZONE_NAME);
251 if (llinfo_arp_zone == NULL)
252 panic("%s: failed allocating llinfo_arp_zone", __func__);
253
254 zone_change(llinfo_arp_zone, Z_EXPAND, TRUE);
6d2010ae 255 zone_change(llinfo_arp_zone, Z_CALLERACCT, FALSE);
b0d623f7
A
256
257 arpinit_done = 1;
b0d623f7
A
258}
259
260static struct llinfo_arp *
39236c6e 261arp_llinfo_alloc(int how)
b0d623f7 262{
39236c6e
A
263 struct llinfo_arp *la;
264
265 la = (how == M_WAITOK) ? zalloc(llinfo_arp_zone) :
266 zalloc_noblock(llinfo_arp_zone);
267 if (la != NULL)
268 bzero(la, sizeof (*la));
269
270 return (la);
b0d623f7
A
271}
272
273static void
274arp_llinfo_free(void *arg)
275{
276 struct llinfo_arp *la = arg;
277
278 if (la->la_le.le_next != NULL || la->la_le.le_prev != NULL) {
279 panic("%s: trying to free %p when it is in use", __func__, la);
280 /* NOTREACHED */
281 }
282
283 /* Just in case there's anything there, free it */
284 if (la->la_hold != NULL) {
285 m_freem(la->la_hold);
286 la->la_hold = NULL;
39236c6e 287 arpstat.purged++;
b0d623f7
A
288 }
289
6d2010ae
A
290 /* Purge any link-layer info caching */
291 VERIFY(la->la_rt->rt_llinfo == la);
292 if (la->la_rt->rt_llinfo_purge != NULL)
293 la->la_rt->rt_llinfo_purge(la->la_rt);
294
b0d623f7
A
295 zfree(llinfo_arp_zone, la);
296}
297
6d2010ae
A
298static void
299arp_llinfo_purge(struct rtentry *rt)
300{
301 struct llinfo_arp *la = rt->rt_llinfo;
302
303 RT_LOCK_ASSERT_HELD(rt);
304 VERIFY(rt->rt_llinfo_purge == arp_llinfo_purge && la != NULL);
305
306 if (la->la_llreach != NULL) {
307 RT_CONVERT_LOCK(rt);
308 ifnet_llreach_free(la->la_llreach);
309 la->la_llreach = NULL;
310 }
311 la->la_lastused = 0;
312}
313
314static void
315arp_llinfo_get_ri(struct rtentry *rt, struct rt_reach_info *ri)
316{
317 struct llinfo_arp *la = rt->rt_llinfo;
318 struct if_llreach *lr = la->la_llreach;
319
320 if (lr == NULL) {
321 bzero(ri, sizeof (*ri));
316670eb
A
322 ri->ri_rssi = IFNET_RSSI_UNKNOWN;
323 ri->ri_lqm = IFNET_LQM_THRESH_OFF;
324 ri->ri_npm = IFNET_NPM_THRESH_UNKNOWN;
6d2010ae
A
325 } else {
326 IFLR_LOCK(lr);
327 /* Export to rt_reach_info structure */
328 ifnet_lr2ri(lr, ri);
316670eb
A
329 /* Export ARP send expiration (calendar) time */
330 ri->ri_snd_expire =
331 ifnet_llreach_up2calexp(lr, la->la_lastused);
332 IFLR_UNLOCK(lr);
333 }
334}
335
336static void
337arp_llinfo_get_iflri(struct rtentry *rt, struct ifnet_llreach_info *iflri)
338{
339 struct llinfo_arp *la = rt->rt_llinfo;
340 struct if_llreach *lr = la->la_llreach;
341
342 if (lr == NULL) {
343 bzero(iflri, sizeof (*iflri));
344 iflri->iflri_rssi = IFNET_RSSI_UNKNOWN;
345 iflri->iflri_lqm = IFNET_LQM_THRESH_OFF;
346 iflri->iflri_npm = IFNET_NPM_THRESH_UNKNOWN;
347 } else {
348 IFLR_LOCK(lr);
349 /* Export to ifnet_llreach_info structure */
350 ifnet_lr2iflri(lr, iflri);
351 /* Export ARP send expiration (uptime) time */
352 iflri->iflri_snd_expire =
353 ifnet_llreach_up2upexp(lr, la->la_lastused);
6d2010ae
A
354 IFLR_UNLOCK(lr);
355 }
356}
357
358void
359arp_llreach_set_reachable(struct ifnet *ifp, void *addr, unsigned int alen)
360{
361 /* Nothing more to do if it's disabled */
362 if (arp_llreach_base == 0)
363 return;
364
365 ifnet_llreach_set_reachable(ifp, ETHERTYPE_IP, addr, alen);
366}
367
368static __inline void
369arp_llreach_use(struct llinfo_arp *la)
370{
371 if (la->la_llreach != NULL)
372 la->la_lastused = net_uptime();
373}
374
375static __inline int
376arp_llreach_reachable(struct llinfo_arp *la)
377{
378 struct if_llreach *lr;
379 const char *why = NULL;
380
381 /* Nothing more to do if it's disabled; pretend it's reachable */
382 if (arp_llreach_base == 0)
383 return (1);
384
385 if ((lr = la->la_llreach) == NULL) {
386 /*
387 * Link-layer reachability record isn't present for this
388 * ARP entry; pretend it's reachable and use it as is.
389 */
390 return (1);
391 } else if (ifnet_llreach_reachable(lr)) {
392 /*
393 * Record is present, it's not shared with other ARP
394 * entries and a packet has recently been received
395 * from the remote host; consider it reachable.
396 */
397 if (lr->lr_reqcnt == 1)
398 return (1);
399
400 /* Prime it up, if this is the first time */
401 if (la->la_lastused == 0) {
402 VERIFY(la->la_llreach != NULL);
403 arp_llreach_use(la);
404 }
405
406 /*
407 * Record is present and shared with one or more ARP
408 * entries, and a packet has recently been received
409 * from the remote host. Since it's shared by more
410 * than one IP addresses, we can't rely on the link-
411 * layer reachability alone; consider it reachable if
412 * this ARP entry has been used "recently."
413 */
414 if (ifnet_llreach_reachable_delta(lr, la->la_lastused))
415 return (1);
416
417 why = "has alias(es) and hasn't been used in a while";
418 } else {
419 why = "haven't heard from it in a while";
420 }
421
39236c6e 422 if (arp_verbose > 1) {
6d2010ae
A
423 char tmp[MAX_IPv4_STR_LEN];
424 u_int64_t now = net_uptime();
425
39236c6e 426 log(LOG_DEBUG, "%s: ARP probe(s) needed for %s; "
6d2010ae 427 "%s [lastused %lld, lastrcvd %lld] secs ago\n",
39236c6e 428 if_name(lr->lr_ifp), inet_ntop(AF_INET,
6d2010ae 429 &SIN(rt_key(la->la_rt))->sin_addr, tmp, sizeof (tmp)), why,
39236c6e
A
430 (la->la_lastused ? (int64_t)(now - la->la_lastused) : -1),
431 (lr->lr_lastrcvd ? (int64_t)(now - lr->lr_lastrcvd) : -1));
6d2010ae
A
432
433 }
434 return (0);
435}
436
437/*
438 * Obtain a link-layer source cache entry for the sender.
439 *
440 * NOTE: This is currently only for ARP/Ethernet.
441 */
442static void
443arp_llreach_alloc(struct rtentry *rt, struct ifnet *ifp, void *addr,
444 unsigned int alen, boolean_t solicited)
445{
446 VERIFY(rt->rt_expire == 0 || rt->rt_rmx.rmx_expire != 0);
447 VERIFY(rt->rt_expire != 0 || rt->rt_rmx.rmx_expire == 0);
39236c6e
A
448
449 if (arp_llreach_base != 0 && rt->rt_expire != 0 &&
450 !(rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
6d2010ae
A
451 ifp->if_addrlen == IF_LLREACH_MAXLEN && /* Ethernet */
452 alen == ifp->if_addrlen) {
453 struct llinfo_arp *la = rt->rt_llinfo;
454 struct if_llreach *lr;
455 const char *why = NULL, *type = "";
456
457 /* Become a regular mutex, just in case */
458 RT_CONVERT_LOCK(rt);
459
460 if ((lr = la->la_llreach) != NULL) {
461 type = (solicited ? "ARP reply" : "ARP announcement");
462 /*
463 * If target has changed, create a new record;
464 * otherwise keep existing record.
465 */
466 IFLR_LOCK(lr);
467 if (bcmp(addr, lr->lr_key.addr, alen) != 0) {
468 IFLR_UNLOCK(lr);
469 /* Purge any link-layer info caching */
470 VERIFY(rt->rt_llinfo_purge != NULL);
471 rt->rt_llinfo_purge(rt);
472 lr = NULL;
473 why = " for different target HW address; "
474 "using new llreach record";
475 } else {
476 lr->lr_probes = 0; /* reset probe count */
477 IFLR_UNLOCK(lr);
478 if (solicited) {
479 why = " for same target HW address; "
480 "keeping existing llreach record";
481 }
482 }
483 }
484
485 if (lr == NULL) {
486 lr = la->la_llreach = ifnet_llreach_alloc(ifp,
487 ETHERTYPE_IP, addr, alen, arp_llreach_base);
488 if (lr != NULL) {
489 lr->lr_probes = 0; /* reset probe count */
490 if (why == NULL)
491 why = "creating new llreach record";
492 }
493 }
494
39236c6e
A
495 /* Bump up retry ceiling to accomodate unicast retries */
496 if (lr != NULL)
497 la->la_maxtries = arp_maxtries + arp_unicast_lim;
498
499 if (arp_verbose > 1 && lr != NULL && why != NULL) {
6d2010ae
A
500 char tmp[MAX_IPv4_STR_LEN];
501
39236c6e
A
502 log(LOG_DEBUG, "%s: %s%s for %s\n", if_name(ifp),
503 type, why, inet_ntop(AF_INET,
6d2010ae
A
504 &SIN(rt_key(rt))->sin_addr, tmp, sizeof (tmp)));
505 }
506 }
507}
508
39236c6e
A
509struct arptf_arg {
510 int draining;
511 uint32_t killed;
512 uint32_t aging;
513 uint32_t sticky;
514 uint32_t found;
515};
516
91447636
A
517/*
518 * Free an arp entry.
519 */
520static void
39236c6e 521arptfree(struct llinfo_arp *la, void *arg)
91447636 522{
39236c6e 523 struct arptf_arg *ap = arg;
91447636 524 struct rtentry *rt = la->la_rt;
b0d623f7
A
525
526 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
b0d623f7 527
39236c6e
A
528 /* rnh_lock acquired by caller protects rt from going away */
529 RT_LOCK(rt);
530
531 VERIFY(rt->rt_expire == 0 || rt->rt_rmx.rmx_expire != 0);
532 VERIFY(rt->rt_expire != 0 || rt->rt_rmx.rmx_expire == 0);
533
534 ap->found++;
535 if (rt->rt_expire == 0 || (rt->rt_flags & RTF_STATIC)) {
536 ap->sticky++;
537 /* ARP entry is permanent? */
15129b1c 538 if (rt->rt_expire == 0) {
39236c6e
A
539 RT_UNLOCK(rt);
540 return;
541 }
542 }
543
544 /* ARP entry hasn't expired and we're not draining? */
545 if (!ap->draining && rt->rt_expire > net_uptime()) {
b0d623f7 546 RT_UNLOCK(rt);
39236c6e
A
547 ap->aging++;
548 return;
549 }
550
551 if (rt->rt_refcnt > 0) {
6d2010ae 552 /*
39236c6e
A
553 * ARP entry has expired, with outstanding refcnt.
554 * If we're not draining, force ARP query to be
555 * generated next time this entry is used.
6d2010ae 556 */
39236c6e
A
557 if (!ap->draining) {
558 struct sockaddr_dl *sdl = SDL(rt->rt_gateway);
559 if (sdl != NULL)
560 sdl->sdl_alen = 0;
561 la->la_asked = 0;
562 rt->rt_flags &= ~RTF_REJECT;
563 }
6d2010ae 564 RT_UNLOCK(rt);
39236c6e 565 } else if (!(rt->rt_flags & RTF_STATIC)) {
b0d623f7 566 /*
39236c6e
A
567 * ARP entry has no outstanding refcnt, and we're either
568 * draining or it has expired; delete it from the routing
569 * table. Safe to drop rt_lock and use rt_key, since holding
b0d623f7
A
570 * rnh_lock here prevents another thread from calling
571 * rt_setgate() on this route.
572 */
573 RT_UNLOCK(rt);
39236c6e
A
574 rtrequest_locked(RTM_DELETE, rt_key(rt), NULL,
575 rt_mask(rt), 0, NULL);
576 arpstat.timeouts++;
577 ap->killed++;
578 } else {
579 /* ARP entry is static; let it linger */
580 RT_UNLOCK(rt);
91447636 581 }
91447636
A
582}
583
d1ecb069 584void
39236c6e 585in_arpdrain(void *arg)
91447636 586{
39236c6e 587#pragma unused(arg)
0c530ab8 588 struct llinfo_arp *la, *ola;
39236c6e
A
589 struct arptf_arg farg;
590
591 if (arp_verbose)
592 log(LOG_DEBUG, "%s: draining ARP entries\n", __func__);
91447636 593
b0d623f7 594 lck_mtx_lock(rnh_lock);
0c530ab8 595 la = llinfo_arp.lh_first;
39236c6e
A
596 bzero(&farg, sizeof (farg));
597 farg.draining = 1;
598 while ((ola = la) != NULL) {
91447636 599 la = la->la_le.le_next;
39236c6e
A
600 arptfree(ola, &farg);
601 }
602 if (arp_verbose) {
603 log(LOG_DEBUG, "%s: found %u, aging %u, sticky %u, killed %u\n",
604 __func__, farg.found, farg.aging, farg.sticky, farg.killed);
91447636 605 }
b0d623f7 606 lck_mtx_unlock(rnh_lock);
d1ecb069
A
607}
608
39236c6e
A
609/*
610 * Timeout routine. Age arp_tab entries periodically.
611 */
612static void
613arp_timeout(void *arg)
6d2010ae 614{
39236c6e
A
615#pragma unused(arg)
616 struct llinfo_arp *la, *ola;
617 struct timeval atv;
618 struct arptf_arg farg;
6d2010ae 619
39236c6e
A
620 lck_mtx_lock(rnh_lock);
621 la = llinfo_arp.lh_first;
622 bzero(&farg, sizeof (farg));
623 while ((ola = la) != NULL) {
624 la = la->la_le.le_next;
625 arptfree(ola, &farg);
626 }
627 if (arp_verbose) {
628 log(LOG_DEBUG, "%s: found %u, aging %u, sticky %u, killed %u\n",
629 __func__, farg.found, farg.aging, farg.sticky, farg.killed);
630 }
631 atv.tv_usec = 0;
632 atv.tv_sec = arpt_prune;
633 /* re-arm the timer if there's work to do */
634 arp_timeout_run = 0;
635 if (farg.aging > 0)
636 arp_sched_timeout(&atv);
637 else if (arp_verbose)
638 log(LOG_DEBUG, "%s: not rescheduling timer\n", __func__);
639 lck_mtx_unlock(rnh_lock);
6d2010ae
A
640}
641
d1ecb069 642static void
39236c6e 643arp_sched_timeout(struct timeval *atv)
d1ecb069 644{
39236c6e
A
645 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
646
647 if (!arp_timeout_run) {
648 struct timeval tv;
649
650 if (atv == NULL) {
651 tv.tv_usec = 0;
652 tv.tv_sec = MAX(arpt_prune / 5, 1);
653 atv = &tv;
654 }
655 if (arp_verbose) {
656 log(LOG_DEBUG, "%s: timer scheduled in "
657 "T+%llus.%lluu\n", __func__,
658 (uint64_t)atv->tv_sec, (uint64_t)atv->tv_usec);
659 }
660 arp_timeout_run = 1;
661 timeout(arp_timeout, NULL, tvtohz(atv));
662 }
91447636
A
663}
664
665/*
39236c6e 666 * ifa_rtrequest() callback
91447636
A
667 */
668static void
39236c6e 669arp_rtrequest(int req, struct rtentry *rt, struct sockaddr *sa)
91447636 670{
39236c6e 671#pragma unused(sa)
91447636 672 struct sockaddr *gate = rt->rt_gateway;
b0d623f7 673 struct llinfo_arp *la = rt->rt_llinfo;
39236c6e
A
674 static struct sockaddr_dl null_sdl =
675 { .sdl_len = sizeof (null_sdl), .sdl_family = AF_LINK };
6d2010ae 676 uint64_t timenow;
39236c6e 677 char buf[MAX_IPv4_STR_LEN];
91447636 678
39236c6e 679 VERIFY(arpinit_done);
b0d623f7
A
680 lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_OWNED);
681 RT_LOCK_ASSERT_HELD(rt);
91447636
A
682
683 if (rt->rt_flags & RTF_GATEWAY)
684 return;
39236c6e 685
6d2010ae 686 timenow = net_uptime();
91447636 687 switch (req) {
91447636
A
688 case RTM_ADD:
689 /*
690 * XXX: If this is a manually added route to interface
691 * such as older version of routed or gated might provide,
692 * restore cloning bit.
693 */
39236c6e
A
694 if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != NULL &&
695 SIN(rt_mask(rt))->sin_addr.s_addr != INADDR_BROADCAST)
91447636 696 rt->rt_flags |= RTF_CLONING;
39236c6e 697
91447636
A
698 if (rt->rt_flags & RTF_CLONING) {
699 /*
700 * Case 1: This route should come from a route to iface.
701 */
39236c6e 702 if (rt_setgate(rt, rt_key(rt), SA(&null_sdl)) == 0) {
b0d623f7
A
703 gate = rt->rt_gateway;
704 SDL(gate)->sdl_type = rt->rt_ifp->if_type;
705 SDL(gate)->sdl_index = rt->rt_ifp->if_index;
706 /*
707 * In case we're called before 1.0 sec.
708 * has elapsed.
709 */
6d2010ae 710 rt_setexpire(rt, MAX(timenow, 1));
b0d623f7 711 }
91447636
A
712 break;
713 }
714 /* Announce a new entry if requested. */
b0d623f7 715 if (rt->rt_flags & RTF_ANNOUNCE) {
6d2010ae
A
716 if (la != NULL)
717 arp_llreach_use(la); /* Mark use timestamp */
b0d623f7
A
718 RT_UNLOCK(rt);
719 dlil_send_arp(rt->rt_ifp, ARPOP_REQUEST,
316670eb 720 SDL(gate), rt_key(rt), NULL, rt_key(rt), 0);
b0d623f7 721 RT_LOCK(rt);
39236c6e 722 arpstat.txannounces++;
b0d623f7 723 }
39236c6e 724 /* FALLTHRU */
91447636
A
725 case RTM_RESOLVE:
726 if (gate->sa_family != AF_LINK ||
39236c6e
A
727 gate->sa_len < sizeof (null_sdl)) {
728 arpstat.invalidreqs++;
729 log(LOG_ERR, "%s: route to %s has bad gateway address "
730 "(sa_family %u sa_len %u) on %s\n",
731 __func__, inet_ntop(AF_INET,
732 &SIN(rt_key(rt))->sin_addr.s_addr, buf,
733 sizeof (buf)), gate->sa_family, gate->sa_len,
734 if_name(rt->rt_ifp));
91447636
A
735 break;
736 }
737 SDL(gate)->sdl_type = rt->rt_ifp->if_type;
738 SDL(gate)->sdl_index = rt->rt_ifp->if_index;
39236c6e
A
739
740 if (la != NULL)
91447636 741 break; /* This happens on a route change */
39236c6e 742
91447636
A
743 /*
744 * Case 2: This route may come from cloning, or a manual route
745 * add with a LL address.
746 */
39236c6e 747 rt->rt_llinfo = la = arp_llinfo_alloc(M_WAITOK);
b0d623f7 748 if (la == NULL) {
39236c6e 749 arpstat.reqnobufs++;
91447636
A
750 break;
751 }
39236c6e
A
752 rt->rt_llinfo_get_ri = arp_llinfo_get_ri;
753 rt->rt_llinfo_get_iflri = arp_llinfo_get_iflri;
754 rt->rt_llinfo_purge = arp_llinfo_purge;
755 rt->rt_llinfo_free = arp_llinfo_free;
91447636 756 rt->rt_flags |= RTF_LLINFO;
39236c6e 757 la->la_rt = rt;
91447636 758 LIST_INSERT_HEAD(&llinfo_arp, la, la_le);
39236c6e
A
759 arpstat.inuse++;
760
761 /* We have at least one entry; arm the timer if not already */
762 arp_sched_timeout(NULL);
91447636 763
91447636
A
764 /*
765 * This keeps the multicast addresses from showing up
766 * in `arp -a' listings as unresolved. It's not actually
6d2010ae
A
767 * functional. Then the same for broadcast. For IPv4
768 * link-local address, keep the entry around even after
769 * it has expired.
91447636
A
770 */
771 if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) {
b0d623f7
A
772 RT_UNLOCK(rt);
773 dlil_resolve_multi(rt->rt_ifp, rt_key(rt), gate,
39236c6e 774 sizeof (struct sockaddr_dl));
b0d623f7 775 RT_LOCK(rt);
6d2010ae 776 rt_setexpire(rt, 0);
39236c6e
A
777 } else if (in_broadcast(SIN(rt_key(rt))->sin_addr,
778 rt->rt_ifp)) {
779 struct sockaddr_dl *gate_ll = SDL(gate);
780 size_t broadcast_len;
b0d623f7 781 ifnet_llbroadcast_copy_bytes(rt->rt_ifp,
39236c6e 782 LLADDR(gate_ll), sizeof (gate_ll->sdl_data),
b0d623f7 783 &broadcast_len);
91447636
A
784 gate_ll->sdl_alen = broadcast_len;
785 gate_ll->sdl_family = AF_LINK;
39236c6e 786 gate_ll->sdl_len = sizeof (struct sockaddr_dl);
593a1d5f 787 /* In case we're called before 1.0 sec. has elapsed */
6d2010ae 788 rt_setexpire(rt, MAX(timenow, 1));
39236c6e
A
789 } else if (IN_LINKLOCAL(ntohl(SIN(rt_key(rt))->
790 sin_addr.s_addr))) {
6d2010ae 791 rt->rt_flags |= RTF_STATIC;
91447636 792 }
91447636 793
39236c6e
A
794 /* Set default maximum number of retries */
795 la->la_maxtries = arp_maxtries;
796
6d2010ae
A
797 /* Become a regular mutex, just in case */
798 RT_CONVERT_LOCK(rt);
799 IFA_LOCK_SPIN(rt->rt_ifa);
91447636
A
800 if (SIN(rt_key(rt))->sin_addr.s_addr ==
801 (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) {
6d2010ae
A
802 IFA_UNLOCK(rt->rt_ifa);
803 /*
804 * This test used to be
805 * if (loif.if_flags & IFF_UP)
806 * It allowed local traffic to be forced through the
807 * hardware by configuring the loopback down. However,
808 * it causes problems during network configuration
809 * for boards that can't receive packets they send.
810 * It is now necessary to clear "useloopback" and
811 * remove the route to force traffic out to the
812 * hardware.
813 */
814 rt_setexpire(rt, 0);
815 ifnet_lladdr_copy_bytes(rt->rt_ifp, LLADDR(SDL(gate)),
816 SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen);
d1ecb069 817 if (useloopback) {
6d2010ae
A
818 if (rt->rt_ifp != lo_ifp) {
819 /*
820 * Purge any link-layer info caching.
821 */
822 if (rt->rt_llinfo_purge != NULL)
823 rt->rt_llinfo_purge(rt);
824
825 /*
826 * Adjust route ref count for the
827 * interfaces.
828 */
829 if (rt->rt_if_ref_fn != NULL) {
830 rt->rt_if_ref_fn(lo_ifp, 1);
831 rt->rt_if_ref_fn(rt->rt_ifp, -1);
832 }
d1ecb069 833 }
2d21ac55 834 rt->rt_ifp = lo_ifp;
39236c6e
A
835 /*
836 * If rmx_mtu is not locked, update it
837 * to the MTU used by the new interface.
838 */
839 if (!(rt->rt_rmx.rmx_locks & RTV_MTU))
840 rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
d1ecb069 841 }
6d2010ae
A
842 } else {
843 IFA_UNLOCK(rt->rt_ifa);
91447636
A
844 }
845 break;
846
847 case RTM_DELETE:
39236c6e 848 if (la == NULL)
91447636 849 break;
b0d623f7
A
850 /*
851 * Unchain it but defer the actual freeing until the route
852 * itself is to be freed. rt->rt_llinfo still points to
853 * llinfo_arp, and likewise, la->la_rt still points to this
854 * route entry, except that RTF_LLINFO is now cleared.
855 */
91447636 856 LIST_REMOVE(la, la_le);
b0d623f7
A
857 la->la_le.le_next = NULL;
858 la->la_le.le_prev = NULL;
39236c6e 859 arpstat.inuse--;
6d2010ae
A
860
861 /*
862 * Purge any link-layer info caching.
863 */
864 if (rt->rt_llinfo_purge != NULL)
865 rt->rt_llinfo_purge(rt);
866
91447636 867 rt->rt_flags &= ~RTF_LLINFO;
6d2010ae 868 if (la->la_hold != NULL) {
91447636 869 m_freem(la->la_hold);
6d2010ae 870 la->la_hold = NULL;
39236c6e 871 arpstat.purged++;
6d2010ae 872 }
91447636
A
873 }
874}
875
876/*
877 * convert hardware address to hex string for logging errors.
878 */
879static const char *
39236c6e 880sdl_addr_to_hex(const struct sockaddr_dl *sdl, char *orig_buf, int buflen)
91447636 881{
39236c6e
A
882 char *buf = orig_buf;
883 int i;
884 const u_char *lladdr = (u_char *)(size_t)sdl->sdl_data;
885 int maxbytes = buflen / 3;
886
91447636
A
887 if (maxbytes > sdl->sdl_alen) {
888 maxbytes = sdl->sdl_alen;
39236c6e 889 }
91447636
A
890 *buf = '\0';
891 for (i = 0; i < maxbytes; i++) {
892 snprintf(buf, 3, "%02x", lladdr[i]);
893 buf += 2;
894 *buf = (i == maxbytes - 1) ? '\0' : ':';
895 buf++;
896 }
897 return (orig_buf);
898}
899
900/*
901 * arp_lookup_route will lookup the route for a given address.
902 *
b0d623f7
A
903 * The address must be for a host on a local network on this interface.
904 * If the returned route is non-NULL, the route is locked and the caller
905 * is responsible for unlocking it and releasing its reference.
91447636
A
906 */
907static errno_t
b0d623f7
A
908arp_lookup_route(const struct in_addr *addr, int create, int proxy,
909 route_t *route, unsigned int ifscope)
91447636 910{
39236c6e
A
911 struct sockaddr_inarp sin =
912 { sizeof (sin), AF_INET, 0, { 0 }, { 0 }, 0, 0 };
2d21ac55 913 const char *why = NULL;
91447636 914 errno_t error = 0;
b0d623f7
A
915 route_t rt;
916
917 *route = NULL;
91447636
A
918
919 sin.sin_addr.s_addr = addr->s_addr;
920 sin.sin_other = proxy ? SIN_PROXY : 0;
c910b4d9 921
6d2010ae
A
922 /*
923 * If the destination is a link-local address, don't
924 * constrain the lookup (don't scope it).
925 */
926 if (IN_LINKLOCAL(ntohl(addr->s_addr)))
927 ifscope = IFSCOPE_NONE;
928
39236c6e 929 rt = rtalloc1_scoped((struct sockaddr *)&sin, create, 0, ifscope);
b0d623f7
A
930 if (rt == NULL)
931 return (ENETUNREACH);
932
933 RT_LOCK(rt);
934
935 if (rt->rt_flags & RTF_GATEWAY) {
91447636 936 why = "host is not on local network";
91447636 937 error = ENETUNREACH;
b0d623f7 938 } else if (!(rt->rt_flags & RTF_LLINFO)) {
91447636 939 why = "could not allocate llinfo";
91447636 940 error = ENOMEM;
b0d623f7 941 } else if (rt->rt_gateway->sa_family != AF_LINK) {
91447636 942 why = "gateway route is not ours";
91447636
A
943 error = EPROTONOSUPPORT;
944 }
b0d623f7
A
945
946 if (error != 0) {
39236c6e 947 if (create && (arp_verbose || log_arp_warnings)) {
b0d623f7 948 char tmp[MAX_IPv4_STR_LEN];
39236c6e
A
949 log(LOG_DEBUG, "%s: link#%d %s failed: %s\n",
950 __func__, ifscope, inet_ntop(AF_INET, addr, tmp,
b0d623f7
A
951 sizeof (tmp)), why);
952 }
953
954 /*
955 * If there are no references to this route, and it is
956 * a cloned route, and not static, and ARP had created
957 * the route, then purge it from the routing table as
958 * it is probably bogus.
959 */
960 if (rt->rt_refcnt == 1 &&
961 (rt->rt_flags & (RTF_WASCLONED | RTF_STATIC)) ==
962 RTF_WASCLONED) {
963 /*
964 * Prevent another thread from modiying rt_key,
965 * rt_gateway via rt_setgate() after rt_lock is
966 * dropped by marking the route as defunct.
967 */
968 rt->rt_flags |= RTF_CONDEMNED;
969 RT_UNLOCK(rt);
970 rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
39236c6e 971 rt_mask(rt), rt->rt_flags, NULL);
b0d623f7
A
972 rtfree(rt);
973 } else {
974 RT_REMREF_LOCKED(rt);
975 RT_UNLOCK(rt);
976 }
977 return (error);
91447636 978 }
91447636 979
b0d623f7
A
980 /*
981 * Caller releases reference and does RT_UNLOCK(rt).
982 */
983 *route = rt;
984 return (0);
985}
91447636 986
b0d623f7
A
987/*
988 * This is the ARP pre-output routine; care must be taken to ensure that
989 * the "hint" route never gets freed via rtfree(), since the caller may
990 * have stored it inside a struct route with a reference held for that
991 * placeholder.
992 */
91447636 993errno_t
b0d623f7
A
994arp_lookup_ip(ifnet_t ifp, const struct sockaddr_in *net_dest,
995 struct sockaddr_dl *ll_dest, size_t ll_dest_len, route_t hint,
996 mbuf_t packet)
91447636 997{
b0d623f7 998 route_t route = NULL; /* output route */
91447636 999 errno_t result = 0;
39236c6e
A
1000 struct sockaddr_dl *gateway;
1001 struct llinfo_arp *llinfo = NULL;
6d2010ae
A
1002 uint64_t timenow;
1003 int unreachable = 0;
fe8ab488
A
1004 struct if_llreach *lr;
1005 struct ifaddr *rt_ifa;
1006 struct sockaddr *sa;
1007 uint32_t rtflags;
1008 struct sockaddr_dl sdl;
b0d623f7 1009
91447636 1010 if (net_dest->sin_family != AF_INET)
b0d623f7
A
1011 return (EAFNOSUPPORT);
1012
91447636 1013 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
b0d623f7
A
1014 return (ENETDOWN);
1015
91447636
A
1016 /*
1017 * If we were given a route, verify the route and grab the gateway
1018 */
b0d623f7
A
1019 if (hint != NULL) {
1020 /*
1021 * Callee holds a reference on the route and returns
1022 * with the route entry locked, upon success.
1023 */
316670eb 1024 result = route_to_gwroute((const struct sockaddr *)
b0d623f7 1025 net_dest, hint, &route);
91447636 1026 if (result != 0)
b0d623f7
A
1027 return (result);
1028 if (route != NULL)
1029 RT_LOCK_ASSERT_HELD(route);
91447636 1030 }
b0d623f7 1031
91447636 1032 if (packet->m_flags & M_BCAST) {
39236c6e 1033 size_t broadcast_len;
91447636 1034 bzero(ll_dest, ll_dest_len);
b0d623f7
A
1035 result = ifnet_llbroadcast_copy_bytes(ifp, LLADDR(ll_dest),
1036 ll_dest_len - offsetof(struct sockaddr_dl, sdl_data),
1037 &broadcast_len);
1038 if (result == 0) {
1039 ll_dest->sdl_alen = broadcast_len;
1040 ll_dest->sdl_family = AF_LINK;
39236c6e 1041 ll_dest->sdl_len = sizeof (struct sockaddr_dl);
91447636 1042 }
b0d623f7 1043 goto release;
91447636
A
1044 }
1045 if (packet->m_flags & M_MCAST) {
b0d623f7
A
1046 if (route != NULL)
1047 RT_UNLOCK(route);
1048 result = dlil_resolve_multi(ifp,
39236c6e
A
1049 (const struct sockaddr *)net_dest,
1050 (struct sockaddr *)ll_dest, ll_dest_len);
b0d623f7
A
1051 if (route != NULL)
1052 RT_LOCK(route);
1053 goto release;
91447636 1054 }
b0d623f7 1055
91447636
A
1056 /*
1057 * If we didn't find a route, or the route doesn't have
1058 * link layer information, trigger the creation of the
1059 * route and link layer information.
1060 */
b0d623f7
A
1061 if (route == NULL || route->rt_llinfo == NULL) {
1062 /* Clean up now while we can */
1063 if (route != NULL) {
1064 if (route == hint) {
1065 RT_REMREF_LOCKED(route);
1066 RT_UNLOCK(route);
1067 } else {
1068 RT_UNLOCK(route);
1069 rtfree(route);
1070 }
1071 }
1072 /*
1073 * Callee holds a reference on the route and returns
1074 * with the route entry locked, upon success.
1075 */
c910b4d9
A
1076 result = arp_lookup_route(&net_dest->sin_addr, 1, 0, &route,
1077 ifp->if_index);
b0d623f7
A
1078 if (result == 0)
1079 RT_LOCK_ASSERT_HELD(route);
1080 }
1081
6d2010ae 1082 if (result || route == NULL || (llinfo = route->rt_llinfo) == NULL) {
b0d623f7
A
1083 /* In case result is 0 but no route, return an error */
1084 if (result == 0)
1085 result = EHOSTUNREACH;
1086
39236c6e
A
1087 if (route != NULL && route->rt_llinfo == NULL) {
1088 char tmp[MAX_IPv4_STR_LEN];
1089 log(LOG_ERR, "%s: can't allocate llinfo for %s\n",
1090 __func__, inet_ntop(AF_INET, &net_dest->sin_addr,
1091 tmp, sizeof (tmp)));
1092 }
b0d623f7 1093 goto release;
91447636 1094 }
b0d623f7 1095
91447636
A
1096 /*
1097 * Now that we have the right route, is it filled in?
1098 */
1099 gateway = SDL(route->rt_gateway);
6d2010ae
A
1100 timenow = net_uptime();
1101 VERIFY(route->rt_expire == 0 || route->rt_rmx.rmx_expire != 0);
1102 VERIFY(route->rt_expire != 0 || route->rt_rmx.rmx_expire == 0);
1103 if ((route->rt_expire == 0 ||
1104 route->rt_expire > timenow) && gateway != NULL &&
1105 gateway->sdl_family == AF_LINK && gateway->sdl_alen != 0 &&
1106 !(unreachable = !arp_llreach_reachable(llinfo))) {
91447636 1107 bcopy(gateway, ll_dest, MIN(gateway->sdl_len, ll_dest_len));
b0d623f7 1108 result = 0;
6d2010ae 1109 arp_llreach_use(llinfo); /* Mark use timestamp */
fe8ab488
A
1110 /*
1111 * Start the unicast probe right before the entry expires.
1112 */
1113 lr = llinfo->la_llreach;
1114 if (lr == NULL)
1115 goto release;
1116 rt_ifa = route->rt_ifa;
1117 /* Become a regular mutex, just in case */
1118 RT_CONVERT_LOCK(route);
1119 IFLR_LOCK_SPIN(lr);
1120 if (route->rt_expire <= timenow + arp_unicast_lim &&
1121 ifp->if_addrlen == IF_LLREACH_MAXLEN &&
1122 lr->lr_probes <= arp_unicast_lim) {
1123 lr->lr_probes++;
1124 bzero(&sdl, sizeof (sdl));
1125 sdl.sdl_alen = ifp->if_addrlen;
1126 bcopy(&lr->lr_key.addr, LLADDR(&sdl),
1127 ifp->if_addrlen);
1128 IFLR_UNLOCK(lr);
1129 IFA_LOCK_SPIN(rt_ifa);
1130 IFA_ADDREF_LOCKED(rt_ifa);
1131 sa = rt_ifa->ifa_addr;
1132 IFA_UNLOCK(rt_ifa);
1133 rtflags = route->rt_flags;
1134 RT_UNLOCK(route);
1135 dlil_send_arp(ifp, ARPOP_REQUEST, NULL, sa,
1136 (const struct sockaddr_dl *)&sdl,
1137 (const struct sockaddr *)net_dest, rtflags);
1138 IFA_REMREF(rt_ifa);
1139 RT_LOCK(route);
1140 } else
1141 IFLR_UNLOCK(lr);
b0d623f7 1142 goto release;
6d2010ae
A
1143 } else if (unreachable) {
1144 /*
1145 * Discard existing answer in case we need to probe.
1146 */
1147 gateway->sdl_alen = 0;
91447636 1148 }
b0d623f7
A
1149
1150 if (ifp->if_flags & IFF_NOARP) {
1151 result = ENOTSUP;
1152 goto release;
1153 }
1154
91447636
A
1155 /*
1156 * Route wasn't complete/valid. We need to arp.
1157 */
b0d623f7 1158 if (packet != NULL) {
39236c6e 1159 if (llinfo->la_hold != NULL) {
91447636 1160 m_freem(llinfo->la_hold);
39236c6e
A
1161 arpstat.dropped++;
1162 }
91447636
A
1163 llinfo->la_hold = packet;
1164 }
b0d623f7 1165
6d2010ae 1166 if (route->rt_expire) {
91447636 1167 route->rt_flags &= ~RTF_REJECT;
39236c6e 1168 if (llinfo->la_asked == 0 || route->rt_expire != timenow) {
6d2010ae 1169 rt_setexpire(route, timenow);
39236c6e 1170 if (llinfo->la_asked++ < llinfo->la_maxtries) {
fe8ab488
A
1171 struct kev_msg ev_msg;
1172 struct kev_in_arpfailure in_arpfailure;
1173 boolean_t sendkev = FALSE;
6d2010ae 1174
fe8ab488
A
1175 rt_ifa = route->rt_ifa;
1176 lr = llinfo->la_llreach;
6d2010ae
A
1177 /* Become a regular mutex, just in case */
1178 RT_CONVERT_LOCK(route);
1179 /* Update probe count, if applicable */
39236c6e
A
1180 if (lr != NULL) {
1181 IFLR_LOCK_SPIN(lr);
1182 lr->lr_probes++;
39236c6e 1183 IFLR_UNLOCK(lr);
6d2010ae 1184 }
fe8ab488
A
1185 if (ifp->if_addrlen == IF_LLREACH_MAXLEN &&
1186 route->rt_flags & RTF_ROUTER &&
1187 llinfo->la_asked > 1) {
1188 sendkev = TRUE;
1189 llinfo->la_flags |= LLINFO_RTRFAIL_EVTSENT;
1190 }
6d2010ae
A
1191 IFA_LOCK_SPIN(rt_ifa);
1192 IFA_ADDREF_LOCKED(rt_ifa);
1193 sa = rt_ifa->ifa_addr;
1194 IFA_UNLOCK(rt_ifa);
39236c6e 1195 arp_llreach_use(llinfo); /* Mark use tstamp */
316670eb 1196 rtflags = route->rt_flags;
b0d623f7 1197 RT_UNLOCK(route);
39236c6e 1198 dlil_send_arp(ifp, ARPOP_REQUEST, NULL, sa,
fe8ab488
A
1199 NULL, (const struct sockaddr *)net_dest,
1200 rtflags);
6d2010ae 1201 IFA_REMREF(rt_ifa);
fe8ab488
A
1202 if (sendkev) {
1203 bzero(&ev_msg, sizeof(ev_msg));
1204 bzero(&in_arpfailure,
1205 sizeof(in_arpfailure));
1206 in_arpfailure.link_data.if_family =
1207 ifp->if_family;
1208 in_arpfailure.link_data.if_unit =
1209 ifp->if_unit;
1210 strlcpy(in_arpfailure.link_data.if_name,
1211 ifp->if_name, IFNAMSIZ);
1212 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1213 ev_msg.kev_class = KEV_NETWORK_CLASS;
1214 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1215 ev_msg.event_code =
1216 KEV_INET_ARPRTRFAILURE;
1217 ev_msg.dv[0].data_ptr = &in_arpfailure;
1218 ev_msg.dv[0].data_length =
1219 sizeof(struct
1220 kev_in_arpfailure);
1221 kev_post_msg(&ev_msg);
1222 }
b0d623f7 1223 result = EJUSTRETURN;
fe8ab488 1224 RT_LOCK(route);
b0d623f7
A
1225 goto release;
1226 } else {
91447636 1227 route->rt_flags |= RTF_REJECT;
39236c6e
A
1228 rt_setexpire(route,
1229 route->rt_expire + arpt_down);
91447636 1230 llinfo->la_asked = 0;
6d2010ae
A
1231 /*
1232 * Clear la_hold; don't free the packet since
1233 * we're not returning EJUSTRETURN; the caller
1234 * will handle the freeing.
1235 */
2d21ac55 1236 llinfo->la_hold = NULL;
b0d623f7
A
1237 result = EHOSTUNREACH;
1238 goto release;
91447636
A
1239 }
1240 }
1241 }
b0d623f7
A
1242
1243 /* The packet is now held inside la_hold (can "packet" be NULL?) */
1244 result = EJUSTRETURN;
1245
1246release:
39236c6e
A
1247 if (result == EHOSTUNREACH)
1248 arpstat.dropped++;
1249
b0d623f7
A
1250 if (route != NULL) {
1251 if (route == hint) {
1252 RT_REMREF_LOCKED(route);
1253 RT_UNLOCK(route);
1254 } else {
1255 RT_UNLOCK(route);
1256 rtfree(route);
1257 }
1258 }
1259 return (result);
91447636
A
1260}
1261
1262errno_t
39236c6e
A
1263arp_ip_handle_input(ifnet_t ifp, u_short arpop,
1264 const struct sockaddr_dl *sender_hw, const struct sockaddr_in *sender_ip,
1265 const struct sockaddr_in *target_ip)
91447636 1266{
39236c6e 1267 char ipv4str[MAX_IPv4_STR_LEN];
b0d623f7
A
1268 struct sockaddr_dl proxied;
1269 struct sockaddr_dl *gateway, *target_hw = NULL;
1270 struct ifaddr *ifa;
91447636
A
1271 struct in_ifaddr *ia;
1272 struct in_ifaddr *best_ia = NULL;
6d2010ae 1273 struct sockaddr_in best_ia_sin;
91447636 1274 route_t route = NULL;
39236c6e 1275 char buf[3 * MAX_HW_LEN]; /* enough for MAX_HW_LEN byte hw address */
91447636 1276 struct llinfo_arp *llinfo;
91447636 1277 errno_t error;
2d21ac55 1278 int created_announcement = 0;
b7266188 1279 int bridged = 0, is_bridge = 0;
6d2010ae 1280
39236c6e
A
1281 arpstat.received++;
1282
91447636 1283 /* Do not respond to requests for 0.0.0.0 */
39236c6e 1284 if (target_ip->sin_addr.s_addr == INADDR_ANY && arpop == ARPOP_REQUEST)
b0d623f7 1285 goto done;
6d2010ae
A
1286
1287 if (ifp->if_bridge)
b7266188
A
1288 bridged = 1;
1289 if (ifp->if_type == IFT_BRIDGE)
1290 is_bridge = 1;
b0d623f7 1291
39236c6e
A
1292 if (arpop == ARPOP_REPLY)
1293 arpstat.rxreplies++;
1294
91447636
A
1295 /*
1296 * Determine if this ARP is for us
6d2010ae 1297 * For a bridge, we want to check the address irrespective
b7266188 1298 * of the receive interface.
91447636 1299 */
b0d623f7
A
1300 lck_rw_lock_shared(in_ifaddr_rwlock);
1301 TAILQ_FOREACH(ia, INADDR_HASH(target_ip->sin_addr.s_addr), ia_hash) {
6d2010ae 1302 IFA_LOCK_SPIN(&ia->ia_ifa);
b7266188 1303 if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
6d2010ae 1304 (ia->ia_ifp == ifp)) &&
b0d623f7 1305 ia->ia_addr.sin_addr.s_addr == target_ip->sin_addr.s_addr) {
6d2010ae
A
1306 best_ia = ia;
1307 best_ia_sin = best_ia->ia_addr;
1308 IFA_ADDREF_LOCKED(&ia->ia_ifa);
1309 IFA_UNLOCK(&ia->ia_ifa);
1310 lck_rw_done(in_ifaddr_rwlock);
1311 goto match;
91447636 1312 }
6d2010ae 1313 IFA_UNLOCK(&ia->ia_ifa);
91447636 1314 }
b0d623f7
A
1315
1316 TAILQ_FOREACH(ia, INADDR_HASH(sender_ip->sin_addr.s_addr), ia_hash) {
6d2010ae 1317 IFA_LOCK_SPIN(&ia->ia_ifa);
b7266188 1318 if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
6d2010ae 1319 (ia->ia_ifp == ifp)) &&
b0d623f7 1320 ia->ia_addr.sin_addr.s_addr == sender_ip->sin_addr.s_addr) {
6d2010ae
A
1321 best_ia = ia;
1322 best_ia_sin = best_ia->ia_addr;
1323 IFA_ADDREF_LOCKED(&ia->ia_ifa);
1324 IFA_UNLOCK(&ia->ia_ifa);
1325 lck_rw_done(in_ifaddr_rwlock);
1326 goto match;
b7266188 1327 }
6d2010ae 1328 IFA_UNLOCK(&ia->ia_ifa);
b7266188
A
1329 }
1330
39236c6e
A
1331#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \
1332 (ia->ia_ifp->if_bridge == ifp->if_softc && \
1333 bcmp(IF_LLADDR(ia->ia_ifp), IF_LLADDR(ifp), ifp->if_addrlen) == 0 && \
b7266188
A
1334 addr == ia->ia_addr.sin_addr.s_addr)
1335 /*
1336 * Check the case when bridge shares its MAC address with
1337 * some of its children, so packets are claimed by bridge
1338 * itself (bridge_input() does it first), but they are really
1339 * meant to be destined to the bridge member.
1340 */
1341 if (is_bridge) {
6d2010ae
A
1342 TAILQ_FOREACH(ia, INADDR_HASH(target_ip->sin_addr.s_addr),
1343 ia_hash) {
1344 IFA_LOCK_SPIN(&ia->ia_ifa);
1345 if (BDG_MEMBER_MATCHES_ARP(target_ip->sin_addr.s_addr,
1346 ifp, ia)) {
b7266188
A
1347 ifp = ia->ia_ifp;
1348 best_ia = ia;
6d2010ae
A
1349 best_ia_sin = best_ia->ia_addr;
1350 IFA_ADDREF_LOCKED(&ia->ia_ifa);
1351 IFA_UNLOCK(&ia->ia_ifa);
b7266188
A
1352 lck_rw_done(in_ifaddr_rwlock);
1353 goto match;
1354 }
6d2010ae 1355 IFA_UNLOCK(&ia->ia_ifa);
b0d623f7 1356 }
91447636 1357 }
39236c6e 1358#undef BDG_MEMBER_MATCHES_ARP
b0d623f7
A
1359 lck_rw_done(in_ifaddr_rwlock);
1360
1361 /*
1362 * No match, use the first inet address on the receive interface
1363 * as a dummy address for the rest of the function; we may be
1364 * proxying for another address.
1365 */
1366 ifnet_lock_shared(ifp);
1367 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
6d2010ae
A
1368 IFA_LOCK_SPIN(ifa);
1369 if (ifa->ifa_addr->sa_family != AF_INET) {
1370 IFA_UNLOCK(ifa);
b0d623f7 1371 continue;
6d2010ae 1372 }
b0d623f7 1373 best_ia = (struct in_ifaddr *)ifa;
6d2010ae
A
1374 best_ia_sin = best_ia->ia_addr;
1375 IFA_ADDREF_LOCKED(ifa);
1376 IFA_UNLOCK(ifa);
b7266188
A
1377 ifnet_lock_done(ifp);
1378 goto match;
b0d623f7
A
1379 }
1380 ifnet_lock_done(ifp);
1381
b7266188
A
1382 /*
1383 * If we're not a bridge member, or if we are but there's no
1384 * IPv4 address to use for the interface, drop the packet.
1385 */
1386 if (!bridged || best_ia == NULL)
b0d623f7
A
1387 goto done;
1388
1389match:
91447636 1390 /* If the packet is from this interface, ignore the packet */
39236c6e
A
1391 if (bcmp(CONST_LLADDR(sender_hw), IF_LLADDR(ifp),
1392 sender_hw->sdl_alen) == 0)
b0d623f7 1393 goto done;
b0d623f7 1394
91447636 1395 /* Check for a conflict */
39236c6e
A
1396 if (!bridged &&
1397 sender_ip->sin_addr.s_addr == best_ia_sin.sin_addr.s_addr) {
1398 struct kev_msg ev_msg;
91447636 1399 struct kev_in_collision *in_collision;
39236c6e
A
1400 u_char storage[sizeof (struct kev_in_collision) + MAX_HW_LEN];
1401
1402 bzero(&ev_msg, sizeof (struct kev_msg));
1403 bzero(storage, (sizeof (struct kev_in_collision) + MAX_HW_LEN));
1404 in_collision = (struct kev_in_collision *)(void *)storage;
1405 log(LOG_ERR, "%s duplicate IP address %s sent from "
1406 "address %s\n", if_name(ifp),
1407 inet_ntop(AF_INET, &sender_ip->sin_addr, ipv4str,
1408 sizeof (ipv4str)), sdl_addr_to_hex(sender_hw, buf,
1409 sizeof (buf)));
b0d623f7 1410
91447636
A
1411 /* Send a kernel event so anyone can learn of the conflict */
1412 in_collision->link_data.if_family = ifp->if_family;
1413 in_collision->link_data.if_unit = ifp->if_unit;
fe8ab488 1414 strlcpy(&in_collision->link_data.if_name[0],
39236c6e 1415 ifp->if_name, IFNAMSIZ);
91447636 1416 in_collision->ia_ipaddr = sender_ip->sin_addr;
39236c6e
A
1417 in_collision->hw_len = (sender_hw->sdl_alen < MAX_HW_LEN) ?
1418 sender_hw->sdl_alen : MAX_HW_LEN;
1419 bcopy(CONST_LLADDR(sender_hw), (caddr_t)in_collision->hw_addr,
1420 in_collision->hw_len);
91447636
A
1421 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1422 ev_msg.kev_class = KEV_NETWORK_CLASS;
1423 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1424 ev_msg.event_code = KEV_INET_ARPCOLLISION;
1425 ev_msg.dv[0].data_ptr = in_collision;
39236c6e
A
1426 ev_msg.dv[0].data_length =
1427 sizeof (struct kev_in_collision) + in_collision->hw_len;
91447636
A
1428 ev_msg.dv[1].data_length = 0;
1429 kev_post_msg(&ev_msg);
39236c6e 1430 arpstat.dupips++;
91447636
A
1431 goto respond;
1432 }
b0d623f7 1433
91447636
A
1434 /*
1435 * Look up the routing entry. If it doesn't exist and we are the
c910b4d9 1436 * target, and the sender isn't 0.0.0.0, go ahead and create one.
b0d623f7
A
1437 * Callee holds a reference on the route and returns with the route
1438 * entry locked, upon success.
91447636 1439 */
c910b4d9 1440 error = arp_lookup_route(&sender_ip->sin_addr,
6d2010ae 1441 (target_ip->sin_addr.s_addr == best_ia_sin.sin_addr.s_addr &&
c910b4d9 1442 sender_ip->sin_addr.s_addr != 0), 0, &route, ifp->if_index);
b0d623f7
A
1443
1444 if (error == 0)
1445 RT_LOCK_ASSERT_HELD(route);
1446
39236c6e
A
1447 if (error || route == NULL || route->rt_gateway == NULL) {
1448 if (arpop != ARPOP_REQUEST)
2d21ac55 1449 goto respond;
39236c6e
A
1450
1451 if (arp_sendllconflict && send_conflicting_probes != 0 &&
1452 (ifp->if_eflags & IFEF_ARPLL) &&
1453 IN_LINKLOCAL(ntohl(target_ip->sin_addr.s_addr)) &&
1454 sender_ip->sin_addr.s_addr == INADDR_ANY) {
91447636 1455 /*
39236c6e
A
1456 * Verify this ARP probe doesn't conflict with
1457 * an IPv4LL we know of on another interface.
91447636 1458 */
b0d623f7
A
1459 if (route != NULL) {
1460 RT_REMREF_LOCKED(route);
1461 RT_UNLOCK(route);
1462 route = NULL;
1463 }
1464 /*
1465 * Callee holds a reference on the route and returns
1466 * with the route entry locked, upon success.
1467 */
c910b4d9
A
1468 error = arp_lookup_route(&target_ip->sin_addr, 0, 0,
1469 &route, ifp->if_index);
b0d623f7 1470
39236c6e
A
1471 if (error != 0 || route == NULL ||
1472 route->rt_gateway == NULL)
1473 goto respond;
b0d623f7 1474
39236c6e
A
1475 RT_LOCK_ASSERT_HELD(route);
1476
1477 gateway = SDL(route->rt_gateway);
1478 if (route->rt_ifp != ifp && gateway->sdl_alen != 0 &&
1479 (gateway->sdl_alen != sender_hw->sdl_alen ||
1480 bcmp(CONST_LLADDR(gateway), CONST_LLADDR(sender_hw),
1481 gateway->sdl_alen) != 0)) {
1482 /*
1483 * A node is probing for an IPv4LL we know
1484 * exists on a different interface. We respond
1485 * with a conflicting probe to force the new
1486 * device to pick a different IPv4LL address.
1487 */
1488 if (arp_verbose || log_arp_warnings) {
1489 log(LOG_INFO, "arp: %s on %s sent "
1490 "probe for %s, already on %s\n",
1491 sdl_addr_to_hex(sender_hw, buf,
1492 sizeof (buf)), if_name(ifp),
1493 inet_ntop(AF_INET,
1494 &target_ip->sin_addr, ipv4str,
1495 sizeof (ipv4str)),
1496 if_name(route->rt_ifp));
1497 log(LOG_INFO, "arp: sending "
1498 "conflicting probe to %s on %s\n",
1499 sdl_addr_to_hex(sender_hw, buf,
1500 sizeof (buf)), if_name(ifp));
6d2010ae 1501 }
39236c6e
A
1502 /* Mark use timestamp */
1503 if (route->rt_llinfo != NULL)
1504 arp_llreach_use(route->rt_llinfo);
1505 /* We're done with the route */
1506 RT_REMREF_LOCKED(route);
1507 RT_UNLOCK(route);
1508 route = NULL;
1509 /*
1510 * Send a conservative unicast "ARP probe".
1511 * This should force the other device to pick
1512 * a new number. This will not force the
1513 * device to pick a new number if the device
1514 * has already assigned that number. This will
1515 * not imply to the device that we own that
1516 * address. The link address is always
1517 * present; it's never freed.
1518 */
1519 ifnet_lock_shared(ifp);
1520 ifa = ifp->if_lladdr;
1521 IFA_ADDREF(ifa);
1522 ifnet_lock_done(ifp);
1523 dlil_send_arp_internal(ifp, ARPOP_REQUEST,
1524 SDL(ifa->ifa_addr),
1525 (const struct sockaddr *)sender_ip,
1526 sender_hw,
1527 (const struct sockaddr *)target_ip);
1528 IFA_REMREF(ifa);
1529 ifa = NULL;
1530 arpstat.txconflicts++;
91447636 1531 }
2d21ac55 1532 goto respond;
39236c6e
A
1533 } else if (keep_announcements != 0 &&
1534 target_ip->sin_addr.s_addr == sender_ip->sin_addr.s_addr) {
1535 /*
1536 * Don't create entry if link-local address and
1537 * link-local is disabled
1538 */
1539 if (!IN_LINKLOCAL(ntohl(sender_ip->sin_addr.s_addr)) ||
1540 (ifp->if_eflags & IFEF_ARPLL)) {
b0d623f7
A
1541 if (route != NULL) {
1542 RT_REMREF_LOCKED(route);
1543 RT_UNLOCK(route);
1544 route = NULL;
1545 }
1546 /*
1547 * Callee holds a reference on the route and
1548 * returns with the route entry locked, upon
1549 * success.
1550 */
c910b4d9
A
1551 error = arp_lookup_route(&sender_ip->sin_addr,
1552 1, 0, &route, ifp->if_index);
b0d623f7
A
1553
1554 if (error == 0)
1555 RT_LOCK_ASSERT_HELD(route);
1556
39236c6e
A
1557 if (error == 0 && route != NULL &&
1558 route->rt_gateway != NULL)
2d21ac55 1559 created_announcement = 1;
2d21ac55 1560 }
39236c6e 1561 if (created_announcement == 0)
2d21ac55 1562 goto respond;
2d21ac55
A
1563 } else {
1564 goto respond;
91447636 1565 }
91447636 1566 }
b0d623f7
A
1567
1568 RT_LOCK_ASSERT_HELD(route);
6d2010ae
A
1569 VERIFY(route->rt_expire == 0 || route->rt_rmx.rmx_expire != 0);
1570 VERIFY(route->rt_expire != 0 || route->rt_rmx.rmx_expire == 0);
39236c6e 1571
91447636 1572 gateway = SDL(route->rt_gateway);
b7266188 1573 if (!bridged && route->rt_ifp != ifp) {
39236c6e
A
1574 if (!IN_LINKLOCAL(ntohl(sender_ip->sin_addr.s_addr)) ||
1575 !(ifp->if_eflags & IFEF_ARPLL)) {
1576 if (arp_verbose || log_arp_warnings)
1577 log(LOG_ERR, "arp: %s is on %s but got "
1578 "reply from %s on %s\n",
1579 inet_ntop(AF_INET, &sender_ip->sin_addr,
1580 ipv4str, sizeof (ipv4str)),
1581 if_name(route->rt_ifp),
1582 sdl_addr_to_hex(sender_hw, buf,
1583 sizeof (buf)), if_name(ifp));
91447636 1584 goto respond;
39236c6e 1585 } else {
91447636 1586 /* Don't change a permanent address */
39236c6e 1587 if (route->rt_expire == 0)
91447636 1588 goto respond;
b0d623f7
A
1589
1590 /*
1591 * We're about to check and/or change the route's ifp
1592 * and ifa, so do the lock dance: drop rt_lock, hold
1593 * rnh_lock and re-hold rt_lock to avoid violating the
1594 * lock ordering. We have an extra reference on the
1595 * route, so it won't go away while we do this.
1596 */
1597 RT_UNLOCK(route);
1598 lck_mtx_lock(rnh_lock);
1599 RT_LOCK(route);
91447636 1600 /*
b0d623f7
A
1601 * Don't change the cloned route away from the
1602 * parent's interface if the address did resolve
1603 * or if the route is defunct. rt_ifp on both
1604 * the parent and the clone can now be freely
1605 * accessed now that we have acquired rnh_lock.
91447636 1606 */
b0d623f7 1607 gateway = SDL(route->rt_gateway);
39236c6e
A
1608 if ((gateway->sdl_alen != 0 &&
1609 route->rt_parent != NULL &&
b0d623f7
A
1610 route->rt_parent->rt_ifp == route->rt_ifp) ||
1611 (route->rt_flags & RTF_CONDEMNED)) {
1612 RT_REMREF_LOCKED(route);
1613 RT_UNLOCK(route);
1614 route = NULL;
1615 lck_mtx_unlock(rnh_lock);
91447636
A
1616 goto respond;
1617 }
6d2010ae
A
1618 if (route->rt_ifp != ifp) {
1619 /*
1620 * Purge any link-layer info caching.
1621 */
1622 if (route->rt_llinfo_purge != NULL)
1623 route->rt_llinfo_purge(route);
1624
1625 /* Adjust route ref count for the interfaces */
1626 if (route->rt_if_ref_fn != NULL) {
1627 route->rt_if_ref_fn(ifp, 1);
1628 route->rt_if_ref_fn(route->rt_ifp, -1);
1629 }
d1ecb069 1630 }
91447636
A
1631 /* Change the interface when the existing route is on */
1632 route->rt_ifp = ifp;
39236c6e
A
1633 /*
1634 * If rmx_mtu is not locked, update it
1635 * to the MTU used by the new interface.
1636 */
1637 if (!(route->rt_rmx.rmx_locks & RTV_MTU))
1638 route->rt_rmx.rmx_mtu = route->rt_ifp->if_mtu;
1639
91447636
A
1640 rtsetifa(route, &best_ia->ia_ifa);
1641 gateway->sdl_index = ifp->if_index;
b0d623f7
A
1642 RT_UNLOCK(route);
1643 lck_mtx_unlock(rnh_lock);
1644 RT_LOCK(route);
1645 /* Don't bother if the route is down */
1646 if (!(route->rt_flags & RTF_UP))
1647 goto respond;
1648 /* Refresh gateway pointer */
1649 gateway = SDL(route->rt_gateway);
91447636 1650 }
b0d623f7 1651 RT_LOCK_ASSERT_HELD(route);
91447636 1652 }
b0d623f7 1653
39236c6e
A
1654 if (gateway->sdl_alen != 0 && bcmp(LLADDR(gateway),
1655 CONST_LLADDR(sender_hw), gateway->sdl_alen) != 0) {
1656 if (route->rt_expire != 0 &&
1657 (arp_verbose || log_arp_warnings)) {
91447636 1658 char buf2[3 * MAX_HW_LEN];
39236c6e 1659 log(LOG_INFO, "arp: %s moved from %s to %s on %s\n",
2d21ac55 1660 inet_ntop(AF_INET, &sender_ip->sin_addr, ipv4str,
39236c6e
A
1661 sizeof (ipv4str)),
1662 sdl_addr_to_hex(gateway, buf, sizeof (buf)),
1663 sdl_addr_to_hex(sender_hw, buf2, sizeof (buf2)),
1664 if_name(ifp));
1665 } else if (route->rt_expire == 0) {
1666 if (arp_verbose || log_arp_warnings) {
2d21ac55 1667 log(LOG_ERR, "arp: %s attempts to modify "
39236c6e 1668 "permanent entry for %s on %s\n",
2d21ac55 1669 sdl_addr_to_hex(sender_hw, buf,
39236c6e 1670 sizeof (buf)),
2d21ac55 1671 inet_ntop(AF_INET, &sender_ip->sin_addr,
39236c6e
A
1672 ipv4str, sizeof (ipv4str)),
1673 if_name(ifp));
2d21ac55 1674 }
91447636
A
1675 goto respond;
1676 }
1677 }
b0d623f7 1678
91447636
A
1679 /* Copy the sender hardware address in to the route's gateway address */
1680 gateway->sdl_alen = sender_hw->sdl_alen;
1681 bcopy(CONST_LLADDR(sender_hw), LLADDR(gateway), gateway->sdl_alen);
b0d623f7 1682
91447636 1683 /* Update the expire time for the route and clear the reject flag */
39236c6e
A
1684 if (route->rt_expire != 0)
1685 rt_setexpire(route, net_uptime() + arpt_keep);
91447636 1686 route->rt_flags &= ~RTF_REJECT;
b0d623f7 1687
6d2010ae
A
1688 /* cache the gateway (sender HW) address */
1689 arp_llreach_alloc(route, ifp, LLADDR(gateway), gateway->sdl_alen,
1690 (arpop == ARPOP_REPLY));
1691
b0d623f7 1692 llinfo = route->rt_llinfo;
fe8ab488
A
1693 /* send a notification that the route is back up */
1694 if (ifp->if_addrlen == IF_LLREACH_MAXLEN &&
1695 route->rt_flags & RTF_ROUTER &&
1696 llinfo->la_flags & LLINFO_RTRFAIL_EVTSENT) {
1697 struct kev_msg ev_msg;
1698 struct kev_in_arpfailure in_arpalive;
1699
1700 llinfo->la_flags &= ~LLINFO_RTRFAIL_EVTSENT;
1701 RT_UNLOCK(route);
1702 bzero(&ev_msg, sizeof(ev_msg));
1703 bzero(&in_arpalive, sizeof(in_arpalive));
1704 in_arpalive.link_data.if_family = ifp->if_family;
1705 in_arpalive.link_data.if_unit = ifp->if_unit;
1706 strlcpy(in_arpalive.link_data.if_name, ifp->if_name, IFNAMSIZ);
1707 ev_msg.vendor_code = KEV_VENDOR_APPLE;
1708 ev_msg.kev_class = KEV_NETWORK_CLASS;
1709 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
1710 ev_msg.event_code = KEV_INET_ARPRTRALIVE;
1711 ev_msg.dv[0].data_ptr = &in_arpalive;
1712 ev_msg.dv[0].data_length = sizeof(struct kev_in_arpalive);
1713 kev_post_msg(&ev_msg);
1714 RT_LOCK(route);
1715 }
1716 /* update the llinfo, send a queued packet if there is one */
91447636
A
1717 llinfo->la_asked = 0;
1718 if (llinfo->la_hold) {
39236c6e 1719 struct mbuf *m0 = llinfo->la_hold;
6d2010ae 1720 llinfo->la_hold = NULL;
b0d623f7 1721 RT_UNLOCK(route);
39236c6e
A
1722 dlil_output(ifp, PF_INET, m0, (caddr_t)route,
1723 rt_key(route), 0, NULL);
b0d623f7
A
1724 RT_REMREF(route);
1725 route = NULL;
91447636 1726 }
b0d623f7 1727
fe8ab488 1728
91447636 1729respond:
b0d623f7 1730 if (route != NULL) {
6d2010ae
A
1731 /* Mark use timestamp if we're going to send a reply */
1732 if (arpop == ARPOP_REQUEST && route->rt_llinfo != NULL)
1733 arp_llreach_use(route->rt_llinfo);
b0d623f7
A
1734 RT_REMREF_LOCKED(route);
1735 RT_UNLOCK(route);
1736 route = NULL;
91447636 1737 }
b0d623f7
A
1738
1739 if (arpop != ARPOP_REQUEST)
1740 goto done;
1741
39236c6e
A
1742 arpstat.rxrequests++;
1743
91447636 1744 /* If we are not the target, check if we should proxy */
6d2010ae 1745 if (target_ip->sin_addr.s_addr != best_ia_sin.sin_addr.s_addr) {
b0d623f7
A
1746 /*
1747 * Find a proxy route; callee holds a reference on the
1748 * route and returns with the route entry locked, upon
1749 * success.
1750 */
c910b4d9
A
1751 error = arp_lookup_route(&target_ip->sin_addr, 0, SIN_PROXY,
1752 &route, ifp->if_index);
b0d623f7
A
1753
1754 if (error == 0) {
1755 RT_LOCK_ASSERT_HELD(route);
b7266188
A
1756 /*
1757 * Return proxied ARP replies only on the interface
1758 * or bridge cluster where this network resides.
1759 * Otherwise we may conflict with the host we are
1760 * proxying for.
1761 */
1762 if (route->rt_ifp != ifp &&
39236c6e
A
1763 (route->rt_ifp->if_bridge != ifp->if_bridge ||
1764 ifp->if_bridge == NULL)) {
1765 RT_REMREF_LOCKED(route);
1766 RT_UNLOCK(route);
1767 goto done;
1768 }
b0d623f7
A
1769 proxied = *SDL(route->rt_gateway);
1770 target_hw = &proxied;
1771 } else {
1772 /*
1773 * We don't have a route entry indicating we should
1774 * use proxy. If we aren't supposed to proxy all,
1775 * we are done.
1776 */
1777 if (!arp_proxyall)
1778 goto done;
1779
1780 /*
1781 * See if we have a route to the target ip before
1782 * we proxy it.
1783 */
1784 route = rtalloc1_scoped((struct sockaddr *)
1785 (size_t)target_ip, 0, 0, ifp->if_index);
1786 if (!route)
1787 goto done;
1788
91447636
A
1789 /*
1790 * Don't proxy for hosts already on the same interface.
1791 */
b0d623f7 1792 RT_LOCK(route);
91447636 1793 if (route->rt_ifp == ifp) {
b0d623f7
A
1794 RT_UNLOCK(route);
1795 rtfree(route);
1796 goto done;
91447636
A
1797 }
1798 }
6d2010ae
A
1799 /* Mark use timestamp */
1800 if (route->rt_llinfo != NULL)
1801 arp_llreach_use(route->rt_llinfo);
b0d623f7
A
1802 RT_REMREF_LOCKED(route);
1803 RT_UNLOCK(route);
91447636 1804 }
b0d623f7
A
1805
1806 dlil_send_arp(ifp, ARPOP_REPLY,
39236c6e
A
1807 target_hw, (const struct sockaddr *)target_ip,
1808 sender_hw, (const struct sockaddr *)sender_ip, 0);
b0d623f7
A
1809
1810done:
1811 if (best_ia != NULL)
6d2010ae 1812 IFA_REMREF(&best_ia->ia_ifa);
39236c6e 1813 return (0);
91447636
A
1814}
1815
1816void
6d2010ae 1817arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
91447636 1818{
6d2010ae
A
1819 struct sockaddr *sa;
1820
1821 IFA_LOCK(ifa);
91447636
A
1822 ifa->ifa_rtrequest = arp_rtrequest;
1823 ifa->ifa_flags |= RTF_CLONING;
6d2010ae
A
1824 sa = ifa->ifa_addr;
1825 IFA_UNLOCK(ifa);
316670eb 1826 dlil_send_arp(ifp, ARPOP_REQUEST, NULL, sa, NULL, sa, 0);
91447636 1827}
39236c6e
A
1828
1829static int
1830arp_getstat SYSCTL_HANDLER_ARGS
1831{
1832#pragma unused(oidp, arg1, arg2)
1833 if (req->oldptr == USER_ADDR_NULL)
1834 req->oldlen = (size_t)sizeof (struct arpstat);
1835
1836 return (SYSCTL_OUT(req, &arpstat, MIN(sizeof (arpstat), req->oldlen)));
1837}