summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpi <mpi@openbsd.org>2014-08-19 12:49:41 +0000
committermpi <mpi@openbsd.org>2014-08-19 12:49:41 +0000
commitf880c90912c34a9d270a0e51a9ddc66dfddd1c2c (patch)
treef3b4829df0d212104ea198e7cd9aaf4aa471bbe2
parentEntries for broadcast addresses should also be ignored, just like local (diff)
downloadwireguard-openbsd-f880c90912c34a9d270a0e51a9ddc66dfddd1c2c.tar.xz
wireguard-openbsd-f880c90912c34a9d270a0e51a9ddc66dfddd1c2c.zip
When a local route entry is added for an ifa having a broadcast address,
also adds a broadcast entry flagged with RTF_BROADCAST. Prior to this change broadcast entries were simple clonned ARP entries, that would be deleted once their timer expired since they would always be incomplete. With this change they are now persistant and identifiable with a new flag. Committing early to be able to deal with any potential fallout before we start relying on this. ok florian@, mikeb@, henning@
-rw-r--r--sys/net/route.c32
-rw-r--r--sys/netinet/if_ether.c14
2 files changed, 39 insertions, 7 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index f8a6583a1f3..b31351c13cb 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.178 2014/08/14 09:01:47 mpi Exp $ */
+/* $OpenBSD: route.c,v 1.179 2014/08/19 12:49:41 mpi Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -790,7 +790,8 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio,
* sure that local routes are only modified by the
* kernel.
*/
- if (rt->rt_flags & RTF_LOCAL && prio != RTP_LOCAL)
+ if ((rt->rt_flags & (RTF_LOCAL | RTF_BROADCAST)) &&
+ prio != RTP_LOCAL)
senderr(EINVAL);
if ((rn = rnh->rnh_deladdr(info->rti_info[RTAX_DST],
@@ -1109,7 +1110,7 @@ rt_ifa_add(struct ifaddr *ifa, int flags, struct sockaddr *dst)
if ((flags & RTF_HOST) == 0)
info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
- if (flags & RTF_LOCAL)
+ if (flags & (RTF_LOCAL|RTF_BROADCAST))
prio = RTP_LOCAL;
error = rtrequest1(RTM_ADD, &info, prio, &nrt, rtableid);
@@ -1127,6 +1128,12 @@ rt_ifa_add(struct ifaddr *ifa, int flags, struct sockaddr *dst)
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(RTM_ADD, rt);
}
+
+ /*
+ * A local route is created for every address configured
+ * on an interface, so use this information to notify
+ * userland that a new address has been added.
+ */
if (flags & RTF_LOCAL)
rt_newaddrmsg(RTM_ADD, ifa, error, nrt);
}
@@ -1177,7 +1184,7 @@ rt_ifa_del(struct ifaddr *ifa, int flags, struct sockaddr *dst)
if ((flags & RTF_HOST) == 0)
info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask;
- if (flags & RTF_LOCAL)
+ if (flags & (RTF_LOCAL|RTF_BROADCAST))
prio = RTP_LOCAL;
error = rtrequest1(RTM_DELETE, &info, prio, &nrt, rtableid);
@@ -1228,9 +1235,16 @@ rt_ifa_addloop(struct ifaddr *ifa)
/* If there is no loopback entry, allocate one. */
rt = rtalloc1(ifa->ifa_addr, 0, ifa->ifa_ifp->if_rdomain);
if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
- (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
+ (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) {
rt_ifa_add(ifa, RTF_UP| RTF_HOST | RTF_LLINFO | RTF_LOCAL,
ifa->ifa_addr);
+
+ if ((ifa->ifa_ifp->if_flags & IFF_BROADCAST) &&
+ ifa->ifa_broadaddr)
+ rt_ifa_add(ifa, RTF_UP | RTF_HOST | RTF_LLINFO |
+ RTF_BROADCAST, ifa->ifa_broadaddr);
+
+ }
if (rt)
rt->rt_refcnt--;
}
@@ -1273,9 +1287,15 @@ rt_ifa_delloop(struct ifaddr *ifa)
*/
rt = rtalloc1(ifa->ifa_addr, 0, ifa->ifa_ifp->if_rdomain);
if (rt != NULL && (rt->rt_flags & RTF_HOST) != 0 &&
- (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0)
+ (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
rt_ifa_del(ifa, RTF_HOST | RTF_LLINFO | RTF_LOCAL,
ifa->ifa_addr);
+
+ if ((ifa->ifa_ifp->if_flags & IFF_BROADCAST) &&
+ ifa->ifa_broadaddr)
+ rt_ifa_del(ifa, RTF_HOST | RTF_LLINFO | RTF_BROADCAST,
+ ifa->ifa_broadaddr);
+ }
if (rt)
rt->rt_refcnt--;
}
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 3d8d7f81c1b..11f7876a472 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.c,v 1.133 2014/08/11 13:51:07 mpi Exp $ */
+/* $OpenBSD: if_ether.c,v 1.134 2014/08/19 12:49:41 mpi Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
@@ -232,6 +232,18 @@ arp_rtrequest(int req, struct rtentry *rt)
rt->rt_flags |= RTF_LLINFO;
LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
+ /*
+ * Routes to broadcast addresses must be incomplete
+ * arp entries so that they won't be picked up, but
+ * since we expect them to always be present in the
+ * routing table, make sure arptimer() won't free
+ * them.
+ */
+ if (rt->rt_flags & RTF_BROADCAST) {
+ rt->rt_expire = 0;
+ break;
+ }
+
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
if ((ifa->ifa_addr->sa_family == AF_INET) &&
ifatoia(ifa)->ia_addr.sin_addr.s_addr ==