summaryrefslogtreecommitdiffstats
path: root/sys/net/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/route.c')
-rw-r--r--sys/net/route.c97
1 files changed, 96 insertions, 1 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index 1db844d..47d8978 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -37,6 +37,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_route.h"
+#include "opt_sctp.h"
#include "opt_mrouting.h"
#include "opt_mpath.h"
@@ -85,6 +86,13 @@
#define RT_NUMFIBS 1
#endif
+#if defined(INET) || defined(INET6)
+#ifdef SCTP
+extern void sctp_addr_change(struct ifaddr *ifa, int cmd);
+#endif /* SCTP */
+#endif
+
+
/* This is read-only.. */
u_int rt_numfibs = RT_NUMFIBS;
SYSCTL_UINT(_net, OID_AUTO, fibs, CTLFLAG_RD, &rt_numfibs, 0, "");
@@ -117,7 +125,8 @@ VNET_DEFINE(int, rttrash); /* routes not in table but not freed */
/* compare two sockaddr structures */
-#define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
+#define sa_equal(a1, a2) (((a1)->sa_len == (a2)->sa_len) && \
+ (bcmp((a1), (a2), (a1)->sa_len) == 0))
/*
* Convert a 'struct radix_node *' to a 'struct rtentry *'.
@@ -1756,3 +1765,89 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
}
return (rtinit1(ifa, cmd, flags, fib));
}
+
+/*
+ * Announce interface address arrival/withdraw
+ * Returns 0 on success.
+ */
+int
+rt_addrmsg(int cmd, struct ifaddr *ifa, int fibnum)
+{
+
+ KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE,
+ ("unexpected cmd %d", cmd));
+
+ KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs),
+ ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs));
+
+ return (rtsock_addrmsg(cmd, ifa, fibnum));
+}
+
+/*
+ * Announce route addition/removal.
+ * Users of this function MUST validate input data BEFORE calling.
+ * However we have to be able to handle invalid data:
+ * if some userland app sends us "invalid" route message (invalid mask,
+ * no dst, wrong address families, etc...) we need to pass it back
+ * to app (and any other rtsock consumers) with rtm_errno field set to
+ * non-zero value.
+ * Returns 0 on success.
+ */
+int
+rt_routemsg(int cmd, struct ifnet *ifp, int error, struct rtentry *rt,
+ int fibnum)
+{
+
+ KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE,
+ ("unexpected cmd %d", cmd));
+
+ KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs),
+ ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs));
+
+ KASSERT(rt_key(rt) != NULL, (":%s: rt_key must be supplied", __func__));
+
+ return (rtsock_routemsg(cmd, ifp, error, rt, fibnum));
+}
+
+void
+rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+{
+
+ rt_newaddrmsg_fib(cmd, ifa, error, rt, RT_ALL_FIBS);
+}
+
+/*
+ * This is called to generate messages from the routing socket
+ * indicating a network interface has had addresses associated with it.
+ */
+void
+rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt,
+ int fibnum)
+{
+
+ KASSERT(cmd == RTM_ADD || cmd == RTM_DELETE,
+ ("unexpected cmd %u", cmd));
+ KASSERT(fibnum == RT_ALL_FIBS || (fibnum >= 0 && fibnum < rt_numfibs),
+ ("%s: fib out of range 0 <=%d<%d", __func__, fibnum, rt_numfibs));
+
+#if defined(INET) || defined(INET6)
+#ifdef SCTP
+ /*
+ * notify the SCTP stack
+ * this will only get called when an address is added/deleted
+ * XXX pass the ifaddr struct instead if ifa->ifa_addr...
+ */
+ sctp_addr_change(ifa, cmd);
+#endif /* SCTP */
+#endif
+ if (cmd == RTM_ADD) {
+ rt_addrmsg(cmd, ifa, fibnum);
+ if (rt != NULL)
+ rt_routemsg(cmd, ifa->ifa_ifp, error, rt, fibnum);
+ } else {
+ if (rt != NULL)
+ rt_routemsg(cmd, ifa->ifa_ifp, error, rt, fibnum);
+ rt_addrmsg(cmd, ifa, fibnum);
+ }
+}
+
OpenPOWER on IntegriCloud