Merge in a stable fix from OpenBSD:
MFC: Fix by dhartmei@ change pf_route() loop detection: introduce a counter (number of times a packet is routed already) in the mbuf tag, allow at most four times. Fixes some legitimate cases broken by the previous change. Reviewed by: dhartmei
This commit is contained in:
parent
ffd446110e
commit
0ad9506fab
@ -1,5 +1,5 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $OpenBSD: pf.c,v 1.433.2.1 2004/04/30 21:46:33 brad Exp $ */
|
||||
/* $OpenBSD: pf.c,v 1.433.2.2 2004/07/17 03:22:34 brad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Daniel Hartmeier
|
||||
@ -5119,12 +5119,12 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
struct pf_state *s)
|
||||
{
|
||||
struct mbuf *m0, *m1;
|
||||
struct m_tag *mtag;
|
||||
struct route iproute;
|
||||
struct route *ro = NULL; /* XXX: was uninitialized */
|
||||
struct sockaddr_in *dst;
|
||||
struct ip *ip;
|
||||
struct ifnet *ifp = NULL;
|
||||
struct m_tag *mtag;
|
||||
struct pf_addr naddr;
|
||||
struct pf_src_node *sn = NULL;
|
||||
int error = 0;
|
||||
@ -5136,22 +5136,34 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
|
||||
panic("pf_route: invalid parameters");
|
||||
|
||||
if (r->rt == PF_DUPTO) {
|
||||
m0 = *m;
|
||||
mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
|
||||
if (mtag == NULL) {
|
||||
mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
|
||||
if (mtag == NULL)
|
||||
goto bad;
|
||||
m_tag_prepend(m0, mtag);
|
||||
if ((mtag = m_tag_find(*m, PACKET_TAG_PF_ROUTED, NULL)) == NULL) {
|
||||
if ((mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 1, M_NOWAIT)) ==
|
||||
NULL) {
|
||||
m0 = *m;
|
||||
*m = NULL;
|
||||
goto bad;
|
||||
}
|
||||
*(char *)(mtag + 1) = 1;
|
||||
m_tag_prepend(*m, mtag);
|
||||
} else {
|
||||
if (*(char *)(mtag + 1) > 3) {
|
||||
m0 = *m;
|
||||
*m = NULL;
|
||||
goto bad;
|
||||
}
|
||||
(*(char *)(mtag + 1))++;
|
||||
}
|
||||
|
||||
if (r->rt == PF_DUPTO) {
|
||||
#ifdef __FreeBSD__
|
||||
m0 = m_dup(*m, M_DONTWAIT);
|
||||
if ((m0 = m_dup(*m, M_DONTWAIT)) == NULL)
|
||||
#else
|
||||
m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
|
||||
if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
|
||||
#endif
|
||||
if (m0 == NULL)
|
||||
return;
|
||||
if ((mtag = m_tag_copy(mtag)) == NULL)
|
||||
goto bad;
|
||||
m_tag_prepend(m0, mtag);
|
||||
} else {
|
||||
if ((r->rt == PF_REPLYTO) == (r->direction == dir))
|
||||
return;
|
||||
@ -5198,17 +5210,9 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifp == NULL)
|
||||
goto bad;
|
||||
|
||||
if (m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL) != NULL)
|
||||
goto bad;
|
||||
mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
|
||||
if (mtag == NULL)
|
||||
goto bad;
|
||||
m_tag_prepend(m0, mtag);
|
||||
|
||||
if (oifp != ifp) {
|
||||
#ifdef __FreeBSD__
|
||||
PF_UNLOCK();
|
||||
@ -5415,22 +5419,34 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
(dir != PF_IN && dir != PF_OUT) || oifp == NULL)
|
||||
panic("pf_route6: invalid parameters");
|
||||
|
||||
if (r->rt == PF_DUPTO) {
|
||||
m0 = *m;
|
||||
mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
|
||||
if (mtag == NULL) {
|
||||
mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
|
||||
if (mtag == NULL)
|
||||
goto bad;
|
||||
m_tag_prepend(m0, mtag);
|
||||
if ((mtag = m_tag_find(*m, PACKET_TAG_PF_ROUTED, NULL)) == NULL) {
|
||||
if ((mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 1, M_NOWAIT)) ==
|
||||
NULL) {
|
||||
m0 = *m;
|
||||
*m = NULL;
|
||||
goto bad;
|
||||
}
|
||||
*(char *)(mtag + 1) = 1;
|
||||
m_tag_prepend(*m, mtag);
|
||||
} else {
|
||||
if (*(char *)(mtag + 1) > 3) {
|
||||
m0 = *m;
|
||||
*m = NULL;
|
||||
goto bad;
|
||||
}
|
||||
(*(char *)(mtag + 1))++;
|
||||
}
|
||||
|
||||
if (r->rt == PF_DUPTO) {
|
||||
#ifdef __FreeBSD__
|
||||
m0 = m_dup(*m, M_DONTWAIT);
|
||||
if ((m0 = m_dup(*m, M_DONTWAIT)) == NULL)
|
||||
#else
|
||||
m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT);
|
||||
if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
|
||||
#endif
|
||||
if (m0 == NULL)
|
||||
return;
|
||||
if ((mtag = m_tag_copy(mtag)) == NULL)
|
||||
goto bad;
|
||||
m_tag_prepend(m0, mtag);
|
||||
} else {
|
||||
if ((r->rt == PF_REPLYTO) == (r->direction == dir))
|
||||
return;
|
||||
@ -5480,34 +5496,29 @@ pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
|
||||
&s->rt_addr, AF_INET6);
|
||||
ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
|
||||
}
|
||||
|
||||
if (ifp == NULL)
|
||||
goto bad;
|
||||
|
||||
if (oifp != ifp) {
|
||||
mtag = m_tag_find(m0, PACKET_TAG_PF_ROUTED, NULL);
|
||||
if (mtag == NULL) {
|
||||
mtag = m_tag_get(PACKET_TAG_PF_ROUTED, 0, M_NOWAIT);
|
||||
if (mtag == NULL)
|
||||
goto bad;
|
||||
m_tag_prepend(m0, mtag);
|
||||
#ifdef __FreeBSD__
|
||||
PF_UNLOCK();
|
||||
if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) {
|
||||
PF_LOCK();
|
||||
goto bad;
|
||||
} else if (m0 == NULL) {
|
||||
PF_LOCK();
|
||||
goto done;
|
||||
}
|
||||
PF_UNLOCK();
|
||||
if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS) {
|
||||
PF_LOCK();
|
||||
#else
|
||||
if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS)
|
||||
goto bad;
|
||||
else if (m0 == NULL)
|
||||
goto done;
|
||||
#endif
|
||||
goto bad;
|
||||
} else if (m0 == NULL) {
|
||||
PF_LOCK();
|
||||
goto done;
|
||||
}
|
||||
PF_LOCK();
|
||||
#else
|
||||
if (pf_test6(PF_OUT, ifp, &m0) != PF_PASS)
|
||||
goto bad;
|
||||
else if (m0 == NULL)
|
||||
goto done;
|
||||
#endif
|
||||
if (m0->m_len < sizeof(struct ip6_hdr))
|
||||
panic("pf_route6: m0->m_len < sizeof(struct ip6_hdr)");
|
||||
ip6 = mtod(m0, struct ip6_hdr *);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user