summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/net/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/net/route.c')
-rw-r--r--freebsd/sys/net/route.c167
1 files changed, 156 insertions, 11 deletions
diff --git a/freebsd/sys/net/route.c b/freebsd/sys/net/route.c
index fdd8a12c..b444b740 100644
--- a/freebsd/sys/net/route.c
+++ b/freebsd/sys/net/route.c
@@ -39,6 +39,7 @@
#include <rtems/bsd/local/opt_inet.h>
#include <rtems/bsd/local/opt_inet6.h>
#include <rtems/bsd/local/opt_route.h>
+#include <rtems/bsd/local/opt_sctp.h>
#include <rtems/bsd/local/opt_mrouting.h>
#include <rtems/bsd/local/opt_mpath.h>
@@ -92,6 +93,14 @@
#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, "");
/*
@@ -131,7 +140,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 *'.
@@ -974,6 +984,57 @@ bad:
return (error);
}
+#if 0
+int p_sockaddr(char *buf, int buflen, struct sockaddr *s);
+int rt_print(char *buf, int buflen, struct rtentry *rt);
+
+int
+p_sockaddr(char *buf, int buflen, struct sockaddr *s)
+{
+ void *paddr = NULL;
+
+ switch (s->sa_family) {
+ case AF_INET:
+ paddr = &((struct sockaddr_in *)s)->sin_addr;
+ break;
+ case AF_INET6:
+ paddr = &((struct sockaddr_in6 *)s)->sin6_addr;
+ break;
+ }
+
+ if (paddr == NULL)
+ return (0);
+
+ if (inet_ntop(s->sa_family, paddr, buf, buflen) == NULL)
+ return (0);
+
+ return (strlen(buf));
+}
+
+int
+rt_print(char *buf, int buflen, struct rtentry *rt)
+{
+ struct sockaddr *addr, *mask;
+ int i = 0;
+
+ addr = rt_key(rt);
+ mask = rt_mask(rt);
+
+ i = p_sockaddr(buf, buflen, addr);
+ if (!(rt->rt_flags & RTF_HOST)) {
+ buf[i++] = '/';
+ i += p_sockaddr(buf + i, buflen - i, mask);
+ }
+
+ if (rt->rt_flags & RTF_GATEWAY) {
+ buf[i++] = '>';
+ i += p_sockaddr(buf + i, buflen - i, rt->rt_gateway);
+ }
+
+ return (i);
+}
+#endif
+
#ifdef RADIX_MPATH
static int
rn_mpath_update(int req, struct rt_addrinfo *info,
@@ -987,10 +1048,11 @@ rn_mpath_update(int req, struct rt_addrinfo *info,
register struct radix_node *rn;
int error = 0;
- rn = rnh->rnh_matchaddr(dst, rnh);
+ rn = rnh->rnh_lookup(dst, netmask, rnh);
if (rn == NULL)
return (ESRCH);
rto = rt = RNTORT(rn);
+
rt = rt_mpath_matchgate(rt, gateway);
if (rt == NULL)
return (ESRCH);
@@ -1495,7 +1557,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
fibnum = RT_DEFAULT_FIB;
break;
}
- if (fibnum == -1) {
+ if (fibnum == RT_ALL_FIBS) {
if (rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD) {
#ifndef __rtems__
startfib = endfib = curthread->td_proc->p_fibnum;
@@ -1548,10 +1610,10 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
/* this table doesn't exist but others might */
continue;
RADIX_NODE_HEAD_RLOCK(rnh);
+ rn = rnh->rnh_lookup(dst, netmask, rnh);
#ifdef RADIX_MPATH
if (rn_mpath_capable(rnh)) {
- rn = rnh->rnh_matchaddr(dst, rnh);
if (rn == NULL)
error = ESRCH;
else {
@@ -1565,17 +1627,14 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
*/
rt = rt_mpath_matchgate(rt,
ifa->ifa_addr);
- if (!rt)
+ if (rt == NULL)
error = ESRCH;
}
}
- else
#endif
- rn = rnh->rnh_lookup(dst, netmask, rnh);
error = (rn == NULL ||
(rn->rn_flags & RNF_ROOT) ||
- RNTORT(rn)->rt_ifa != ifa ||
- !sa_equal((struct sockaddr *)rn->rn_key, dst));
+ RNTORT(rn)->rt_ifa != ifa);
RADIX_NODE_HEAD_RUNLOCK(rnh);
if (error) {
/* this is only an error if bad on ALL tables */
@@ -1706,7 +1765,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
int
rtinit_fib(struct ifaddr *ifa, int cmd, int flags)
{
- return (rtinit1(ifa, cmd, flags, -1));
+ return (rtinit1(ifa, cmd, flags, RT_ALL_FIBS));
}
#endif
@@ -1730,8 +1789,94 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
case AF_INET6:
case AF_INET:
/* We do support multiple FIBs. */
- fib = -1;
+ fib = RT_ALL_FIBS;
break;
}
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));
+
+#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
+ 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 (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);
+ }
+}
+