Skip to content

Commit

Permalink
pf: use M_IP_NEXTHOP and M_IP6_NEXTHOP
Browse files Browse the repository at this point in the history
Allow pf(4) to use the tagging as well while imposing consistency
inside the pfil hook.  The interface is stored using its index
for the time being as it is lockless and may only end up directing
packets to the wrong interface if it was changed.

Packets through pf_route() and pf_route6() now take the long way
to ip_output() and ip6_output(), respectively, with the interface
switch being enforced there.
  • Loading branch information
fichtner committed Oct 3, 2016
1 parent 6a71818 commit 03fab4b
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 138 deletions.
10 changes: 9 additions & 1 deletion sys/netinet/ip_fastfwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,16 +465,24 @@ ip_fastforward(struct mbuf *m)
RTFREE(ro.ro_rt);
return m;
}
RTFREE(ro.ro_rt);
/*
* Redo route lookup with new destination address
*/
if (fwd_tag) {
struct m_nexthop *nh = (struct m_nexthop *)(fwd_tag+1);
struct ifnet *nh_ifp = NULL;
dest.s_addr = nh->nexthop_dst.sin_addr.s_addr;
if (nh->nexthop_if_index) {
nh_ifp = ifnet_byindex(nh->nexthop_if_index);
}
m_tag_delete(m, fwd_tag);
m->m_flags &= ~M_IP_NEXTHOP;
if (nh_ifp != NULL) {
ifp = nh_ifp;
goto passout;
}
}
RTFREE(ro.ro_rt);
if ((dst = ip_findroute(&ro, dest, m)) == NULL)
return NULL; /* icmp unreach already sent */
ifp = ro.ro_rt->rt_ifp;
Expand Down
15 changes: 13 additions & 2 deletions sys/netinet/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
struct in_ifaddr *ia;
int isbroadcast;
uint16_t ip_len, ip_off;
struct route *_ro = ro;
struct route iproute;
struct rtentry *rte; /* cache for ro->ro_rt */
struct in_addr odst;
Expand Down Expand Up @@ -567,12 +568,22 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
if ((m->m_flags & M_IP_NEXTHOP) &&
(fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
struct m_nexthop *nh = (struct m_nexthop *)(fwd_tag+1);
struct ifnet *nh_ifp = NULL;
bcopy(&nh->nexthop_dst, dst, sizeof(struct sockaddr_in));
if (nh->nexthop_if_index) {
nh_ifp = ifnet_byindex(nh->nexthop_if_index);
}
m->m_flags |= M_SKIP_FIREWALL;
m->m_flags &= ~M_IP_NEXTHOP;
m_tag_delete(m, fwd_tag);
if (have_ia_ref)
ifa_free(&ia->ia_ifa);
if (nh_ifp != NULL) {
ifp = nh_ifp;
_ro = NULL;
gw = dst;
goto passout;
}
goto again;
}

Expand Down Expand Up @@ -637,7 +648,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
m_clrprotoflags(m);
IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL);
error = (*ifp->if_output)(ifp, m,
(const struct sockaddr *)gw, ro);
(const struct sockaddr *)gw, _ro);
goto done;
}

Expand Down Expand Up @@ -672,7 +683,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,

IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL);
error = (*ifp->if_output)(ifp, m,
(const struct sockaddr *)gw, ro);
(const struct sockaddr *)gw, _ro);
} else
m_freem(m);
}
Expand Down
1 change: 1 addition & 0 deletions sys/netinet6/in6.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ struct m_nexthop {
struct sockaddr_in __nexthop_dst;
struct sockaddr_in6 __nexthop_dst6;
} __nexthop_u;
u_short nexthop_if_index;
};

