diff options
author | 2016-03-30 10:13:14 +0000 | |
---|---|---|
committer | 2016-03-30 10:13:14 +0000 | |
commit | 83eaa5b12f4436b13c2ba1d8348d921d99416fc6 (patch) | |
tree | c45bb3636185d1c65812c5111e61e3679a80dae9 | |
parent | Hook up the gpio interrupt on devices that use it for card detection. (diff) | |
download | wireguard-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.h | 3 | ||||
-rw-r--r-- | sys/net/rtsock.c | 46 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 16 | ||||
-rw-r--r-- | sys/netinet/if_ether.h | 3 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 7 |
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 |