summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2016-03-30 10:13:14 +0000
committermpi <mpi@openbsd.org>2016-03-30 10:13:14 +0000
commit83eaa5b12f4436b13c2ba1d8348d921d99416fc6 (patch)
treec45bb3636185d1c65812c5111e61e3679a80dae9
parentHook up the gpio interrupt on devices that use it for card detection. (diff)
downloadwireguard-openbsd-83eaa5b12f4436b13c2ba1d8348d921d99416fc6.tar.xz
wireguard-openbsd-83eaa5b12f4436b13c2ba1d8348d921d99416fc6.zip
Implement proxy ARP for ART based on mpath support.
Since mpath is not enabled in RAMDISK, proxy ARP won't work there either. ok bluhm@
-rw-r--r--sys/net/route.h3
-rw-r--r--sys/net/rtsock.c46
-rw-r--r--sys/netinet/if_ether.c16
-rw-r--r--sys/netinet/if_ether.h3
-rw-r--r--sys/netinet6/nd6.h7
5 files changed, 63 insertions, 12 deletions
diff --git a/sys/net/route.h b/sys/net/route.h
index 15b76bfed3d..bef35438642 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.h,v 1.133 2016/03/26 21:56:04 mpi Exp $ */
+/* $OpenBSD: route.h,v 1.134 2016/03/30 10:13:14 mpi Exp $ */
/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */
/*
@@ -136,6 +136,7 @@ struct rtentry {
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
#define RTF_PROTO3 0x2000 /* protocol specific routing flag */
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
+#define RTF_ANNOUNCE RTF_PROTO2 /* announce L2 entry */
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
#define RTF_CLONED 0x10000 /* this is a cloned route */
#define RTF_MPATH 0x40000 /* multipath route or operation */
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 008d91e0a77..11ef5246a4c 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsock.c,v 1.187 2016/03/26 21:56:04 mpi Exp $ */
+/* $OpenBSD: rtsock.c,v 1.188 2016/03/30 10:13:14 mpi Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
@@ -98,6 +98,7 @@ struct walkarg {
int route_ctloutput(int, struct socket *, int, int, struct mbuf **);
void route_input(struct mbuf *m0, ...);
+int route_arp_conflict(struct rt_addrinfo *, unsigned int);
struct mbuf *rt_msg1(int, struct rt_addrinfo *);
int rt_msg2(int, int, struct rt_addrinfo *, caddr_t,
@@ -600,6 +601,8 @@ route_output(struct mbuf *m, ...)
error = EINVAL;
goto flush;
}
+ if ((error = route_arp_conflict(&info, tableid)))
+ goto flush;
error = rtrequest(RTM_ADD, &info, prio, &saved_nrt, tableid);
if (error == 0) {
rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
@@ -886,6 +889,47 @@ fail:
return (error);
}
+/*
+ * Check if the user request to insert an ARP entry does not conflict
+ * with existing ones.
+ *
+ * Only two entries are allowed for a given IP address: a private one
+ * (priv) and a public one (pub).
+ */
+int
+route_arp_conflict(struct rt_addrinfo *info, unsigned int tableid)
+{
+#if defined(ART) && !defined(SMALL_KERNEL)
+ struct rtentry *rt;
+ int proxy = (info->rti_flags & RTF_ANNOUNCE);
+
+ if ((info->rti_flags & RTF_LLINFO) == 0 ||
+ (info->rti_info[RTAX_DST]->sa_family != AF_INET))
+ return (0);
+
+ rt = rtalloc(info->rti_info[RTAX_DST], 0, tableid);
+ if (rt == NULL || !ISSET(rt->rt_flags, RTF_LLINFO)) {
+ rtfree(rt);
+ return (0);
+ }
+
+ /*
+ * Same destination and both "priv" or "pub" conflict.
+ * If a second entry exists, it always conflict.
+ */
+ if ((ISSET(rt->rt_flags, RTF_ANNOUNCE) == proxy) ||
+ (rtable_mpath_next(rt) != NULL)) {
+ rtfree(rt);
+ return (EEXIST);
+ }
+
+ /* No conflict but an entry exist so we need to force mpath. */
+ info->rti_flags |= RTF_MPATH;
+ rtfree(rt);
+#endif /* ART && !SMALL_KERNEL */
+ return (0);
+}
+
void
rt_setmetrics(u_long which, struct rt_metrics *in, struct rt_kmetrics *out)
{
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 50095387798..ca7fea72be9 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.c,v 1.203 2016/03/24 07:15:10 mpi Exp $ */
+/* $OpenBSD: if_ether.c,v 1.204 2016/03/30 10:13:14 mpi Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
@@ -698,8 +698,20 @@ arplookup(u_int32_t addr, int create, int proxy, u_int tableid)
}
if (proxy && !ISSET(rt->rt_flags, RTF_ANNOUNCE)) {
+ struct rtentry *mrt = NULL;
+#if defined(ART) && !defined(SMALL_KERNEL)
+ mrt = rt;
+ KERNEL_LOCK();
+ while ((mrt = rtable_mpath_next(mrt)) != NULL) {
+ if (ISSET(mrt->rt_flags, RTF_ANNOUNCE)) {
+ rtref(mrt);
+ break;
+ }
+ }
+ KERNEL_UNLOCK();
+#endif /* ART && !SMALL_KERNEL */
rtfree(rt);
- return (NULL);
+ return (mrt);
}
return (rt);
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index 365693b0103..a6e5fc1bd01 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.h,v 1.69 2016/03/16 11:48:27 dlg Exp $ */
+/* $OpenBSD: if_ether.h,v 1.70 2016/03/30 10:13:14 mpi Exp $ */
/* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */
/*
@@ -148,7 +148,6 @@ struct sockaddr_inarp {
* IP and ethernet specific routing flags
*/
#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */
-#define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */
#define RTF_PERMANENT_ARP RTF_PROTO3 /* only manual overwrite of entry */
#ifdef _KERNEL
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 1f534d02d04..80e91781fa9 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.h,v 1.57 2016/03/03 12:57:15 jca Exp $ */
+/* $OpenBSD: nd6.h,v 1.58 2016/03/30 10:13:14 mpi Exp $ */
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
/*
@@ -35,11 +35,6 @@
#include <sys/task.h>
-/* see net/route.h, or net/if_inarp.h */
-#ifndef RTF_ANNOUNCE
-#define RTF_ANNOUNCE RTF_PROTO2
-#endif
-
#define ND6_LLINFO_PURGE -3
#define ND6_LLINFO_NOSTATE -2
#define ND6_LLINFO_INCOMPLETE 0