Author: bz
Date: Wed Sep 28 13:48:36 2011
New Revision: 225837
URL: http://svn.freebsd.org/changeset/base/225837

Log:
  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

Modified:
  head/sys/net/raw_cb.h
  head/sys/net/raw_usrreq.c
  head/sys/net/route.c
  head/sys/net/route.h
  head/sys/net/rtsock.c

Modified: head/sys/net/raw_cb.h
==============================================================================
--- head/sys/net/raw_cb.h       Wed Sep 28 13:27:31 2011        (r225836)
+++ head/sys/net/raw_cb.h       Wed Sep 28 13:48:36 2011        (r225837)
@@ -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

Modified: head/sys/net/raw_usrreq.c
==============================================================================
--- head/sys/net/raw_usrreq.c   Wed Sep 28 13:27:31 2011        (r225836)
+++ head/sys/net/raw_usrreq.c   Wed Sep 28 13:48:36 2011        (r225837)
@@ -71,6 +71,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;
        struct socket *last;
@@ -83,6 +91,8 @@ raw_input(struct mbuf *m0, struct sockpr
                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);

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c        Wed Sep 28 13:27:31 2011        (r225836)
+++ head/sys/net/route.c        Wed Sep 28 13:48:36 2011        (r225837)
@@ -384,7 +384,7 @@ miss:
                 */
                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 @@ out:
        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
                        }
                        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) {

Modified: head/sys/net/route.h
==============================================================================
--- head/sys/net/route.h        Wed Sep 28 13:27:31 2011        (r225836)
+++ head/sys/net/route.h        Wed Sep 28 13:48:36 2011        (r225837)
@@ -369,7 +369,9 @@ void         rt_ieee80211msg(struct ifnet *, in
 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 *);

Modified: head/sys/net/rtsock.c
==============================================================================
--- head/sys/net/rtsock.c       Wed Sep 28 13:27:31 2011        (r225836)
+++ head/sys/net/rtsock.c       Wed Sep 28 13:48:36 2011        (r225837)
@@ -122,6 +122,13 @@ MALLOC_DEFINE(M_RTABLE, "routetbl", "rou
 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 
        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 
        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 *if
                        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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to