Author: hrs
Date: Thu Oct  2 00:25:57 2014
New Revision: 272391
URL: https://svnweb.freebsd.org/changeset/base/272391

Log:
  Add an additional routing table lookup when m->m_pkthdr.fibnum is changed
  at a PFIL hook in ip{,6}_output().  IPFW setfib rule did not perform
  a routing table lookup when the destination address was not changed.
  
  CR:   D805

Modified:
  head/sys/netinet/ip_output.c
  head/sys/netinet6/ip6_output.c

Modified: head/sys/netinet/ip_output.c
==============================================================================
--- head/sys/netinet/ip_output.c        Thu Oct  2 00:19:24 2014        
(r272390)
+++ head/sys/netinet/ip_output.c        Thu Oct  2 00:25:57 2014        
(r272391)
@@ -136,7 +136,9 @@ ip_output(struct mbuf *m, struct mbuf *o
        struct rtentry *rte;    /* cache for ro->ro_rt */
        struct in_addr odst;
        struct m_tag *fwd_tag = NULL;
+       uint32_t fibnum;
        int have_ia_ref;
+       int needfiblookup;
 #ifdef IPSEC
        int no_route_but_check_spd = 0;
 #endif
@@ -202,6 +204,7 @@ ip_output(struct mbuf *m, struct mbuf *o
         * therefore we need restore gw if we're redoing lookup.
         */
        gw = dst = (struct sockaddr_in *)&ro->ro_dst;
+       fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
 again:
        ia = NULL;
        have_ia_ref = 0;
@@ -283,10 +286,9 @@ again:
 #ifdef RADIX_MPATH
                        rtalloc_mpath_fib(ro,
                            ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr),
-                           inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m));
+                           fibnum);
 #else
-                       in_rtalloc_ign(ro, 0,
-                           inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m));
+                       in_rtalloc_ign(ro, 0, fibnum);
 #endif
                        rte = ro->ro_rt;
                }
@@ -504,6 +506,7 @@ sendit:
                goto done;
 
        ip = mtod(m, struct ip *);
+       needfiblookup = 0;
 
        /* See if destination IP address was changed by packet filter. */
        if (odst.s_addr != ip->ip_dst.s_addr) {
@@ -529,9 +532,18 @@ sendit:
                } else {
                        if (have_ia_ref)
                                ifa_free(&ia->ia_ifa);
-                       goto again;     /* Redo the routing table lookup. */
+                       needfiblookup = 1; /* Redo the routing table lookup. */
                }
        }
+       /* See if fib was changed by packet filter. */
+       if (fibnum != M_GETFIB(m)) {
+               m->m_flags |= M_SKIP_FIREWALL;
+               fibnum = M_GETFIB(m);
+               RO_RTFREE(ro);
+               needfiblookup = 1;
+       }
+       if (needfiblookup)
+               goto again;
 
        /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
        if (m->m_flags & M_FASTFWD_OURS) {

Modified: head/sys/netinet6/ip6_output.c
==============================================================================
--- head/sys/netinet6/ip6_output.c      Thu Oct  2 00:19:24 2014        
(r272390)
+++ head/sys/netinet6/ip6_output.c      Thu Oct  2 00:25:57 2014        
(r272391)
@@ -255,6 +255,8 @@ ip6_output(struct mbuf *m0, struct ip6_p
        struct route_in6 *ro_pmtu = NULL;
        int hdrsplit = 0;
        int sw_csum, tso;
+       int needfiblookup;
+       uint32_t fibnum;
        struct m_tag *fwd_tag = NULL;
 
        ip6 = mtod(m, struct ip6_hdr *);
@@ -448,6 +450,7 @@ ip6_output(struct mbuf *m0, struct ip6_p
        if (ro->ro_rt == NULL)
                (void )flowtable_lookup(AF_INET6, m, (struct route *)ro);
 #endif
+       fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
 again:
        /*
         * if specified, try to fill in the traffic class field.
@@ -489,7 +492,7 @@ again:
                        dst_sa.sin6_addr = ip6->ip6_dst;
                }
                error = in6_selectroute_fib(&dst_sa, opt, im6o, ro, &ifp,
-                   &rt, inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m));
+                   &rt, fibnum);
                if (error != 0) {
                        if (ifp != NULL)
                                in6_ifstat_inc(ifp, ifs6_out_discard);
@@ -649,7 +652,7 @@ again:
 
        /* Determine path MTU. */
        if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
-           &alwaysfrag, inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m))) != 0)
+           &alwaysfrag, fibnum)) != 0)
                goto bad;
 
        /*
@@ -727,6 +730,7 @@ again:
                goto done;
        ip6 = mtod(m, struct ip6_hdr *);
 
+       needfiblookup = 0;
        /* See if destination IP address was changed by packet filter. */
        if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) {
                m->m_flags |= M_SKIP_FIREWALL;
@@ -747,8 +751,17 @@ again:
                        error = netisr_queue(NETISR_IPV6, m);
                        goto done;
                } else
-                       goto again;     /* Redo the routing table lookup. */
+                       needfiblookup = 1; /* Redo the routing table lookup. */
        }
+       /* See if fib was changed by packet filter. */
+       if (fibnum != M_GETFIB(m)) {
+               m->m_flags |= M_SKIP_FIREWALL;
+               fibnum = M_GETFIB(m);
+               RO_RTFREE(ro);
+               needfiblookup = 1;
+       }
+       if (needfiblookup)
+               goto again;
 
        /* See if local, if yes, send it to netisr. */
        if (m->m_flags & M_FASTFWD_OURS) {
_______________________________________________
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