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
This commit is contained in:
Hiroki Sato 2014-10-02 00:25:57 +00:00
parent 394c813d06
commit 9c57a5b630
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=272391
2 changed files with 32 additions and 7 deletions

View File

@ -136,7 +136,9 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
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 *opt, struct route *ro, int flags,
* 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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
#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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
} 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) {

View File

@ -255,6 +255,8 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
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_pktopts *opt,
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 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
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 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
/* 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 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
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 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
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) {