#define nexthop_dst __nexthop_u.__nexthop_dst
Expand Down
33 changes: 25 additions & 8 deletions sys/netinet6/ip6_forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ ip6_forward(struct mbuf *m, int srcrt)
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct sockaddr_in6 *dst = NULL;
struct rtentry *_rt = NULL;
struct ifnet *_ifp = NULL;
struct rtentry *rt = NULL;
struct route_in6 rin6;
int error, type = 0, code = 0;
Expand Down Expand Up @@ -543,18 +545,33 @@ ip6_forward(struct mbuf *m, int srcrt)
if ((m->m_flags & M_IP6_NEXTHOP) &&
(fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
struct m_nexthop *nh = (struct m_nexthop *)(fwd_tag+1);
struct ifnet *nh_ifp = NULL;
if (nh->nexthop_if_index) {
nh_ifp = ifnet_byindex(nh->nexthop_if_index);
}
dst = (struct sockaddr_in6 *)&rin6.ro_dst;
bcopy(&nh->nexthop_dst6, dst, sizeof(struct sockaddr_in6));
m->m_flags |= M_SKIP_FIREWALL;
m->m_flags &= ~M_IP6_NEXTHOP;
m_tag_delete(m, fwd_tag);
if (nh_ifp != NULL) {
_ifp = nh_ifp;
_rt = NULL;
goto pass;
}
goto again2;
}

pass:
/* Use lookup result when M_IP6_NEXTHOP was not set */
if (_ifp == NULL) {
_ifp = rt->rt_ifp;
_rt = rt;
}

/* See if the size was changed by the packet filter. */
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
if (m->m_pkthdr.len > IN6_LINKMTU(_ifp)) {
in6_ifstat_inc(_ifp, ifs6_in_toobig);
if (mcopy) {
u_long mtu;
#ifdef IPSEC
Expand All @@ -563,14 +580,14 @@ ip6_forward(struct mbuf *m, int srcrt)
size_t ipsechdrsiz;
#endif /* IPSEC */

mtu = IN6_LINKMTU(rt->rt_ifp);
mtu = IN6_LINKMTU(_ifp);
#ifdef IPSEC
/*
* When we do IPsec tunnel ingress, we need to play
* with the link value (decrement IPsec header size
* from mtu value). The code is much simpler than v4
* case, as we have the outgoing interface for
* encapsulated packet as "rt->rt_ifp".
* encapsulated packet as "_ifp".
*/
sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
IP_FORWARDING, &ipsecerror);
Expand All @@ -593,13 +610,13 @@ ip6_forward(struct mbuf *m, int srcrt)
goto bad;
}

error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
error = nd6_output(_ifp, origifp, m, dst, _rt);
if (error) {
in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
in6_ifstat_inc(_ifp, ifs6_out_discard);
IP6STAT_INC(ip6s_cantforward);
} else {
IP6STAT_INC(ip6s_forward);
in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward);
in6_ifstat_inc(_ifp, ifs6_out_forward);
if (type)
IP6STAT_INC(ip6s_redirectsent);
else {
Expand All @@ -613,7 +630,7 @@ ip6_forward(struct mbuf *m, int srcrt)
switch (error) {
case 0:
if (type == ND_REDIRECT) {
icmp6_redirect_output(mcopy, rt);
icmp6_redirect_output(mcopy, _rt);
goto out;
}
goto freecopy;
Expand Down
8 changes: 8 additions & 0 deletions sys/netinet6/ip6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,11 +817,19 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
if ((m->m_flags & M_IP6_NEXTHOP) &&
(fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
struct m_nexthop *nh = (struct m_nexthop *)(fwd_tag+1);
struct ifnet *nh_ifp = NULL;
if (nh->nexthop_if_index) {
nh_ifp = ifnet_byindex(nh->nexthop_if_index);
}
dst = (struct sockaddr_in6 *)&ro->ro_dst;
bcopy(&nh->nexthop_dst6, &dst_sa, sizeof(struct sockaddr_in6));
m->m_flags |= M_SKIP_FIREWALL;
m->m_flags &= ~M_IP6_NEXTHOP;
m_tag_delete(m, fwd_tag);
if (nh_ifp != NULL) {
ifp = nh_ifp;
goto passout;
}
goto again;
}

Expand Down
Loading

0 comments on commit 03fab4b

Please sign in to comment.