summaryrefslogtreecommitdiff
path: root/sys/net/pf.c
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2008-05-09 02:44:56 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2008-05-09 02:44:56 +0000
commit6b5278216d3e945e7764e8fb4d6084731d9c1d42 (patch)
treee16579e8549035c8a3ce6525cf6278091980d103 /sys/net/pf.c
parentbf10d8a20a778604168423fc81c27ee72bc63285 (diff)
divert packets to local socket without modifying the ip header;
makes transparent proxies much easier; ok beck@, feedback claudio@
Diffstat (limited to 'sys/net/pf.c')
-rw-r--r--sys/net/pf.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/sys/net/pf.c b/sys/net/pf.c
index a76f3c7fbe8..42cb24c54f9 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.572 2008/05/07 07:07:29 markus Exp $ */
+/* $OpenBSD: pf.c,v 1.573 2008/05/09 02:44:54 markus Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -218,6 +218,7 @@ void pf_set_rt_ifp(struct pf_state *,
struct pf_addr *);
int pf_check_proto_cksum(struct mbuf *, int, int,
u_int8_t, sa_family_t);
+struct pf_divert *pf_get_divert(struct mbuf *);
int pf_addr_wrap_neq(struct pf_addr_wrap *,
struct pf_addr_wrap *);
struct pf_state *pf_find_state(struct pfi_kif *,
@@ -2653,7 +2654,8 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
case AF_INET:
inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
if (inp == NULL) {
- inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
+ inp = in_pcblookup_listen(tb, daddr->v4, dport, 0,
+ NULL);
if (inp == NULL)
return (-1);
}
@@ -5456,6 +5458,34 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
return (0);
}
+struct pf_divert *
+pf_find_divert(struct mbuf *m)
+{
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL)
+ return (NULL);
+
+ return ((struct pf_divert *)(mtag + 1));
+}
+
+struct pf_divert *
+pf_get_divert(struct mbuf *m)
+{
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF_DIVERT, NULL)) == NULL) {
+ mtag = m_tag_get(PACKET_TAG_PF_DIVERT, sizeof(struct pf_divert),
+ M_NOWAIT);
+ if (mtag == NULL)
+ return (NULL);
+ bzero(mtag + 1, sizeof(struct pf_divert));
+ m_tag_prepend(m, mtag);
+ }
+
+ return ((struct pf_divert *)(mtag + 1));
+}
+
#ifdef INET
int
pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
@@ -5674,6 +5704,16 @@ done:
(ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
+ if (dir == PF_IN && action == PF_PASS && r->divert.port) {
+ struct pf_divert *divert;
+
+ if ((divert = pf_get_divert(m))) {
+ m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED;
+ divert->port = r->divert.port;
+ divert->addr.ipv4 = r->divert.addr.v4;
+ }
+ }
+
if (log) {
struct pf_rule *lr;
@@ -6050,6 +6090,16 @@ done:
IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))
m->m_pkthdr.pf.flags |= PF_TAG_TRANSLATE_LOCALHOST;
+ if (dir == PF_IN && action == PF_PASS && r->divert.port) {
+ struct pf_divert *divert;
+
+ if ((divert = pf_get_divert(m))) {
+ m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED;
+ divert->port = r->divert.port;
+ divert->addr.ipv6 = r->divert.addr.v6;
+ }
+ }
+
if (log) {
struct pf_rule *lr;