Page MenuHomeFreeBSD

D47257.diff
No OneTemporary

D47257.diff

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -2491,12 +2491,12 @@
struct mbuf *pf_build_tcp(const struct pf_krule *, sa_family_t,
const struct pf_addr *, const struct pf_addr *,
u_int16_t, u_int16_t, u_int32_t, u_int32_t,
- u_int8_t, u_int16_t, u_int16_t, u_int8_t, bool,
+ u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
u_int16_t, u_int16_t, int);
void pf_send_tcp(const struct pf_krule *, sa_family_t,
const struct pf_addr *, const struct pf_addr *,
u_int16_t, u_int16_t, u_int32_t, u_int32_t,
- u_int8_t, u_int16_t, u_int16_t, u_int8_t, bool,
+ u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
u_int16_t, u_int16_t, int);
void pf_syncookies_init(void);
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -2207,6 +2207,9 @@
#ifdef INET
case PFSE_IP: {
if (pf_isforlocal(pfse->pfse_m, AF_INET)) {
+ KASSERT(pfse->pfse_m->m_pkthdr.rcvif == V_loif,
+ ("%s: rcvif != loif", __func__));
+
pfse->pfse_m->m_flags |= M_SKIP_FIREWALL;
pfse->pfse_m->m_pkthdr.csum_flags |=
CSUM_IP_VALID | CSUM_IP_CHECKED;
@@ -2225,7 +2228,11 @@
#ifdef INET6
case PFSE_IP6:
if (pf_isforlocal(pfse->pfse_m, AF_INET6)) {
- pfse->pfse_m->m_flags |= M_SKIP_FIREWALL;
+ KASSERT(pfse->pfse_m->m_pkthdr.rcvif == V_loif,
+ ("%s: rcvif != loif", __func__));
+
+ pfse->pfse_m->m_flags |= M_SKIP_FIREWALL |
+ M_LOOP;
ip6_input(pfse->pfse_m);
} else {
ip6_output(pfse->pfse_m, NULL, NULL, 0, NULL,
@@ -2574,7 +2581,8 @@
s->key[PF_SK_WIRE]->port[1],
s->key[PF_SK_WIRE]->port[0],
s->src.seqhi, s->src.seqlo + 1,
- TH_RST|TH_ACK, 0, 0, 0, true, s->tag, 0, s->act.rtableid);
+ TH_RST|TH_ACK, 0, 0, 0, M_SKIP_FIREWALL, s->tag, 0,
+ s->act.rtableid);
}
LIST_REMOVE(s, entry);
@@ -3334,7 +3342,7 @@
const struct pf_addr *saddr, const struct pf_addr *daddr,
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
u_int8_t tcp_flags, u_int16_t win, u_int16_t mss, u_int8_t ttl,
- bool skip_firewall, u_int16_t mtag_tag, u_int16_t mtag_flags, int rtableid)
+ int mbuf_flags, u_int16_t mtag_tag, u_int16_t mtag_flags, int rtableid)
{
struct mbuf *m;
int len, tlen;
@@ -3380,8 +3388,7 @@
m_freem(m);
return (NULL);
}
- if (skip_firewall)
- m->m_flags |= M_SKIP_FIREWALL;
+ m->m_flags |= mbuf_flags;
pf_mtag->tag = mtag_tag;
pf_mtag->flags = mtag_flags;
@@ -3598,13 +3605,13 @@
const struct pf_addr *saddr, const struct pf_addr *daddr,
u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
u_int8_t tcp_flags, u_int16_t win, u_int16_t mss, u_int8_t ttl,
- bool skip_firewall, u_int16_t mtag_tag, u_int16_t mtag_flags, int rtableid)
+ int mbuf_flags, u_int16_t mtag_tag, u_int16_t mtag_flags, int rtableid)
{
struct pf_send_entry *pfse;
struct mbuf *m;
m = pf_build_tcp(r, af, saddr, daddr, sport, dport, seq, ack, tcp_flags,
- win, mss, ttl, skip_firewall, mtag_tag, mtag_flags, rtableid);
+ win, mss, ttl, mbuf_flags, mtag_tag, mtag_flags, rtableid);
if (m == NULL)
return;
@@ -3672,7 +3679,7 @@
pf_send_tcp(r, pd->af, pd->dst,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
- r->return_ttl, true, 0, 0, rtableid);
+ r->return_ttl, M_SKIP_FIREWALL, 0, 0, rtableid);
}
} else if (pd->proto == IPPROTO_SCTP &&
(r->rule_flag & PFRULE_RETURN)) {
@@ -5537,7 +5544,7 @@
s->src.mss = mss;
pf_send_tcp(r, pd->af, pd->dst, pd->src, th->th_dport,
th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
- TH_SYN|TH_ACK, 0, s->src.mss, 0, true, 0, 0,
+ TH_SYN|TH_ACK, 0, s->src.mss, 0, M_SKIP_FIREWALL, 0, 0,
pd->act.rtableid);
REASON_SET(&reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
@@ -5898,8 +5905,8 @@
pd->dst, pd->src, th->th_dport,
th->th_sport, ntohl(th->th_ack), 0,
TH_RST, 0, 0,
- (*state)->rule->return_ttl, true, 0, 0,
- (*state)->act.rtableid);
+ (*state)->rule->return_ttl, M_SKIP_FIREWALL,
+ 0, 0, (*state)->act.rtableid);
src->seqlo = 0;
src->seqhi = 1;
src->max_win = 1;
@@ -6035,8 +6042,8 @@
pf_send_tcp((*state)->rule, pd->af, pd->dst,
pd->src, th->th_dport, th->th_sport,
(*state)->src.seqhi, ntohl(th->th_seq) + 1,
- TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, true, 0, 0,
- (*state)->act.rtableid);
+ TH_SYN|TH_ACK, 0, (*state)->src.mss, 0,
+ M_SKIP_FIREWALL, 0, 0, (*state)->act.rtableid);
REASON_SET(reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
} else if ((th->th_flags & (TH_ACK|TH_RST|TH_FIN)) != TH_ACK ||
@@ -6067,8 +6074,9 @@
&sk->addr[pd->sidx], &sk->addr[pd->didx],
sk->port[pd->sidx], sk->port[pd->didx],
(*state)->dst.seqhi, 0, TH_SYN, 0,
- (*state)->src.mss, 0, false, (*state)->tag, 0,
- (*state)->act.rtableid);
+ (*state)->src.mss, 0,
+ (*state)->orig_kif->pfik_ifp == V_loif ? M_LOOP : 0,
+ (*state)->tag, 0, (*state)->act.rtableid);
REASON_SET(reason, PFRES_SYNPROXY);
return (PF_SYNPROXY_DROP);
} else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
@@ -6082,14 +6090,14 @@
pf_send_tcp((*state)->rule, pd->af, pd->dst,
pd->src, th->th_dport, th->th_sport,
ntohl(th->th_ack), ntohl(th->th_seq) + 1,
- TH_ACK, (*state)->src.max_win, 0, 0, false,
+ TH_ACK, (*state)->src.max_win, 0, 0, 0,
(*state)->tag, 0, (*state)->act.rtableid);
pf_send_tcp((*state)->rule, pd->af,
&sk->addr[pd->sidx], &sk->addr[pd->didx],
sk->port[pd->sidx], sk->port[pd->didx],
(*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
- TH_ACK, (*state)->dst.max_win, 0, 0, true, 0, 0,
- (*state)->act.rtableid);
+ TH_ACK, (*state)->dst.max_win, 0, 0,
+ M_SKIP_FIREWALL, 0, 0, (*state)->act.rtableid);
(*state)->src.seqdiff = (*state)->dst.seqhi -
(*state)->src.seqlo;
(*state)->dst.seqdiff = (*state)->src.seqhi -
diff --git a/sys/netpfil/pf/pf_syncookies.c b/sys/netpfil/pf/pf_syncookies.c
--- a/sys/netpfil/pf/pf_syncookies.c
+++ b/sys/netpfil/pf/pf_syncookies.c
@@ -298,7 +298,8 @@
iss = pf_syncookie_generate(pd, mss);
pf_send_tcp(NULL, pd->af, pd->dst, pd->src, *pd->dport, *pd->sport,
iss, ntohl(pd->hdr.tcp.th_seq) + 1, TH_SYN|TH_ACK, 0, mss,
- 0, true, 0, 0, pd->act.rtableid);
+ 0, M_SKIP_FIREWALL | (pd->m->m_flags & M_LOOP), 0, 0,
+ pd->act.rtableid);
counter_u64_add(V_pf_status.lcounters[KLCNT_SYNCOOKIES_SENT], 1);
/* XXX Maybe only in adaptive mode? */
atomic_add_64(&V_pf_status.syncookies_inflight[V_pf_syncookie_status.oddeven],
@@ -515,6 +516,7 @@
wscale = pf_syncookie_wstab[cookie.flags.wscale_idx];
return (pf_build_tcp(NULL, pd->af, pd->src, pd->dst, *pd->sport,
- *pd->dport, seq, 0, TH_SYN, wscale, mss, pd->ttl, false, 0,
- PF_MTAG_FLAG_SYNCOOKIE_RECREATED, pd->act.rtableid));
+ *pd->dport, seq, 0, TH_SYN, wscale, mss, pd->ttl,
+ (pd->m->m_flags & M_LOOP), 0, PF_MTAG_FLAG_SYNCOOKIE_RECREATED,
+ pd->act.rtableid));
}
diff --git a/tests/sys/netpfil/pf/syncookie.sh b/tests/sys/netpfil/pf/syncookie.sh
--- a/tests/sys/netpfil/pf/syncookie.sh
+++ b/tests/sys/netpfil/pf/syncookie.sh
@@ -233,6 +233,90 @@
pft_cleanup
}
+loopback_test()
+{
+ local addr port
+
+ addr=$1
+ port=$2
+
+ # syncookies don't work without state tracking enabled.
+ atf_check -e ignore pfctl -e
+ atf_check pfctl -f - <<__EOF__
+set syncookies always
+pass all keep state
+__EOF__
+
+ # Try to transmit data over a loopback connection.
+ cat <<__EOF__ >in
+Creativity, no.
+__EOF__
+ nc -l $addr $port >out &
+
+ atf_check nc -N $addr $port < in
+
+ atf_check -o file:in cat out
+
+ atf_check -e ignore pfctl -d
+}
+
+atf_test_case "loopback" "cleanup"
+loopback_head()
+{
+ atf_set descr 'Make sure that loopback v4 TCP connections work with syncookies on'
+ atf_set require.user root
+}
+
+loopback_body()
+{
+ local epair
+
+ pft_init
+
+ atf_check ifconfig lo0 127.0.0.1/8
+ atf_check ifconfig lo0 up
+
+ loopback_test 127.0.0.1 8080
+
+ epair=$(vnet_mkepair)
+ atf_check ifconfig ${epair}a inet 192.0.2.1/24
+
+ loopback_test 192.0.2.1 8081
+}
+
+loopback_cleanup()
+{
+ pft_cleanup
+}
+
+atf_test_case "loopback_v6" "cleanup"
+loopback_v6_head()
+{
+ atf_set descr 'Make sure that loopback v6 TCP connections work with syncookies on'
+ atf_set require.user root
+}
+
+loopback_v6_body()
+{
+ local epair
+
+ pft_init
+
+ atf_check ifconfig lo0 up
+
+ loopback_test ::1 8080
+
+ epair=$(vnet_mkepair)
+ atf_check ifconfig ${epair}a inet6 2001:db8::1/64
+
+ loopback_test 2001:db8::1 8081
+}
+
+loopback_v6_cleanup()
+{
+ pft_cleanup
+}
+
atf_test_case "nostate" "cleanup"
nostate_head()
{
@@ -483,6 +567,8 @@
atf_add_test_case "basic_v6"
atf_add_test_case "forward"
atf_add_test_case "forward_v6"
+ atf_add_test_case "loopback"
+ atf_add_test_case "loopback_v6"
atf_add_test_case "nostate"
atf_add_test_case "nostate_v6"
atf_add_test_case "adaptive"

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 31, 4:23 PM (17 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16366514
Default Alt Text
D47257.diff (8 KB)

Event Timeline