1 /* $NetBSD: if_arp.c,v 1.148 2009/11/03 00:57:42 christos Exp $ */
4 * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Public Access Networks Corporation ("Panix"). It was developed under
9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1982, 1986, 1988, 1993
35 * The Regents of the University of California. All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)if_ether.c 8.2 (Berkeley) 9/26/94
65 * Ethernet address resolution protocol.
67 * add "inuse/lock" bit (or ref. count) along with valid bit
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.148 2009/11/03 00:57:42 christos Exp $");
80 #include <sys/param.h>
81 #include <sys/systm.h>
82 #include <sys/callout.h>
83 #include <sys/malloc.h>
85 #include <sys/socket.h>
87 #include <sys/timetc.h>
88 #include <sys/kernel.h>
89 #include <sys/errno.h>
90 #include <sys/ioctl.h>
91 #include <sys/syslog.h>
93 #include <sys/protosw.h>
94 #include <sys/domain.h>
95 #include <sys/sysctl.h>
96 #include <sys/socketvar.h>
97 #include <sys/percpu.h>
99 #include <net/ethertypes.h>
101 #include <net/if_dl.h>
102 #include <net/if_token.h>
103 #include <net/if_types.h>
104 #include <net/if_ether.h>
105 #include <net/route.h>
106 #include <net/net_stats.h>
108 #include <netinet/in.h>
109 #include <netinet/in_systm.h>
110 #include <netinet/in_var.h>
111 #include <netinet/ip.h>
112 #include <netinet/if_inarp.h>
116 #include <net/if_arc.h>
120 #include <net/if_fddi.h>
125 #include <netinet/ip_carp.h>
128 #define SIN(s) ((struct sockaddr_in *)s)
129 #define SRP(s) ((struct sockaddr_inarp *)s)
132 * ARP trailer negotiation. Trailer protocol is not IP specific,
133 * but ARP request/response use IP addresses.
135 #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
138 int arpt_prune
= (5*60*1); /* walk list every 5 minutes */
139 int arpt_keep
= (20*60); /* once resolved, good for 20 more minutes */
140 int arpt_down
= 20; /* once declared down, don't send for 20 secs */
141 int arpt_refresh
= (5*60); /* time left before refreshing */
142 #define rt_expire rt_rmx.rmx_expire
143 #define rt_pksent rt_rmx.rmx_pksent
145 static struct sockaddr
*arp_setgate(struct rtentry
*, struct sockaddr
*,
146 const struct sockaddr
*);
147 static void arptfree(struct llinfo_arp
*);
148 static void arptimer(void *);
149 static struct llinfo_arp
*arplookup1(struct mbuf
*, const struct in_addr
*,
150 int, int, struct rtentry
*);
151 static struct llinfo_arp
*arplookup(struct mbuf
*, const struct in_addr
*,
153 static void in_arpinput(struct mbuf
*);
155 LIST_HEAD(, llinfo_arp
) llinfo_arp
;
156 struct ifqueue arpintrq
= {
163 int arp_inuse
, arp_allocated
, arp_intimer
;
164 int arp_maxtries
= 5;
165 int useloopback
= 1; /* use loopback interface for local traffic */
166 int arpinit_done
= 0;
168 static percpu_t
*arpstat_percpu
;
170 #define ARP_STAT_GETREF() _NET_STAT_GETREF(arpstat_percpu)
171 #define ARP_STAT_PUTREF() _NET_STAT_PUTREF(arpstat_percpu)
173 #define ARP_STATINC(x) _NET_STATINC(arpstat_percpu, x)
174 #define ARP_STATADD(x, v) _NET_STATADD(arpstat_percpu, x, v)
176 struct callout arptimer_ch
;
179 struct in_addr myip
, srv_ip
;
180 int myip_initialized
= 0;
181 int revarp_in_progress
= 0;
182 struct ifnet
*myip_ifp
= NULL
;
185 static void db_print_sa(const struct sockaddr
*);
186 static void db_print_ifa(struct ifaddr
*);
187 static void db_print_llinfo(void *);
188 static int db_show_rtentry(struct rtentry
*, void *);
192 * this should be elsewhere.
196 lla_snprintf(u_int8_t
*, int);
199 lla_snprintf(u_int8_t
*adrp
, int len
)
202 static char buf
[NUMBUFS
][16*3];
210 *p
++ = hexdigits
[(*adrp
)>>4];
211 *p
++ = hexdigits
[(*adrp
++)&0xf];
213 for (i
=1; i
<len
&& i
<16; i
++) {
215 *p
++ = hexdigits
[(*adrp
)>>4];
216 *p
++ = hexdigits
[(*adrp
++)&0xf];
221 bnum
= (bnum
+ 1) % NUMBUFS
;
225 DOMAIN_DEFINE(arpdomain
); /* forward declare and add to link set */
227 const struct protosw arpsw
[] = {
229 .pr_domain
= &arpdomain
,
240 .pr_drain
= arp_drain
,
245 struct domain arpdomain
= {
246 .dom_family
= PF_ARP
,
248 .dom_protosw
= arpsw
,
249 .dom_protoswNPROTOSW
= &arpsw
[__arraycount(arpsw
)],
255 * to prevent lossage vs. the arp_drain routine (which may be called at
256 * any time, including in a device driver context), we do two things:
258 * 1) manipulation of la->la_hold is done at splnet() (for all of
259 * about two instructions).
261 * 2) manipulation of the arp table's linked list is done under the
262 * protection of the ARP_LOCK; if arp_drain() or arptimer is called
263 * while the arp table is locked, we punt and try again later.
266 static int arp_locked
;
267 static inline int arp_lock_try(int);
268 static inline void arp_unlock(void);
271 arp_lock_try(int recurse
)
276 * Use splvm() -- we're blocking things that would cause
280 if (!recurse
&& arp_locked
) {
300 #define ARP_LOCK(recurse) \
302 if (arp_lock_try(recurse) == 0) { \
303 printf("%s:%d: arp already locked\n", __FILE__, __LINE__); \
306 } while (/*CONSTCOND*/ 0)
307 #define ARP_LOCK_CHECK() \
309 if (arp_locked == 0) { \
310 printf("%s:%d: arp lock not held\n", __FILE__, __LINE__); \
311 panic("arp lock check"); \
313 } while (/*CONSTCOND*/ 0)
315 #define ARP_LOCK(x) (void) arp_lock_try(x)
316 #define ARP_LOCK_CHECK() /* nothing */
319 #define ARP_UNLOCK() arp_unlock()
321 static void sysctl_net_inet_arp_setup(struct sysctllog
**);
327 sysctl_net_inet_arp_setup(NULL
);
328 arpstat_percpu
= percpu_alloc(sizeof(uint64_t) * ARP_NSTATS
);
332 * ARP protocol drain routine. Called when memory is in short supply.
333 * Called at splvm(); don't acquire softnet_lock as can be called from
334 * hardware interrupt handlers.
339 struct llinfo_arp
*la
, *nla
;
343 KERNEL_LOCK(1, NULL
);
345 if (arp_lock_try(0) == 0) {
346 KERNEL_UNLOCK_ONE(NULL
);
350 for (la
= LIST_FIRST(&llinfo_arp
); la
!= NULL
; la
= nla
) {
351 nla
= LIST_NEXT(la
, la_list
);
362 ARP_STATADD(ARP_STAT_DFRDROPPED
, count
);
363 KERNEL_UNLOCK_ONE(NULL
);
368 * Timeout routine. Age arp_tab entries periodically.
374 struct llinfo_arp
*la
, *nla
;
376 mutex_enter(softnet_lock
);
377 KERNEL_LOCK(1, NULL
);
379 if (arp_lock_try(0) == 0) {
381 KERNEL_UNLOCK_ONE(NULL
);
382 mutex_exit(softnet_lock
);
386 callout_reset(&arptimer_ch
, arpt_prune
* hz
, arptimer
, NULL
);
387 for (la
= LIST_FIRST(&llinfo_arp
); la
!= NULL
; la
= nla
) {
388 struct rtentry
*rt
= la
->la_rt
;
390 nla
= LIST_NEXT(la
, la_list
);
391 if (rt
->rt_expire
== 0)
393 if ((rt
->rt_expire
- time_second
) < arpt_refresh
&&
394 rt
->rt_pksent
> (time_second
- arpt_keep
)) {
396 * If the entry has been used during since last
397 * refresh, try to renew it before deleting.
399 arprequest(rt
->rt_ifp
,
400 &satocsin(rt
->rt_ifa
->ifa_addr
)->sin_addr
,
401 &satocsin(rt_getkey(rt
))->sin_addr
,
402 CLLADDR(rt
->rt_ifp
->if_sadl
));
403 } else if (rt
->rt_expire
<= time_second
)
404 arptfree(la
); /* timer has expired; clear */
409 KERNEL_UNLOCK_ONE(NULL
);
410 mutex_exit(softnet_lock
);
414 * We set the gateway for RTF_CLONING routes to a "prototype"
415 * link-layer sockaddr whose interface type (if_type) and interface
416 * index (if_index) fields are prepared.
418 static struct sockaddr
*
419 arp_setgate(struct rtentry
*rt
, struct sockaddr
*gate
,
420 const struct sockaddr
*netmask
)
422 const struct ifnet
*ifp
= rt
->rt_ifp
;
423 uint8_t namelen
= strlen(ifp
->if_xname
);
424 uint8_t addrlen
= ifp
->if_addrlen
;
427 * XXX: If this is a manually added route to interface
428 * such as older version of routed or gated might provide,
429 * restore cloning bit.
431 if ((rt
->rt_flags
& RTF_HOST
) == 0 && netmask
!= NULL
&&
432 satocsin(netmask
)->sin_addr
.s_addr
!= 0xffffffff)
433 rt
->rt_flags
|= RTF_CLONING
;
434 if (rt
->rt_flags
& RTF_CLONING
) {
437 struct sockaddr_storage ss
;
438 struct sockaddr_dl sdl
;
441 * Case 1: This route should come from a route to iface.
443 sockaddr_dl_init(&u
.sdl
, sizeof(u
.ss
),
444 ifp
->if_index
, ifp
->if_type
, NULL
, namelen
, NULL
, addrlen
);
445 rt_setgate(rt
, &u
.sa
);
446 gate
= rt
->rt_gateway
;
452 * Parallel to llc_rtrequest.
455 arp_rtrequest(int req
, struct rtentry
*rt
, const struct rt_addrinfo
*info
)
457 struct sockaddr
*gate
= rt
->rt_gateway
;
458 struct llinfo_arp
*la
= (struct llinfo_arp
*)rt
->rt_llinfo
;
462 struct in_ifaddr
*ia
;
464 struct ifnet
*ifp
= rt
->rt_ifp
;
469 * We generate expiration times from time_second
470 * so avoid accidentally creating permanent routes.
472 if (time_second
== 0) {
478 callout_init(&arptimer_ch
, CALLOUT_MPSAFE
);
479 callout_reset(&arptimer_ch
, hz
, arptimer
, NULL
);
482 if (req
== RTM_LLINFO_UPD
) {
485 if ((ifa
= info
->rti_ifa
) == NULL
)
488 in
= &ifatoia(ifa
)->ia_addr
.sin_addr
;
490 arprequest(ifa
->ifa_ifp
, in
, in
,
491 CLLADDR(ifa
->ifa_ifp
->if_sadl
));
495 if ((rt
->rt_flags
& RTF_GATEWAY
) != 0) {
500 * linklayers with particular link MTU limitation.
502 switch(ifp
->if_type
) {
505 if (ifp
->if_mtu
> FDDIIPMTU
)
506 rt
->rt_rmx
.rmx_mtu
= FDDIIPMTU
;
514 if (ifp
->if_flags
& IFF_LINK0
)
515 arcipifmtu
= arc_ipmtu
;
518 if (ifp
->if_mtu
> arcipifmtu
)
519 rt
->rt_rmx
.rmx_mtu
= arcipifmtu
;
527 ARP_LOCK(1); /* we may already be locked here. */
531 gate
= arp_setgate(rt
, gate
, info
->rti_info
[RTAX_NETMASK
]);
534 gate
= arp_setgate(rt
, gate
, info
->rti_info
[RTAX_NETMASK
]);
535 if (rt
->rt_flags
& RTF_CLONING
) {
537 * Give this route an expiration time, even though
538 * it's a "permanent" route, so that routes cloned
539 * from it do not need their expiration time set.
541 rt
->rt_expire
= time_second
;
543 * linklayers with particular link MTU limitation.
545 switch (ifp
->if_type
) {
548 if ((rt
->rt_rmx
.rmx_locks
& RTV_MTU
) == 0 &&
549 (rt
->rt_rmx
.rmx_mtu
> FDDIIPMTU
||
550 (rt
->rt_rmx
.rmx_mtu
== 0 &&
551 ifp
->if_mtu
> FDDIIPMTU
)))
552 rt
->rt_rmx
.rmx_mtu
= FDDIIPMTU
;
559 if (ifp
->if_flags
& IFF_LINK0
)
560 arcipifmtu
= arc_ipmtu
;
564 if ((rt
->rt_rmx
.rmx_locks
& RTV_MTU
) == 0 &&
565 (rt
->rt_rmx
.rmx_mtu
> arcipifmtu
||
566 (rt
->rt_rmx
.rmx_mtu
== 0 &&
567 ifp
->if_mtu
> arcipifmtu
)))
568 rt
->rt_rmx
.rmx_mtu
= arcipifmtu
;
575 /* Announce a new entry if requested. */
576 if (rt
->rt_flags
& RTF_ANNOUNCE
) {
578 &satocsin(rt_getkey(rt
))->sin_addr
,
579 &satocsin(rt_getkey(rt
))->sin_addr
,
580 CLLADDR(satocsdl(gate
)));
584 if (gate
->sa_family
!= AF_LINK
||
585 gate
->sa_len
< sockaddr_dl_measure(0, ifp
->if_addrlen
)) {
586 log(LOG_DEBUG
, "arp_rtrequest: bad gateway value\n");
589 satosdl(gate
)->sdl_type
= ifp
->if_type
;
590 satosdl(gate
)->sdl_index
= ifp
->if_index
;
592 break; /* This happens on a route change */
594 * Case 2: This route may come from cloning, or a manual route
595 * add with a LL address.
597 switch (ifp
->if_type
) {
600 allocsize
= sizeof(*la
) + sizeof(struct token_rif
);
602 #endif /* NTOKEN > 0 */
604 allocsize
= sizeof(*la
);
606 R_Malloc(la
, struct llinfo_arp
*, allocsize
);
607 rt
->rt_llinfo
= (void *)la
;
609 log(LOG_DEBUG
, "arp_rtrequest: malloc failed\n");
612 arp_inuse
++, arp_allocated
++;
613 memset(la
, 0, allocsize
);
615 rt
->rt_flags
|= RTF_LLINFO
;
616 LIST_INSERT_HEAD(&llinfo_arp
, la
, la_list
);
618 INADDR_TO_IA(satocsin(rt_getkey(rt
))->sin_addr
, ia
);
619 while (ia
&& ia
->ia_ifp
!= ifp
)
620 NEXT_IA_WITH_SAME_ADDR(ia
);
623 * This test used to be
624 * if (lo0ifp->if_flags & IFF_UP)
625 * It allowed local traffic to be forced through
626 * the hardware by configuring the loopback down.
627 * However, it causes problems during network
628 * configuration for boards that can't receive
629 * packets they send. It is now necessary to clear
630 * "useloopback" and remove the route to force
631 * traffic out to the hardware.
633 * In 4.4BSD, the above "if" statement checked
634 * rt->rt_ifa against rt_getkey(rt). It was changed
635 * to the current form so that we can provide a
636 * better support for multiple IPv4 addresses on a
640 if (sockaddr_dl_init(satosdl(gate
), gate
->sa_len
,
641 ifp
->if_index
, ifp
->if_type
, NULL
, 0,
642 CLLADDR(ifp
->if_sadl
), ifp
->if_addrlen
) == NULL
) {
643 panic("%s(%s): sockaddr_dl_init cannot fail",
644 __func__
, ifp
->if_xname
);
647 ifp
= rt
->rt_ifp
= lo0ifp
;
649 * make sure to set rt->rt_ifa to the interface
650 * address we are using, otherwise we will have trouble
651 * with source address selection.
654 if (ifa
!= rt
->rt_ifa
)
655 rt_replace_ifa(rt
, ifa
);
663 LIST_REMOVE(la
, la_list
);
664 rt
->rt_llinfo
= NULL
;
665 rt
->rt_flags
&= ~RTF_LLINFO
;
681 * Broadcast an ARP request. Caller specifies:
682 * - arp header source ip address
683 * - arp header target ip address
684 * - arp header source ethernet address
687 arprequest(struct ifnet
*ifp
,
688 const struct in_addr
*sip
, const struct in_addr
*tip
,
689 const u_int8_t
*enaddr
)
696 if ((m
= m_gethdr(M_DONTWAIT
, MT_DATA
)) == NULL
)
698 MCLAIM(m
, &arpdomain
.dom_mowner
);
699 switch (ifp
->if_type
) {
701 m
->m_len
= sizeof(*ah
) + 2 * sizeof(struct in_addr
) +
705 m
->m_len
= sizeof(*ah
) + 2 * sizeof(struct in_addr
) +
709 m
->m_pkthdr
.len
= m
->m_len
;
710 MH_ALIGN(m
, m
->m_len
);
711 ah
= mtod(m
, struct arphdr
*);
712 memset(ah
, 0, m
->m_len
);
713 switch (ifp
->if_type
) {
714 case IFT_IEEE1394
: /* RFC2734 */
715 /* fill it now for ar_tpa computation */
716 ah
->ar_hrd
= htons(ARPHRD_IEEE1394
);
719 /* ifp->if_output will fill ar_hrd */
722 ah
->ar_pro
= htons(ETHERTYPE_IP
);
723 ah
->ar_hln
= ifp
->if_addrlen
; /* hardware address length */
724 ah
->ar_pln
= sizeof(struct in_addr
); /* protocol address length */
725 ah
->ar_op
= htons(ARPOP_REQUEST
);
726 memcpy(ar_sha(ah
), enaddr
, ah
->ar_hln
);
727 memcpy(ar_spa(ah
), sip
, ah
->ar_pln
);
728 memcpy(ar_tpa(ah
), tip
, ah
->ar_pln
);
729 sa
.sa_family
= AF_ARP
;
731 m
->m_flags
|= M_BCAST
;
732 arps
= ARP_STAT_GETREF();
733 arps
[ARP_STAT_SNDTOTAL
]++;
734 arps
[ARP_STAT_SENDREQUEST
]++;
736 (*ifp
->if_output
)(ifp
, m
, &sa
, NULL
);
740 * Resolve an IP address into an ethernet address. If success,
741 * desten is filled in. If there is no entry in arptab,
742 * set one up and broadcast a request for the IP address.
743 * Hold onto this mbuf and resend it once the address
744 * is finally resolved. A return value of 1 indicates
745 * that desten has been filled in and the packet should be sent
746 * normally; a 0 return indicates that the packet has been
747 * taken over here, either now or for later transmission.
750 arpresolve(struct ifnet
*ifp
, struct rtentry
*rt
, struct mbuf
*m
,
751 const struct sockaddr
*dst
, u_char
*desten
)
753 struct llinfo_arp
*la
;
754 const struct sockaddr_dl
*sdl
;
758 if ((la
= arplookup1(m
, &satocsin(dst
)->sin_addr
, 1, 0, rt
)) != NULL
)
761 if (la
== NULL
|| rt
== NULL
) {
762 ARP_STATINC(ARP_STAT_ALLOCFAIL
);
764 "arpresolve: can't allocate llinfo on %s for %s\n",
765 ifp
->if_xname
, in_fmtaddr(satocsin(dst
)->sin_addr
));
769 sdl
= satocsdl(rt
->rt_gateway
);
771 * Check the address family and length is valid, the address
772 * is resolved; otherwise, try to resolve.
774 if ((rt
->rt_expire
== 0 || rt
->rt_expire
> time_second
) &&
775 sdl
->sdl_family
== AF_LINK
&& sdl
->sdl_alen
!= 0) {
776 memcpy(desten
, CLLADDR(sdl
),
777 min(sdl
->sdl_alen
, ifp
->if_addrlen
));
778 rt
->rt_pksent
= time_second
; /* Time for last pkt sent */
782 * There is an arptab entry, but no ethernet address
783 * response yet. Replace the held mbuf with this
787 ARP_STATINC(ARP_STAT_DFRTOTAL
);
794 ARP_STATINC(ARP_STAT_DFRDROPPED
);
799 * Re-send the ARP request when appropriate.
802 if (rt
->rt_expire
== 0) {
803 /* This should never happen. (Should it? -gwr) */
804 printf("arpresolve: unresolved and rt_expire == 0\n");
805 /* Set expiration time to now (expired). */
806 rt
->rt_expire
= time_second
;
810 rt
->rt_flags
&= ~RTF_REJECT
;
811 if (la
->la_asked
== 0 || rt
->rt_expire
!= time_second
) {
812 rt
->rt_expire
= time_second
;
813 if (la
->la_asked
++ < arp_maxtries
) {
815 &satocsin(rt
->rt_ifa
->ifa_addr
)->sin_addr
,
816 &satocsin(dst
)->sin_addr
,
818 (rt
->rt_ifp
->if_type
== IFT_CARP
) ?
819 CLLADDR(rt
->rt_ifp
->if_sadl
):
821 CLLADDR(ifp
->if_sadl
));
823 rt
->rt_flags
|= RTF_REJECT
;
824 rt
->rt_expire
+= arpt_down
;
833 * Common length and type checks are done here,
834 * then the protocol-specific routine is called.
844 mutex_enter(softnet_lock
);
845 KERNEL_LOCK(1, NULL
);
846 while (arpintrq
.ifq_head
) {
848 IF_DEQUEUE(&arpintrq
, m
);
850 if (m
== 0 || (m
->m_flags
& M_PKTHDR
) == 0)
853 MCLAIM(m
, &arpdomain
.dom_mowner
);
854 ARP_STATINC(ARP_STAT_RCVTOTAL
);
857 * First, make sure we have at least struct arphdr.
859 if (m
->m_len
< sizeof(struct arphdr
) ||
860 (ar
= mtod(m
, struct arphdr
*)) == NULL
)
863 switch (m
->m_pkthdr
.rcvif
->if_type
) {
865 arplen
= sizeof(struct arphdr
) +
866 ar
->ar_hln
+ 2 * ar
->ar_pln
;
869 arplen
= sizeof(struct arphdr
) +
870 2 * ar
->ar_hln
+ 2 * ar
->ar_pln
;
874 if (/* XXX ntohs(ar->ar_hrd) == ARPHRD_ETHER && */
876 switch (ntohs(ar
->ar_pro
)) {
878 case ETHERTYPE_IPTRAILERS
:
882 ARP_STATINC(ARP_STAT_RCVBADPROTO
);
886 ARP_STATINC(ARP_STAT_RCVBADLEN
);
890 KERNEL_UNLOCK_ONE(NULL
);
891 mutex_exit(softnet_lock
);
895 * ARP for Internet protocols on 10 Mb/s Ethernet.
896 * Algorithm is that given in RFC 826.
897 * In addition, a sanity check is performed on the sender
898 * protocol address, to catch impersonators.
899 * We no longer handle negotiations for use of trailer protocol:
900 * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
901 * along with IP replies if we wanted trailers sent to us,
902 * and also sent them in response to IP replies.
903 * This allowed either end to announce the desire to receive
905 * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
906 * but formerly didn't normally send requests.
909 in_arpinput(struct mbuf
*m
)
912 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
913 struct llinfo_arp
*la
= NULL
;
915 struct in_ifaddr
*ia
;
917 struct in_ifaddr
*bridge_ia
= NULL
;
920 u_int32_t count
= 0, index
= 0;
922 struct sockaddr_dl
*sdl
;
924 struct in_addr isaddr
, itaddr
, myaddr
;
931 if (__predict_false(m_makewritable(&m
, 0, m
->m_pkthdr
.len
, M_DONTWAIT
)))
933 ah
= mtod(m
, struct arphdr
*);
934 op
= ntohs(ah
->ar_op
);
937 * Fix up ah->ar_hrd if necessary, before using ar_tha() or
940 switch (ifp
->if_type
) {
942 if (ntohs(ah
->ar_hrd
) == ARPHRD_IEEE1394
)
945 /* XXX this is to make sure we compute ar_tha right */
946 /* XXX check ar_hrd more strictly? */
947 ah
->ar_hrd
= htons(ARPHRD_IEEE1394
);
951 /* XXX check ar_hrd? */
955 memcpy(&isaddr
, ar_spa(ah
), sizeof (isaddr
));
956 memcpy(&itaddr
, ar_tpa(ah
), sizeof (itaddr
));
958 if (m
->m_flags
& (M_BCAST
|M_MCAST
))
959 ARP_STATINC(ARP_STAT_RCVMCAST
);
962 * If the target IP address is zero, ignore the packet.
963 * This prevents the code below from tring to answer
964 * when we are using IP address zero (booting).
966 if (in_nullhost(itaddr
)) {
967 ARP_STATINC(ARP_STAT_RCVZEROTPA
);
973 * Search for a matching interface address
974 * or any address on the interface to use
975 * as a dummy address in the rest of this function
978 INADDR_TO_IA(itaddr
, ia
);
981 if (ia
->ia_ifp
->if_type
== IFT_CARP
&&
982 ((ia
->ia_ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) ==
983 (IFF_UP
|IFF_RUNNING
))) {
985 if (ia
->ia_ifp
== m
->m_pkthdr
.rcvif
&&
986 carp_iamatch(ia
, ar_sha(ah
),
992 if (ia
->ia_ifp
== m
->m_pkthdr
.rcvif
)
996 * If the interface we received the packet on
997 * is part of a bridge, check to see if we need
998 * to "bridge" the packet to ourselves at this
999 * layer. Note we still prefer a perfect match,
1000 * but allow this weaker match if necessary.
1002 if (m
->m_pkthdr
.rcvif
->if_bridge
!= NULL
&&
1003 m
->m_pkthdr
.rcvif
->if_bridge
== ia
->ia_ifp
->if_bridge
)
1005 #endif /* NBRIDGE > 0 */
1007 NEXT_IA_WITH_SAME_ADDR(ia
);
1011 if (ia
== NULL
&& bridge_ia
!= NULL
) {
1013 ifp
= bridge_ia
->ia_ifp
;
1018 INADDR_TO_IA(isaddr
, ia
);
1019 while ((ia
!= NULL
) && ia
->ia_ifp
!= m
->m_pkthdr
.rcvif
)
1020 NEXT_IA_WITH_SAME_ADDR(ia
);
1025 ARP_STATINC(ARP_STAT_RCVNOINT
);
1031 myaddr
= ia
->ia_addr
.sin_addr
;
1033 /* XXX checks for bridge case? */
1034 if (!memcmp(ar_sha(ah
), CLLADDR(ifp
->if_sadl
), ifp
->if_addrlen
)) {
1035 ARP_STATINC(ARP_STAT_RCVLOCALSHA
);
1036 goto out
; /* it's from me, ignore it. */
1039 /* XXX checks for bridge case? */
1040 if (!memcmp(ar_sha(ah
), ifp
->if_broadcastaddr
, ifp
->if_addrlen
)) {
1041 ARP_STATINC(ARP_STAT_RCVBCASTSHA
);
1043 "%s: arp: link address is broadcast for IP address %s!\n",
1044 ifp
->if_xname
, in_fmtaddr(isaddr
));
1049 * If the source IP address is zero, this is an RFC 5227 ARP probe
1051 if (in_nullhost(isaddr
)) {
1052 ARP_STATINC(ARP_STAT_RCVZEROSPA
);
1056 if (in_hosteq(isaddr
, myaddr
)) {
1057 ARP_STATINC(ARP_STAT_RCVLOCALSPA
);
1059 "duplicate IP address %s sent from link address %s\n",
1060 in_fmtaddr(isaddr
), lla_snprintf(ar_sha(ah
), ah
->ar_hln
));
1064 la
= arplookup(m
, &isaddr
, in_hosteq(itaddr
, myaddr
), 0);
1065 if (la
!= NULL
&& (rt
= la
->la_rt
) && (sdl
= satosdl(rt
->rt_gateway
))) {
1066 if (sdl
->sdl_alen
&&
1067 memcmp(ar_sha(ah
), CLLADDR(sdl
), sdl
->sdl_alen
)) {
1068 if (rt
->rt_flags
& RTF_STATIC
) {
1069 ARP_STATINC(ARP_STAT_RCVOVERPERM
);
1071 "%s tried to overwrite permanent arp info"
1073 lla_snprintf(ar_sha(ah
), ah
->ar_hln
),
1074 in_fmtaddr(isaddr
));
1076 } else if (rt
->rt_ifp
!= ifp
) {
1077 ARP_STATINC(ARP_STAT_RCVOVERINT
);
1079 "%s on %s tried to overwrite "
1080 "arp info for %s on %s\n",
1081 lla_snprintf(ar_sha(ah
), ah
->ar_hln
),
1082 ifp
->if_xname
, in_fmtaddr(isaddr
),
1083 rt
->rt_ifp
->if_xname
);
1086 ARP_STATINC(ARP_STAT_RCVOVER
);
1088 "arp info overwritten for %s by %s\n",
1090 lla_snprintf(ar_sha(ah
), ah
->ar_hln
));
1094 * sanity check for the address length.
1095 * XXX this does not work for protocols with variable address
1098 if (sdl
->sdl_alen
&&
1099 sdl
->sdl_alen
!= ah
->ar_hln
) {
1100 ARP_STATINC(ARP_STAT_RCVLENCHG
);
1102 "arp from %s: new addr len %d, was %d\n",
1103 in_fmtaddr(isaddr
), ah
->ar_hln
, sdl
->sdl_alen
);
1105 if (ifp
->if_addrlen
!= ah
->ar_hln
) {
1106 ARP_STATINC(ARP_STAT_RCVBADLEN
);
1108 "arp from %s: addr len: new %d, i/f %d (ignored)\n",
1109 in_fmtaddr(isaddr
), ah
->ar_hln
,
1115 * XXX uses m_data and assumes the complete answer including
1116 * XXX token-ring headers is in the same buf
1118 if (ifp
->if_type
== IFT_ISO88025
) {
1119 struct token_header
*trh
;
1121 trh
= (struct token_header
*)M_TRHSTART(m
);
1122 if (trh
->token_shost
[0] & TOKEN_RI_PRESENT
) {
1123 struct token_rif
*rif
;
1126 rif
= TOKEN_RIF(trh
);
1127 riflen
= (ntohs(rif
->tr_rcf
) &
1128 TOKEN_RCF_LEN_MASK
) >> 8;
1131 riflen
< sizeof(struct token_rif
) &&
1132 (riflen
& 1) == 0) {
1133 rif
->tr_rcf
^= htons(TOKEN_RCF_DIRECTION
);
1134 rif
->tr_rcf
&= htons(~TOKEN_RCF_BROADCAST_MASK
);
1135 memcpy(TOKEN_RIF(la
), rif
, riflen
);
1139 #endif /* NTOKEN > 0 */
1140 (void)sockaddr_dl_setaddr(sdl
, sdl
->sdl_len
, ar_sha(ah
),
1143 rt
->rt_expire
= time_second
+ arpt_keep
;
1144 rt
->rt_flags
&= ~RTF_REJECT
;
1153 ARP_STATINC(ARP_STAT_DFRSENT
);
1154 (*ifp
->if_output
)(ifp
, mold
, rt_getkey(rt
), rt
);
1158 if (op
!= ARPOP_REQUEST
) {
1159 if (op
== ARPOP_REPLY
)
1160 ARP_STATINC(ARP_STAT_RCVREPLY
);
1165 ARP_STATINC(ARP_STAT_RCVREQUEST
);
1166 if (in_hosteq(itaddr
, myaddr
)) {
1167 /* I am the target */
1170 memcpy(tha
, ar_sha(ah
), ah
->ar_hln
);
1171 memcpy(ar_sha(ah
), CLLADDR(ifp
->if_sadl
), ah
->ar_hln
);
1173 la
= arplookup(m
, &itaddr
, 0, SIN_PROXY
);
1177 if (rt
->rt_ifp
->if_type
== IFT_CARP
&&
1178 m
->m_pkthdr
.rcvif
->if_type
!= IFT_CARP
)
1182 memcpy(tha
, ar_sha(ah
), ah
->ar_hln
);
1183 sdl
= satosdl(rt
->rt_gateway
);
1184 memcpy(ar_sha(ah
), CLLADDR(sdl
), ah
->ar_hln
);
1187 memcpy(ar_tpa(ah
), ar_spa(ah
), ah
->ar_pln
);
1188 memcpy(ar_spa(ah
), &itaddr
, ah
->ar_pln
);
1189 ah
->ar_op
= htons(ARPOP_REPLY
);
1190 ah
->ar_pro
= htons(ETHERTYPE_IP
); /* let's be sure! */
1191 switch (ifp
->if_type
) {
1194 * ieee1394 arp reply is broadcast
1196 m
->m_flags
&= ~M_MCAST
;
1197 m
->m_flags
|= M_BCAST
;
1198 m
->m_len
= sizeof(*ah
) + (2 * ah
->ar_pln
) + ah
->ar_hln
;
1202 m
->m_flags
&= ~(M_BCAST
|M_MCAST
); /* never reply by broadcast */
1203 m
->m_len
= sizeof(*ah
) + (2 * ah
->ar_pln
) + (2 * ah
->ar_hln
);
1206 m
->m_pkthdr
.len
= m
->m_len
;
1207 sa
.sa_family
= AF_ARP
;
1209 arps
= ARP_STAT_GETREF();
1210 arps
[ARP_STAT_SNDTOTAL
]++;
1211 arps
[ARP_STAT_SNDREPLY
]++;
1213 (*ifp
->if_output
)(ifp
, m
, &sa
, (struct rtentry
*)0);
1218 * Free an arp entry.
1220 static void arptfree(struct llinfo_arp
*la
)
1222 struct rtentry
*rt
= la
->la_rt
;
1223 struct sockaddr_dl
*sdl
;
1229 if (rt
->rt_refcnt
> 0 && (sdl
= satosdl(rt
->rt_gateway
)) &&
1230 sdl
->sdl_family
== AF_LINK
) {
1233 rt
->rt_flags
&= ~RTF_REJECT
;
1236 rtrequest(RTM_DELETE
, rt_getkey(rt
), NULL
, rt_mask(rt
), 0, NULL
);
1239 static struct llinfo_arp
*
1240 arplookup(struct mbuf
*m
, const struct in_addr
*addr
, int create
, int proxy
)
1242 return arplookup1(m
, addr
, create
, proxy
, NULL
);
1246 * Lookup or enter a new address in arptab.
1248 static struct llinfo_arp
*
1249 arplookup1(struct mbuf
*m
, const struct in_addr
*addr
, int create
, int proxy
,
1250 struct rtentry
*rt0
)
1253 struct ifnet
*ifp
= m
->m_pkthdr
.rcvif
;
1255 struct sockaddr_inarp sin
;
1256 const char *why
= NULL
;
1258 ah
= mtod(m
, struct arphdr
*);
1260 memset(&sin
, 0, sizeof(sin
));
1261 sin
.sin_len
= sizeof(sin
);
1262 sin
.sin_family
= AF_INET
;
1263 sin
.sin_addr
= *addr
;
1264 sin
.sin_other
= proxy
? SIN_PROXY
: 0;
1265 rt
= rtalloc1(sintosa(&sin
), create
);
1272 #define IS_LLINFO(__rt) \
1273 (((__rt)->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) == RTF_LLINFO && \
1274 (__rt)->rt_gateway->sa_family == AF_LINK)
1278 return (struct llinfo_arp
*)rt
->rt_llinfo
;
1281 if (rt
->rt_flags
& RTF_GATEWAY
)
1282 why
= "host is not on local network";
1283 else if ((rt
->rt_flags
& RTF_LLINFO
) == 0) {
1284 ARP_STATINC(ARP_STAT_ALLOCFAIL
);
1285 why
= "could not allocate llinfo";
1287 why
= "gateway route is not ours";
1288 log(LOG_DEBUG
, "arplookup: unable to enter address"
1289 " for %s@%s on %s (%s)\n",
1290 in_fmtaddr(*addr
), lla_snprintf(ar_sha(ah
), ah
->ar_hln
),
1291 (ifp
) ? ifp
->if_xname
: "null", why
);
1292 if (rt
->rt_refcnt
<= 0 && (rt
->rt_flags
& RTF_CLONED
) != 0) {
1293 rtrequest(RTM_DELETE
, rt_getkey(rt
),
1294 rt
->rt_gateway
, rt_mask(rt
), rt
->rt_flags
, NULL
);
1301 arpioctl(u_long cmd
, void *data
)
1308 arp_ifinit(struct ifnet
*ifp
, struct ifaddr
*ifa
)
1313 * Warn the user if another station has this IP address,
1314 * but only if the interface IP address is not zero.
1316 ip
= &IA_SIN(ifa
)->sin_addr
;
1317 if (!in_nullhost(*ip
))
1318 arprequest(ifp
, ip
, ip
, CLLADDR(ifp
->if_sadl
));
1320 ifa
->ifa_rtrequest
= arp_rtrequest
;
1321 ifa
->ifa_flags
|= RTF_CLONING
;
1325 * Called from 10 Mb/s Ethernet interrupt handlers
1326 * when ether packet type ETHERTYPE_REVARP
1327 * is received. Common length and type checks are done here,
1328 * then the protocol-specific routine is called.
1331 revarpinput(struct mbuf
*m
)
1335 if (m
->m_len
< sizeof(struct arphdr
))
1337 ar
= mtod(m
, struct arphdr
*);
1338 #if 0 /* XXX I don't think we need this... and it will prevent other LL */
1339 if (ntohs(ar
->ar_hrd
) != ARPHRD_ETHER
)
1342 if (m
->m_len
< sizeof(struct arphdr
) + 2 * (ar
->ar_hln
+ ar
->ar_pln
))
1344 switch (ntohs(ar
->ar_pro
)) {
1346 case ETHERTYPE_IPTRAILERS
:
1358 * RARP for Internet protocols on 10 Mb/s Ethernet.
1359 * Algorithm is that given in RFC 903.
1360 * We are only using for bootstrap purposes to get an ip address for one of
1361 * our interfaces. Thus we support no user-interface.
1363 * Since the contents of the RARP reply are specific to the interface that
1364 * sent the request, this code must ensure that they are properly associated.
1366 * Note: also supports ARP via RARP packets, per the RFC.
1369 in_revarpinput(struct mbuf
*m
)
1376 ah
= mtod(m
, struct arphdr
*);
1377 op
= ntohs(ah
->ar_op
);
1379 switch (m
->m_pkthdr
.rcvif
->if_type
) {
1381 /* ARP without target hardware address is not supported */
1389 case ARPOP_REPLY
: /* per RFC */
1392 case ARPOP_REVREPLY
:
1394 case ARPOP_REVREQUEST
: /* handled by rarpd(8) */
1398 if (!revarp_in_progress
)
1400 ifp
= m
->m_pkthdr
.rcvif
;
1401 if (ifp
!= myip_ifp
) /* !same interface */
1403 if (myip_initialized
)
1408 if (memcmp(tha
, CLLADDR(ifp
->if_sadl
), ifp
->if_sadl
->sdl_alen
))
1410 memcpy(&srv_ip
, ar_spa(ah
), sizeof(srv_ip
));
1411 memcpy(&myip
, ar_tpa(ah
), sizeof(myip
));
1412 myip_initialized
= 1;
1413 wake
: /* Do wakeup every time in case it was missed. */
1414 wakeup((void *)&myip
);
1421 * Send a RARP request for the ip address of the specified interface.
1422 * The request should be RFC 903-compliant.
1425 revarprequest(struct ifnet
*ifp
)
1432 if ((m
= m_gethdr(M_DONTWAIT
, MT_DATA
)) == NULL
)
1434 MCLAIM(m
, &arpdomain
.dom_mowner
);
1435 m
->m_len
= sizeof(*ah
) + 2*sizeof(struct in_addr
) +
1437 m
->m_pkthdr
.len
= m
->m_len
;
1438 MH_ALIGN(m
, m
->m_len
);
1439 ah
= mtod(m
, struct arphdr
*);
1440 memset(ah
, 0, m
->m_len
);
1441 ah
->ar_pro
= htons(ETHERTYPE_IP
);
1442 ah
->ar_hln
= ifp
->if_addrlen
; /* hardware address length */
1443 ah
->ar_pln
= sizeof(struct in_addr
); /* protocol address length */
1444 ah
->ar_op
= htons(ARPOP_REVREQUEST
);
1446 memcpy(ar_sha(ah
), CLLADDR(ifp
->if_sadl
), ah
->ar_hln
);
1450 memcpy(tha
, CLLADDR(ifp
->if_sadl
), ah
->ar_hln
);
1452 sa
.sa_family
= AF_ARP
;
1454 m
->m_flags
|= M_BCAST
;
1455 (*ifp
->if_output
)(ifp
, m
, &sa
, NULL
);
1460 * RARP for the ip address of the specified interface, but also
1461 * save the ip address of the server that sent the answer.
1462 * Timeout if no response is received.
1465 revarpwhoarewe(struct ifnet
*ifp
, struct in_addr
*serv_in
,
1466 struct in_addr
*clnt_in
)
1468 int result
, count
= 20;
1470 myip_initialized
= 0;
1473 revarp_in_progress
= 1;
1476 result
= tsleep((void *)&myip
, PSOCK
, "revarp", hz
/2);
1477 if (result
!= EWOULDBLOCK
)
1480 revarp_in_progress
= 0;
1482 if (!myip_initialized
)
1485 memcpy(serv_in
, &srv_ip
, sizeof(*serv_in
));
1486 memcpy(clnt_in
, &myip
, sizeof(*clnt_in
));
1494 #include <machine/db_machdep.h>
1495 #include <ddb/db_interface.h>
1496 #include <ddb/db_output.h>
1499 db_print_sa(const struct sockaddr
*sa
)
1505 db_printf("[NULL]");
1509 p
= (const u_char
*)sa
;
1513 db_printf("%d", *p
);
1515 if (len
) db_printf(",");
1521 db_print_ifa(struct ifaddr
*ifa
)
1525 db_printf(" ifa_addr=");
1526 db_print_sa(ifa
->ifa_addr
);
1527 db_printf(" ifa_dsta=");
1528 db_print_sa(ifa
->ifa_dstaddr
);
1529 db_printf(" ifa_mask=");
1530 db_print_sa(ifa
->ifa_netmask
);
1531 db_printf(" flags=0x%x,refcnt=%d,metric=%d\n",
1538 db_print_llinfo(void *li
)
1540 struct llinfo_arp
*la
;
1544 la
= (struct llinfo_arp
*)li
;
1545 db_printf(" la_rt=%p la_hold=%p, la_asked=0x%lx\n",
1546 la
->la_rt
, la
->la_hold
, la
->la_asked
);
1550 * Function to pass to rt_walktree().
1551 * Return non-zero error to abort walk.
1554 db_show_rtentry(struct rtentry
*rt
, void *w
)
1556 db_printf("rtentry=%p", rt
);
1558 db_printf(" flags=0x%x refcnt=%d use=%ld expire=%lld\n",
1559 rt
->rt_flags
, rt
->rt_refcnt
,
1560 rt
->rt_use
, (long long)rt
->rt_expire
);
1562 db_printf(" key="); db_print_sa(rt_getkey(rt
));
1563 db_printf(" mask="); db_print_sa(rt_mask(rt
));
1564 db_printf(" gw="); db_print_sa(rt
->rt_gateway
);
1566 db_printf(" ifp=%p ", rt
->rt_ifp
);
1568 db_printf("(%s)", rt
->rt_ifp
->if_xname
);
1570 db_printf("(NULL)");
1572 db_printf(" ifa=%p\n", rt
->rt_ifa
);
1573 db_print_ifa(rt
->rt_ifa
);
1575 db_printf(" gwroute=%p llinfo=%p\n",
1576 rt
->rt_gwroute
, rt
->rt_llinfo
);
1577 db_print_llinfo(rt
->rt_llinfo
);
1583 * Function to print all the route trees.
1584 * Use this from ddb: "show arptab"
1587 db_show_arptab(db_expr_t addr
, bool have_addr
,
1588 db_expr_t count
, const char *modif
)
1590 rt_walktree(AF_INET
, db_show_rtentry
, NULL
);
1595 sysctl_net_inet_arp_stats(SYSCTLFN_ARGS
)
1598 return NETSTAT_SYSCTL(arpstat_percpu
, ARP_NSTATS
);
1602 sysctl_net_inet_arp_setup(struct sysctllog
**clog
)
1604 const struct sysctlnode
*node
;
1606 sysctl_createv(clog
, 0, NULL
, NULL
,
1608 CTLTYPE_NODE
, "net", NULL
,
1611 sysctl_createv(clog
, 0, NULL
, NULL
,
1613 CTLTYPE_NODE
, "inet", NULL
,
1615 CTL_NET
, PF_INET
, CTL_EOL
);
1616 sysctl_createv(clog
, 0, NULL
, &node
,
1618 CTLTYPE_NODE
, "arp",
1619 SYSCTL_DESCR("Address Resolution Protocol"),
1621 CTL_NET
, PF_INET
, CTL_CREATE
, CTL_EOL
);
1623 sysctl_createv(clog
, 0, NULL
, NULL
,
1624 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
1625 CTLTYPE_INT
, "prune",
1626 SYSCTL_DESCR("ARP cache pruning interval"),
1627 NULL
, 0, &arpt_prune
, 0,
1628 CTL_NET
,PF_INET
, node
->sysctl_num
, CTL_CREATE
, CTL_EOL
);
1630 sysctl_createv(clog
, 0, NULL
, NULL
,
1631 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
1632 CTLTYPE_INT
, "keep",
1633 SYSCTL_DESCR("Valid ARP entry lifetime"),
1634 NULL
, 0, &arpt_keep
, 0,
1635 CTL_NET
,PF_INET
, node
->sysctl_num
, CTL_CREATE
, CTL_EOL
);
1637 sysctl_createv(clog
, 0, NULL
, NULL
,
1638 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
1639 CTLTYPE_INT
, "down",
1640 SYSCTL_DESCR("Failed ARP entry lifetime"),
1641 NULL
, 0, &arpt_down
, 0,
1642 CTL_NET
,PF_INET
, node
->sysctl_num
, CTL_CREATE
, CTL_EOL
);
1644 sysctl_createv(clog
, 0, NULL
, NULL
,
1645 CTLFLAG_PERMANENT
|CTLFLAG_READWRITE
,
1646 CTLTYPE_INT
, "refresh",
1647 SYSCTL_DESCR("ARP entry refresh interval"),
1648 NULL
, 0, &arpt_refresh
, 0,
1649 CTL_NET
,PF_INET
, node
->sysctl_num
, CTL_CREATE
, CTL_EOL
);
1651 sysctl_createv(clog
, 0, NULL
, NULL
,
1653 CTLTYPE_STRUCT
, "stats",
1654 SYSCTL_DESCR("ARP statistics"),
1655 sysctl_net_inet_arp_stats
, 0, NULL
, 0,
1656 CTL_NET
,PF_INET
, node
->sysctl_num
, CTL_CREATE
, CTL_EOL
);