diff options
author | bz <bz@FreeBSD.org> | 2011-09-28 13:48:36 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2011-09-28 13:48:36 +0000 |
commit | a13ffdabccc99b57bdb73bc04662a95e6f93df8e (patch) | |
tree | 19deb44c2ae23c609f87f88a0cf3c966f9b800aa /sys/net/rtsock.c | |
parent | ae2bc06327902b65a0e544a5e109882b272b701d (diff) | |
download | FreeBSD-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.c | 71 |
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 |