divert: consume PF_TAG_DIVERTED after passthrough (BSD ip_input role); divert layer owns its own skb ref; gate uses pfput path
This commit is contained in:
1 parent
da1f678125
commit
4728648a0c
3 files changed
+24
-6
No files matched your search
@@ -166,13 +166,19 @@ divert_packet(struct mbuf *m, int dir, u_int16_t divert_port)
|
||||
{
|
||||
struct pf_divert *dv = pf_find_divert(m);
|
||||
|
||||
if (dv)
|
||||
if (dv) {
|
||||
type = dv->type;
|
||||
if (divert_port == 0)
|
||||
divert_port = dv->port;
|
||||
}
|
||||
}
|
||||
skb = m_to_skb(m);
|
||||
m->skb = NULL; /* ownership moves into the divert layer */
|
||||
if (skb)
|
||||
skb_get(skb); /* divert layer's own reference */
|
||||
m->skb = NULL;
|
||||
m_freem(m);
|
||||
pfk_divert_queue(skb, dir, type, divert_port);
|
||||
if (skb)
|
||||
pfk_divert_queue(skb, dir, type, divert_port);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <net/pfvar_priv.h>
|
||||
|
||||
extern int pf_test(sa_family_t, int, struct pfk_ifnet *, struct mbuf **);
|
||||
extern void divert_packet(struct mbuf *, int, u_int16_t);
|
||||
extern struct workqueue_struct *pfk_netisr_wq;
|
||||
|
||||
/* PFLINUX: netisr work item — carries ownership of one sk_buff */
|
||||
@@ -91,6 +92,17 @@ pfk_pkt_work(struct work_struct *w)
|
||||
* and packet walk run concurrently from here on — documented. */
|
||||
action = pf_test(pk->af, pk->dir, pk->ifp, &m);
|
||||
|
||||
/* PF_IN rules with `divert-to` only TAG the packet (BSD
|
||||
* netinet/ip_input.c delivers tagged packets to the divert socket);
|
||||
* do that here. divert_packet() consumes the mbuf wrapper and holds
|
||||
* its own skb reference, so our wrapper pointer becomes invalid. */
|
||||
if (action == PF_PASS && m != NULL &&
|
||||
(m->m_pkthdr.pf.flags & PF_TAG_DIVERTED)) {
|
||||
m->m_pkthdr.pf.flags &= ~PF_TAG_DIVERTED;
|
||||
divert_packet(m, pk->dir, 0);
|
||||
m = NULL;
|
||||
}
|
||||
|
||||
if (m == m0) {
|
||||
/* same buffer, possibly rewritten in place: our wrapper
|
||||
* held one extra skb reference — release it */
|
||||
|
||||
@@ -16,8 +16,8 @@ FAILED=0
|
||||
|
||||
pf0 "insmod /tmp/pf.ko 2>/dev/null || insmod /opt/pf/pf.ko; true"
|
||||
pf0 '/opt/pf/pfctl -e; /opt/pf/pfctl -f /dev/null' >/dev/null
|
||||
pfput ../../tools/out/pdivert /opt/pf/pdivert || bad "pdivert deploy"
|
||||
pf0 'chmod +x /opt/pf/pdivert' >/dev/null
|
||||
PDIV=$(pfput ../../tools/out/pdivert) || bad "pdivert deploy"
|
||||
pf0 "chmod +x $PDIV" >/dev/null
|
||||
|
||||
cat > /tmp/g11.conf <<C
|
||||
pass in quick proto icmp from $CLI_IP to $PFLAN divert-to "$PFLAN" port $PORT keep state
|
||||
@@ -32,7 +32,7 @@ pf0 "/opt/pf/pfctl -s info" | grep -qi noport || true # informational
|
||||
# (b) start pdivert, capture reply bytes on cli
|
||||
cli 'tcpdump -ni eth0 -e -c 4 -X icmp > /tmp/td.txt 2>&1 &' 2>/dev/null
|
||||
sleep 1
|
||||
pf0 "setsid /opt/pf/pdivert -p $PORT -q > /tmp/pdiv.log 2>&1 & echo STARTED" | grep -q STARTED || { bad "pdivert start"; finish; }
|
||||
pf0 "setsid ${PDIV:-/tmp/pdivert} -p $PORT -q > /tmp/pdiv.log 2>&1 & echo STARTED" | grep -q STARTED || { bad "pdivert start"; finish; }
|
||||
sleep 1
|
||||
cli "ping -c 2 -W 2 $PFLAN >/dev/null 2>&1" && ok "ping passes through divert+rewrite" || bad "ping with listener"
|
||||
sleep 2
|
||||
|
||||
Reference in new issue
Block a user