diff options
author | mlaier <mlaier@FreeBSD.org> | 2004-07-17 17:15:15 +0000 |
---|---|---|
committer | mlaier <mlaier@FreeBSD.org> | 2004-07-17 17:15:15 +0000 |
commit | 8206972537d22846ebf90ee5084d300d35430f98 (patch) | |
tree | 1ad5590e7aae81c00e9487eb2ba2673d04941255 /sys/contrib | |
parent | 6bd2f3e42ba6a2ebbaf591311cbea3fb98bf9f25 (diff) | |
download | FreeBSD-src-8206972537d22846ebf90ee5084d300d35430f98.zip FreeBSD-src-8206972537d22846ebf90ee5084d300d35430f98.tar.gz |
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
Diffstat (limited to 'sys/contrib')
-rw-r--r-- | sys/contrib/pf/net/pf.c | 115 |
1 files changed, 63 insertions, 52 deletions
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c index 085f5cb..5df3ba6 100644 --- a/sys/contrib/pf/net/pf.c +++ b/sys/contrib/pf/net/pf.c @@ -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(); + 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; + 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 *); } /* |