Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Introduce the routing flag RTF_LOCAL to track local addr...
details: https://anonhg.NetBSD.org/src/rev/634d6c2fa097
branches: trunk
changeset: 336339:634d6c2fa097
user: roy <roy%NetBSD.org@localhost>
date: Thu Feb 26 09:54:46 2015 +0000
description:
Introduce the routing flag RTF_LOCAL to track local address routes.
Add functions rt_ifa_addlocal() and rt_ifa_remlocal() to add and remove
local routes for the address and announce the new address and route
to the routing socket.
Add in_ifaddlocal() and in_ifremlocal() to use these functions.
Rename in6_if{add,rem}loop() to in6_if{add,rem}local() and use these
functions.
rtinit() no longer announces the address, just the network route for the
address. As such, calls to rt_newaddrmsg() have been removed from
in_addprefix() and in_scrubprefix().
This solves the problem of potentially more than one announcement, or no
announcement at all for the address in certain situations.
diffstat:
sys/net/route.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++-
sys/net/route.h | 5 +-
sys/netinet/if_arp.c | 15 +++-
sys/netinet/in.c | 56 ++++++++++++++++----
sys/netinet/ip_carp.c | 8 +-
sys/netinet6/in6.c | 123 +++++----------------------------------------
sys/netinet6/in6_var.h | 6 +-
7 files changed, 206 insertions(+), 138 deletions(-)
diffs (truncated from 603 to 300 lines):
diff -r 18dbabe375b9 -r 634d6c2fa097 sys/net/route.c
--- a/sys/net/route.c Thu Feb 26 09:10:52 2015 +0000
+++ b/sys/net/route.c Thu Feb 26 09:54:46 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: route.c,v 1.135 2015/02/25 12:45:34 roy Exp $ */
+/* $NetBSD: route.c,v 1.136 2015/02/26 09:54:46 roy Exp $ */
/*-
* Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -90,10 +90,11 @@
* @(#)route.c 8.3 (Berkeley) 1/9/95
*/
+#include "opt_inet.h"
#include "opt_route.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.135 2015/02/25 12:45:34 roy Exp $");
+__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.136 2015/02/26 09:54:46 roy Exp $");
#include <sys/param.h>
#include <sys/kmem.h>
@@ -960,7 +961,7 @@
;
else switch (cmd) {
case RTM_DELETE:
- rt_newaddrmsg(cmd, ifa, error, nrt);
+ rt_newmsg(cmd, nrt);
if (rt->rt_refcnt <= 0) {
rt->rt_refcnt++;
rtfree(rt);
@@ -984,7 +985,7 @@
if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL)
ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info);
- rt_newaddrmsg(RTM_CHANGE, ifa, error, nrt);
+ rt_newmsg(RTM_CHANGE, nrt);
break;
case RTM_ADD:
rt->rt_refcnt--;
@@ -1000,12 +1001,132 @@
if (ifa->ifa_rtrequest != NULL)
ifa->ifa_rtrequest(RTM_ADD, rt, &info);
}
- rt_newaddrmsg(cmd, ifa, error, nrt);
+ rt_newmsg(cmd, nrt);
break;
}
return error;
}
+static const struct in_addr inmask32 = {.s_addr = INADDR_BROADCAST};
+
+/* Subroutine for rt_ifa_addlocal() and rt_ifa_remlocal() */
+static int
+rt_ifa_localrequest(int cmd, struct ifaddr *ifa)
+{
+ struct sockaddr *all1_sa;
+ struct sockaddr_in all1_sin;
+#ifdef INET6
+ struct sockaddr_in6 all1_sin6;
+#endif
+ struct rtentry *nrt = NULL;
+ int flags, e;
+
+ switch(ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ sockaddr_in_init(&all1_sin, &inmask32, 0);
+ all1_sa = (struct sockaddr *)&all1_sin;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ sockaddr_in6_init(&all1_sin6, &in6mask128, 0, 0, 0);
+ all1_sa = (struct sockaddr *)&all1_sin6;
+ break;
+#endif
+ default:
+ return 0;
+ }
+
+ flags = RTF_UP | RTF_HOST | RTF_LOCAL;
+ if (!(ifa->ifa_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
+ flags |= RTF_LLINFO;
+ e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr, all1_sa, flags, &nrt);
+
+ /* Make sure rt_ifa be equal to IFA, the second argument of the
+ * function. */
+ if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa)
+ rt_replace_ifa(nrt, ifa);
+
+ rt_newaddrmsg(cmd, ifa, e, nrt);
+ if (nrt) {
+ if (cmd == RTM_DELETE) {
+ if (nrt->rt_refcnt <= 0) {
+ /* XXX: we should free the entry ourselves. */
+ nrt->rt_refcnt++;
+ rtfree(nrt);
+ }
+ } else {
+ /* the cmd must be RTM_ADD here */
+ nrt->rt_refcnt--;
+ }
+ }
+ return e;
+}
+
+/*
+ * Create a local route entry for the address.
+ * Announce the addition of the address and the route to the routing socket.
+ */
+int
+rt_ifa_addlocal(struct ifaddr *ifa)
+{
+ struct rtentry *rt;
+ int e;
+
+ /* If there is no loopback entry, allocate one. */
+ rt = rtalloc1(ifa->ifa_addr, 0);
+ if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
+ (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
+ e = rt_ifa_localrequest(RTM_ADD, ifa);
+ else {
+ e = 0;
+ rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
+ }
+ if (rt != NULL)
+ rt->rt_refcnt--;
+ return e;
+}
+
+/*
+ * Remove the local route entry for the address.
+ * Announce the removal of the address and the route to the routing socket.
+ */
+int
+rt_ifa_remlocal(struct ifaddr *ifa, struct ifaddr *alt_ifa)
+{
+ struct rtentry *rt;
+ int e = 0;
+
+ rt = rtalloc1(ifa->ifa_addr, 0);
+
+ /*
+ * Before deleting, check if a corresponding loopbacked
+ * host route surely exists. With this check, we can avoid
+ * deleting an interface direct route whose destination is
+ * the same as the address being removed. This can happen
+ * when removing a subnet-router anycast address on an
+ * interface attached to a shared medium.
+ */
+ if (rt != NULL &&
+ (rt->rt_flags & RTF_HOST) &&
+ (rt->rt_ifp->if_flags & IFF_LOOPBACK))
+ {
+ /* If we cannot replace the route's ifaddr with the equivalent
+ * ifaddr of another interface, I believe it is safest to
+ * delete the route.
+ */
+ if (alt_ifa == NULL)
+ e = rt_ifa_localrequest(RTM_DELETE, ifa);
+ else {
+ rt_replace_ifa(rt, alt_ifa);
+ rt_newmsg(RTM_CHANGE, rt);
+ }
+ } else
+ rt_newaddrmsg(RTM_DELADDR, ifa, 0, NULL);
+ if (rt != NULL)
+ rt->rt_refcnt--;
+ return e;
+}
+
/*
* Route timer routines. These routes allow functions to be called
* for various routes at any time. This is useful in supporting
diff -r 18dbabe375b9 -r 634d6c2fa097 sys/net/route.h
--- a/sys/net/route.h Thu Feb 26 09:10:52 2015 +0000
+++ b/sys/net/route.h Thu Feb 26 09:54:46 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: route.h,v 1.86 2015/02/25 12:45:34 roy Exp $ */
+/* $NetBSD: route.h,v 1.87 2015/02/26 09:54:46 roy Exp $ */
/*
* Copyright (c) 1980, 1986, 1993
@@ -155,6 +155,7 @@
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
#define RTF_SRC 0x10000 /* route has fixed source address */
#define RTF_ANNOUNCE 0x20000 /* announce new ARP or NDP entry */
+#define RTF_LOCAL 0x40000 /* route represents a local address */
/*
* Routing statistics.
@@ -504,6 +505,8 @@
struct rtentry *rt_deladdr(rtbl_t *, const struct sockaddr *,
const struct sockaddr *);
void rtbl_init(void);
+int rt_ifa_addlocal(struct ifaddr *);
+int rt_ifa_remlocal(struct ifaddr *, struct ifaddr *);
rtbl_t *rt_gettable(sa_family_t);
void rt_assert_inactive(const struct rtentry *);
diff -r 18dbabe375b9 -r 634d6c2fa097 sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c Thu Feb 26 09:10:52 2015 +0000
+++ b/sys/netinet/if_arp.c Thu Feb 26 09:54:46 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_arp.c,v 1.160 2014/11/13 16:11:18 christos Exp $ */
+/* $NetBSD: if_arp.c,v 1.161 2015/02/26 09:54:46 roy Exp $ */
/*-
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.160 2014/11/13 16:11:18 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.161 2015/02/26 09:54:46 roy Exp $");
#include "opt_ddb.h"
#include "opt_inet.h"
@@ -453,7 +453,9 @@
if ((rt->rt_flags & RTF_HOST) == 0 && netmask != NULL &&
satocsin(netmask)->sin_addr.s_addr != 0xffffffff)
rt->rt_flags |= RTF_CLONING;
- if (rt->rt_flags & RTF_CLONING) {
+ if (rt->rt_flags & RTF_CLONING ||
+ ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !rt->rt_llinfo))
+ {
union {
struct sockaddr sa;
struct sockaddr_storage ss;
@@ -554,7 +556,9 @@
break;
case RTM_ADD:
gate = arp_setgate(rt, gate, info->rti_info[RTAX_NETMASK]);
- if (rt->rt_flags & RTF_CLONING) {
+ if (rt->rt_flags & RTF_CLONING ||
+ ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la))
+ {
/*
* Give this route an expiration time, even though
* it's a "permanent" route, so that routes cloned
@@ -592,7 +596,8 @@
}
#endif
}
- break;
+ if (rt->rt_flags & RTF_CLONING)
+ break;
}
/* Announce a new entry if requested. */
if (rt->rt_flags & RTF_ANNOUNCE) {
diff -r 18dbabe375b9 -r 634d6c2fa097 sys/netinet/in.c
--- a/sys/netinet/in.c Thu Feb 26 09:10:52 2015 +0000
+++ b/sys/netinet/in.c Thu Feb 26 09:54:46 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: in.c,v 1.149 2014/12/01 17:07:43 christos Exp $ */
+/* $NetBSD: in.c,v 1.150 2015/02/26 09:54:46 roy Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.149 2014/12/01 17:07:43 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.150 2015/02/26 09:54:46 roy Exp $");
#include "opt_inet.h"
#include "opt_inet_conf.h"
@@ -602,6 +602,40 @@
return error;
}
+/* Add ownaddr as loopback rtentry. */
+static void
+in_ifaddlocal(struct ifaddr *ifa)
+{
+
+ rt_ifa_addlocal(ifa);
+}
+
+/* Rempve loopback entry of ownaddr */
+static void
+in_ifremlocal(struct ifaddr *ifa)
+{
+ struct in_ifaddr *ia, *p;
+ struct ifaddr *alt_ifa = NULL;
+ int ia_count = 0;
+
+ ia = (struct in_ifaddr *)ifa;
+ /* Delete the entry if exactly one ifaddr matches the
+ * address, ifa->ifa_addr. */
+ TAILQ_FOREACH(p, &in_ifaddrhead, ia_list) {
+ if (!in_hosteq(p->ia_addr.sin_addr, ia->ia_addr.sin_addr))
+ continue;
+ if (p->ia_ifp != ia->ia_ifp)
+ alt_ifa = &p->ia_ifa;
+ if (++ia_count > 1 && alt_ifa != NULL)
+ break;
+ }
+
Home |
Main Index |
Thread Index |
Old Index