Page MenuHomeFreeBSD

D14547.id39839.diff
No OneTemporary

D14547.id39839.diff

Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -78,6 +78,8 @@
static void in_socktrim(struct sockaddr_in *);
static void in_purgemaddrs(struct ifnet *);
+static void in_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info);
+
static VNET_DEFINE(int, nosameprefix);
#define V_nosameprefix VNET(nosameprefix)
SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW,
@@ -401,6 +403,7 @@
ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
callout_init_rw(&ia->ia_garp_timer, &ifp->if_addr_lock,
CALLOUT_RETURNUNLOCKED);
+ ifa->ifa_rtrequest = in_rtrequest;
ia->ia_ifp = ifp;
ia->ia_addr = *addr;
@@ -1497,3 +1500,56 @@
lltable_free(ii->ii_llt);
free(ii, M_IFADDR);
}
+
+/*
+ * Return true if the route described by info is the local subnet route for
+ * ifa, or false otherwise.
+ */
+static int
+in_is_subnet_route(struct ifaddr *ifa, struct rt_addrinfo *info)
+{
+ struct sockaddr *tmp_sa;
+ struct sockaddr_storage tmp_storage;
+
+ if (info->rti_info[RTAX_DST] == NULL || info->rti_info[RTAX_NETMASK] == NULL)
+ return (0);
+
+ /* First test that the ifaddr falls into the subnet described by the route. */
+ tmp_sa = (struct sockaddr*)&tmp_storage;
+ rt_maskedcopy(ifa->ifa_addr, tmp_sa, ifa->ifa_netmask);
+
+ if (!sa_equal(tmp_sa, info->rti_info[RTAX_DST]))
+ return (0);
+
+ /*
+ * Now test that the subnet mask is the same for the address and
+ * the route. If they are different then the route has a different
+ * prefix size and ifa just happens to fall within that route.
+ *
+ * For some reason ifa->ifa_netmask sa_len field is not
+ * sizeof(struct sockaddr_in). This causes attempts to directly
+ * compare against info->rti_info[RTAX_NETMASK] to incorrectly
+ * fail even if the netmasks are the same. Fix this by making a
+ * copy of ifa->ifa_netmask with the length field correct.
+ */
+ bzero(tmp_sa, sizeof(struct sockaddr_in));
+ memcpy(tmp_sa, ifa->ifa_netmask, ifa->ifa_netmask->sa_len);
+ tmp_sa->sa_len = sizeof(struct sockaddr_in);
+
+ return (sa_equal(info->rti_info[RTAX_NETMASK], tmp_sa));
+}
+
+static void
+in_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+{
+
+ /*
+ * If we are modifying a route to a subnet, we need to migrate the IFA_ROUTE
+ * flag to the new source ifa for the route.
+ */
+ if (req == RTM_DELETE && rt->rt_ifa->ifa_flags & IFA_ROUTE &&
+ info->rti_ifa != NULL && in_is_subnet_route(rt->rt_ifa, info)) {
+ rt->rt_ifa->ifa_flags &= ~IFA_ROUTE;
+ info->rti_ifa->ifa_flags |= IFA_ROUTE;
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Jun 25, 12:05 AM (9 m, 47 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34284635
Default Alt Text
D14547.id39839.diff (2 KB)

Event Timeline