summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2019-01-20 23:43:14 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2019-01-20 23:43:14 +0000
commitbbdc35a0a0cdc2bcacf7b1decabf58de829f7922 (patch)
treee53125e0691b4925657bd790b05d9a07c059ffeb /sys
parentc3b184c88a7ace5328f8e02108a5eb66e5b77501 (diff)
Refresh arp entries that are about to expire. Once their life time is less
then 1/8 of net.inet.ip.arptimeout the system will send out a arp request about every 30 seconds until either the entry is updated or expired. Not refreshing arp entries will result in packet drop every time a entry expires which is not ideal for important gateway entries. Came up with this after a discussion with deraadt@. OK benno@ deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/if_ether.c64
1 files changed, 32 insertions, 32 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 21b133233cd..130d107e820 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.c,v 1.237 2018/11/30 09:27:56 claudio Exp $ */
+/* $OpenBSD: if_ether.c,v 1.238 2019/01/20 23:43:13 claudio Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
@@ -67,8 +67,9 @@
struct llinfo_arp {
LIST_ENTRY(llinfo_arp) la_list;
struct rtentry *la_rt; /* backpointer to rtentry */
- long la_asked; /* last time we QUERIED */
struct mbuf_list la_ml; /* packet hold queue */
+ time_t la_refreshed; /* when was refresh sent */
+ int la_asked; /* number of queries sent */
};
#define LA_HOLD_QUEUE 10
#define LA_HOLD_TOTAL 100
@@ -119,7 +120,7 @@ arptimer(void *arg)
LIST_FOREACH_SAFE(la, &arp_list, la_list, nla) {
struct rtentry *rt = la->la_rt;
- if (rt->rt_expire && rt->rt_expire <= time_uptime)
+ if (rt->rt_expire && rt->rt_expire < time_uptime)
arptfree(rt); /* timer has expired; clear */
}
NET_UNLOCK();
@@ -130,7 +131,6 @@ arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
{
struct sockaddr *gate = rt->rt_gateway;
struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
- struct ifaddr *ifa;
if (!arpinit_done) {
static struct timeout arptimer_to;
@@ -140,7 +140,7 @@ arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
IPL_SOFTNET, 0, "arp", NULL);
timeout_set_proc(&arptimer_to, arptimer, &arptimer_to);
- timeout_add_sec(&arptimer_to, 1);
+ timeout_add_sec(&arptimer_to, arpt_prune);
}
if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_BROADCAST|RTF_MULTICAST))
@@ -149,17 +149,12 @@ arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
switch (req) {
case RTM_ADD:
- if (rt->rt_flags & RTF_CLONING ||
- ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la)) {
- /*
- * Give this route an expiration time, even though
- * it's a "permanent" route, so that routes cloned
- * from it do not need their expiration time set.
- */
- rt->rt_expire = time_uptime;
- if ((rt->rt_flags & RTF_CLONING) != 0)
- break;
+ if (rt->rt_flags & RTF_CLONING) {
+ rt->rt_expire = 0;
+ break;
}
+ if ((rt->rt_flags & RTF_LOCAL) && !la)
+ rt->rt_expire = 0;
/*
* Announce a new entry if requested or warn the user
* if another station has this IP address.
@@ -179,7 +174,7 @@ arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
}
satosdl(gate)->sdl_type = ifp->if_type;
satosdl(gate)->sdl_index = ifp->if_index;
- if (la != 0)
+ if (la != NULL)
break; /* This happens on a route change */
/*
* Case 2: This route may come from cloning, or a manual route
@@ -195,18 +190,9 @@ arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
ml_init(&la->la_ml);
la->la_rt = rt;
rt->rt_flags |= RTF_LLINFO;
+ if ((rt->rt_flags & RTF_LOCAL) == 0)
+ rt->rt_expire = time_uptime;
LIST_INSERT_HEAD(&arp_list, la, la_list);
-
- TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
- if ((ifa->ifa_addr->sa_family == AF_INET) &&
- ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
- satosin(rt_key(rt))->sin_addr.s_addr)
- break;
- }
- if (ifa) {
- KASSERT(ifa == rt->rt_ifa);
- rt->rt_expire = 0;
- }
break;
case RTM_DELETE:
@@ -314,7 +300,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
struct sockaddr *dst, u_char *desten)
{
struct arpcom *ac = (struct arpcom *)ifp;
- struct llinfo_arp *la = NULL;
+ struct llinfo_arp *la;
struct sockaddr_dl *sdl;
struct rtentry *rt = NULL;
char addr[INET_ADDRSTRLEN];
@@ -331,7 +317,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
rt = rt_getll(rt0);
if (ISSET(rt->rt_flags, RTF_REJECT) &&
- (rt->rt_expire == 0 || time_uptime < rt->rt_expire)) {
+ (rt->rt_expire == 0 || rt->rt_expire > time_uptime )) {
m_freem(m);
return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
}
@@ -352,6 +338,9 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
goto bad;
}
+ la = (struct llinfo_arp *)rt->rt_llinfo;
+ KASSERT(la != NULL);
+
/*
* Check the address family and length is valid, the address
* is resolved; otherwise, try to resolve.
@@ -359,6 +348,17 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) &&
sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
memcpy(desten, LLADDR(sdl), sdl->sdl_alen);
+
+ /* refresh ARP entry when timeout gets close */
+ if (rt->rt_expire != 0 &&
+ rt->rt_expire - arpt_keep / 8 < time_uptime &&
+ la->la_refreshed + 30 < time_uptime) {
+ la->la_refreshed = time_uptime;
+ arprequest(ifp,
+ &satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr,
+ &satosin(dst)->sin_addr.s_addr,
+ ac->ac_enaddr);
+ }
return (0);
}
@@ -370,9 +370,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
* response yet. Insert mbuf in hold queue if below limit
* if above the limit free the queue without queuing the new packet.
*/
- la = (struct llinfo_arp *)rt->rt_llinfo;
- KASSERT(la != NULL);
- if (la_hold_total < LA_HOLD_TOTAL && la_hold_total < nmbclust / 64) {
+ if (la_hold_total < LA_HOLD_TOTAL) {
struct mbuf *mh;
if (ml_len(&la->la_ml) >= LA_HOLD_QUEUE) {
@@ -411,6 +409,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
rt->rt_flags |= RTF_REJECT;
rt->rt_expire += arpt_down;
la->la_asked = 0;
+ la->la_refreshed = 0;
la_hold_total -= ml_purge(&la->la_ml);
}
}
@@ -668,6 +667,7 @@ arpcache(struct ifnet *ifp, struct ether_arp *ea, struct rtentry *rt)
}
la->la_asked = 0;
+ la->la_refreshed = 0;
while ((len = ml_len(&la->la_ml)) != 0) {
struct mbuf *mh;