summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2014-09-03 08:59:07 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2014-09-03 08:59:07 +0000
commit497384e6542634cc614c06f7b2c5f6dcd1d3cf18 (patch)
tree897f24bed34c1d99f5488733010cdd442311d3ca
parent8e4e02b65736c486bea276346c064c5ce4e36723 (diff)
When a route to prefix (connected route) is added, if its associated
broadcast address is non null, add a broadcast entry flagged with RTF_BROADCAST. Re-use the existing logic to switch a route to prefix from an ifa to another to also move this broadcast entry. 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 This version of the diff prevent a corruption reported by millert@ ok mikeb@, florian@
-rw-r--r--sys/netinet/in.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 747613c4d49..df5ccde35a7 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.c,v 1.102 2014/08/23 18:32:55 bluhm Exp $ */
+/* $OpenBSD: in.c,v 1.103 2014/09/03 08:59:06 mpi Exp $ */
/* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
/*
@@ -98,6 +98,8 @@ int in_addprefix(struct in_ifaddr *);
int in_scrubprefix(struct in_ifaddr *);
int in_addhost(struct in_ifaddr *);
int in_scrubhost(struct in_ifaddr *);
+int in_insert_prefix(struct in_ifaddr *);
+void in_remove_prefix(struct in_ifaddr *);
/*
* Determine whether an IP address is in a reserved set of addresses
@@ -808,6 +810,43 @@ in_scrubhost(struct in_ifaddr *ia0)
}
/*
+ * Insert the cloning and broadcast routes for this subnet.
+ */
+int
+in_insert_prefix(struct in_ifaddr *ia)
+{
+ struct ifaddr *ifa = &ia->ia_ifa;
+ int error;
+
+ error = rt_ifa_add(ifa, RTF_UP | RTF_CLONING, ifa->ifa_addr);
+ if (error)
+ return (error);
+
+ if (ia->ia_broadaddr.sin_addr.s_addr != 0)
+ error = rt_ifa_add(ifa, RTF_UP | RTF_HOST |
+ RTF_LLINFO | RTF_BROADCAST, ifa->ifa_broadaddr);
+
+ if (!error)
+ ia->ia_flags |= IFA_ROUTE;
+
+ return (error);
+}
+
+void
+in_remove_prefix(struct in_ifaddr *ia)
+{
+ struct ifaddr *ifa = &ia->ia_ifa;
+
+ rt_ifa_del(ifa, 0, ifa->ifa_addr);
+
+ if (ia->ia_broadaddr.sin_addr.s_addr != 0)
+ rt_ifa_del(ifa, RTF_HOST | RTF_LLINFO | RTF_BROADCAST,
+ ifa->ifa_broadaddr);
+
+ ia->ia_flags &= ~IFA_ROUTE;
+}
+
+/*
* add a route to prefix ("connected route" in cisco terminology).
* does nothing if there's some interface address with the same prefix already.
*/
@@ -816,7 +855,6 @@ in_addprefix(struct in_ifaddr *ia0)
{
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
- int error;
prefix = ia0->ia_addr.sin_addr;
mask = ia0->ia_sockmask.sin_addr;
@@ -843,8 +881,7 @@ in_addprefix(struct in_ifaddr *ia0)
/* move to a real interface instead of carp interface */
if (ia->ia_ifp->if_type == IFT_CARP &&
ia0->ia_ifp->if_type != IFT_CARP) {
- rt_ifa_del(&ia->ia_ifa, 0, ia->ia_ifa.ifa_addr);
- ia->ia_flags &= ~IFA_ROUTE;
+ in_remove_prefix(ia);
break;
}
#endif
@@ -858,11 +895,7 @@ in_addprefix(struct in_ifaddr *ia0)
/*
* noone seem to have prefix route. insert it.
*/
- error = rt_ifa_add(&ia0->ia_ifa, RTF_UP | RTF_CLONING,
- ia0->ia_ifa.ifa_addr);
- if (!error)
- ia0->ia_flags |= IFA_ROUTE;
- return error;
+ return in_insert_prefix(ia0);
}
/*
@@ -875,7 +908,6 @@ in_scrubprefix(struct in_ifaddr *ia0)
{
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
- int error;
if ((ia0->ia_flags & IFA_ROUTE) == 0)
return 0;
@@ -904,20 +936,14 @@ in_scrubprefix(struct in_ifaddr *ia0)
/*
* if we got a matching prefix route, move IFA_ROUTE to him
*/
- rt_ifa_del(&ia0->ia_ifa, 0, ia0->ia_ifa.ifa_addr);
- ia0->ia_flags &= ~IFA_ROUTE;
- error = rt_ifa_add(&ia->ia_ifa, RTF_UP | RTF_CLONING,
- ia->ia_ifa.ifa_addr);
- if (error == 0)
- ia->ia_flags |= IFA_ROUTE;
- return error;
+ in_remove_prefix(ia0);
+ return in_insert_prefix(ia);
}
/*
* noone seem to have prefix route. remove it.
*/
- rt_ifa_del(&ia0->ia_ifa, 0, ia0->ia_ifa.ifa_addr);
- ia0->ia_flags &= ~IFA_ROUTE;
+ in_remove_prefix(ia0);
return 0;
}