summaryrefslogtreecommitdiffstats
path: root/sys/net/rtsock.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2011-09-28 13:48:36 +0000
committerbz <bz@FreeBSD.org>2011-09-28 13:48:36 +0000
commita13ffdabccc99b57bdb73bc04662a95e6f93df8e (patch)
tree19deb44c2ae23c609f87f88a0cf3c966f9b800aa /sys/net/rtsock.c
parentae2bc06327902b65a0e544a5e109882b272b701d (diff)
downloadFreeBSD-src-a13ffdabccc99b57bdb73bc04662a95e6f93df8e.zip
FreeBSD-src-a13ffdabccc99b57bdb73bc04662a95e6f93df8e.tar.gz
Pass the fibnum where we need filtering of the message on the
rtsock allowing routing daemons to filter routing updates on an rtsock per FIB. Adjust raw_input() and split it into wrapper and a new function taking an optional callback argument even though we only have one consumer [1] to keep the hackish flags local to rtsock.c. PR: kern/134931 Submitted by: multiple (see PR) Suggested by: rwatson [1] Reviewed by: rwatson MFC after: 3 days
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r--sys/net/rtsock.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 999557a..fdd017c 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -122,6 +122,13 @@ MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
static struct sockaddr route_src = { 2, PF_ROUTE, };
static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
+/*
+ * Used by rtsock/raw_input callback code to decide whether to filter the update
+ * notification to a socket bound to a particular FIB.
+ */
+#define RTS_FILTER_FIB M_PROTO8
+#define RTS_ALLFIBS -1
+
static struct {
int ip_count; /* attached w/ AF_INET */
int ip6_count; /* attached w/ AF_INET6 */
@@ -196,6 +203,31 @@ rts_init(void)
}
SYSINIT(rtsock, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, rts_init, 0);
+static int
+raw_input_rts_cb(struct mbuf *m, struct sockproto *proto, struct sockaddr *src,
+ struct rawcb *rp)
+{
+ int fibnum;
+
+ KASSERT(m != NULL, ("%s: m is NULL", __func__));
+ KASSERT(proto != NULL, ("%s: proto is NULL", __func__));
+ KASSERT(rp != NULL, ("%s: rp is NULL", __func__));
+
+ /* No filtering requested. */
+ if ((m->m_flags & RTS_FILTER_FIB) == 0)
+ return (0);
+
+ /* Check if it is a rts and the fib matches the one of the socket. */
+ fibnum = M_GETFIB(m);
+ if (proto->sp_family != PF_ROUTE ||
+ rp->rcb_socket == NULL ||
+ rp->rcb_socket->so_fibnum == fibnum)
+ return (0);
+
+ /* Filtering requested and no match, the socket shall be skipped. */
+ return (1);
+}
+
static void
rts_input(struct mbuf *m)
{
@@ -212,7 +244,7 @@ rts_input(struct mbuf *m)
} else
route_proto.sp_protocol = 0;
- raw_input(m, &route_proto, &route_src);
+ raw_input_ext(m, &route_proto, &route_src, raw_input_rts_cb);
}
/*
@@ -885,6 +917,8 @@ flush:
m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
}
if (m) {
+ M_SETFIB(m, so->so_fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
if (rp) {
/*
* XXX insure we don't get a copy by
@@ -1127,7 +1161,8 @@ again:
* destination.
*/
void
-rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
+rt_missmsg_fib(int type, struct rt_addrinfo *rtinfo, int flags, int error,
+ int fibnum)
{
struct rt_msghdr *rtm;
struct mbuf *m;
@@ -1138,6 +1173,14 @@ rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
m = rt_msg1(type, rtinfo);
if (m == NULL)
return;
+
+ if (fibnum != RTS_ALLFIBS) {
+ KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: fibnum out "
+ "of range 0 <= %d < %d", __func__, fibnum, rt_numfibs));
+ M_SETFIB(m, fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
+ }
+
rtm = mtod(m, struct rt_msghdr *);
rtm->rtm_flags = RTF_DONE | flags;
rtm->rtm_errno = error;
@@ -1145,6 +1188,13 @@ rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
rt_dispatch(m, sa);
}
+void
+rt_missmsg(int type, struct rt_addrinfo *rtinfo, int flags, int error)
+{
+
+ rt_missmsg_fib(type, rtinfo, flags, error, RTS_ALLFIBS);
+}
+
/*
* This routine is called to generate a message from the routing
* socket indicating that the status of a network interface has changed.
@@ -1179,7 +1229,8 @@ rt_ifmsg(struct ifnet *ifp)
* copies of it.
*/
void
-rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+rt_newaddrmsg_fib(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt,
+ int fibnum)
{
struct rt_addrinfo info;
struct sockaddr *sa = NULL;
@@ -1237,10 +1288,24 @@ rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
rtm->rtm_errno = error;
rtm->rtm_addrs = info.rti_addrs;
}
+ if (fibnum != RTS_ALLFIBS) {
+ KASSERT(fibnum >= 0 && fibnum < rt_numfibs, ("%s: "
+ "fibnum out of range 0 <= %d < %d", __func__,
+ fibnum, rt_numfibs));
+ M_SETFIB(m, fibnum);
+ m->m_flags |= RTS_FILTER_FIB;
+ }
rt_dispatch(m, sa);
}
}
+void
+rt_newaddrmsg(int cmd, struct ifaddr *ifa, int error, struct rtentry *rt)
+{
+
+ rt_newaddrmsg_fib(cmd, ifa, error, rt, RTS_ALLFIBS);
+}
+
/*
* This is the analogue to the rt_newaddrmsg which performs the same
* function but for multicast group memberhips. This is easier since
OpenPOWER on IntegriCloud