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
This commit is contained in:
parent
e3feec94eb
commit
528737fdfe
@ -70,9 +70,14 @@ pr_init_t raw_init;
|
||||
* Library routines for raw socket usrreq functions; will always be wrapped
|
||||
* so that protocol-specific functions can be handled.
|
||||
*/
|
||||
typedef int (*raw_input_cb_fn)(struct mbuf *, struct sockproto *,
|
||||
struct sockaddr *, struct rawcb *);
|
||||
|
||||
int raw_attach(struct socket *, int);
|
||||
void raw_detach(struct rawcb *);
|
||||
void raw_input(struct mbuf *, struct sockproto *, struct sockaddr *);
|
||||
void raw_input_ext(struct mbuf *, struct sockproto *, struct sockaddr *,
|
||||
raw_input_cb_fn);
|
||||
|
||||
/*
|
||||
* Generic pr_usrreqs entries for raw socket protocols, usually wrapped so
|
||||
|
@ -70,6 +70,14 @@ raw_init(void)
|
||||
*/
|
||||
void
|
||||
raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
|
||||
{
|
||||
|
||||
return (raw_input_ext(m0, proto, src, NULL));
|
||||
}
|
||||
|
||||
void
|
||||
raw_input_ext(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src,
|
||||
raw_input_cb_fn cb)
|
||||
{
|
||||
struct rawcb *rp;
|
||||
struct mbuf *m = m0;
|
||||
@ -83,6 +91,8 @@ raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
|
||||
if (rp->rcb_proto.sp_protocol &&
|
||||
rp->rcb_proto.sp_protocol != proto->sp_protocol)
|
||||
continue;
|
||||
if (cb != NULL && (*cb)(m, proto, src, rp) != 0)
|
||||
continue;
|
||||
if (last) {
|
||||
struct mbuf *n;
|
||||
n = m_copy(m, 0, (int)M_COPYALL);
|
||||
|
@ -384,7 +384,7 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
|
||||
*/
|
||||
bzero(&info, sizeof(info));
|
||||
info.rti_info[RTAX_DST] = dst;
|
||||
rt_missmsg(msgtype, &info, 0, err);
|
||||
rt_missmsg_fib(msgtype, &info, 0, err, fibnum);
|
||||
}
|
||||
done:
|
||||
if (newrt)
|
||||
@ -609,7 +609,7 @@ rtredirect_fib(struct sockaddr *dst,
|
||||
info.rti_info[RTAX_GATEWAY] = gateway;
|
||||
info.rti_info[RTAX_NETMASK] = netmask;
|
||||
info.rti_info[RTAX_AUTHOR] = src;
|
||||
rt_missmsg(RTM_REDIRECT, &info, flags, error);
|
||||
rt_missmsg_fib(RTM_REDIRECT, &info, flags, error, fibnum);
|
||||
if (ifa != NULL)
|
||||
ifa_free(ifa);
|
||||
}
|
||||
@ -1522,7 +1522,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
|
||||
}
|
||||
RT_ADDREF(rt);
|
||||
RT_UNLOCK(rt);
|
||||
rt_newaddrmsg(cmd, ifa, error, rt);
|
||||
rt_newaddrmsg_fib(cmd, ifa, error, rt, fibnum);
|
||||
RT_LOCK(rt);
|
||||
RT_REMREF(rt);
|
||||
if (cmd == RTM_DELETE) {
|
||||
|
@ -369,7 +369,9 @@ void rt_ieee80211msg(struct ifnet *, int, void *, size_t);
|
||||
void rt_ifannouncemsg(struct ifnet *, int);
|
||||
void rt_ifmsg(struct ifnet *);
|
||||
void rt_missmsg(int, struct rt_addrinfo *, int, int);
|
||||
void rt_missmsg_fib(int, struct rt_addrinfo *, int, int, int);
|
||||
void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
|
||||
void rt_newaddrmsg_fib(int, struct ifaddr *, int, struct rtentry *, int);
|
||||
void rt_newmaddrmsg(int, struct ifmultiaddr *);
|
||||
int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
|
||||
void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *);
|
||||
|
@ -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 @@ route_output(struct mbuf *m, struct socket *so)
|
||||
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 @@ rt_msg2(int type, struct rt_addrinfo *rtinfo, caddr_t cp, struct walkarg *w)
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user