summaryrefslogtreecommitdiff
path: root/sys/net
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
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')
-rw-r--r--sys/net/pf.c54
-rw-r--r--sys/net/pfvar.h16
2 files changed, 67 insertions, 3 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;
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index b186c9b2556..340071c3577 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.264 2008/05/08 08:05:16 deraadt Exp $ */
+/* $OpenBSD: pfvar.h,v 1.265 2008/05/09 02:44:54 markus Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -598,6 +598,11 @@ struct pf_rule {
#define PF_FLUSH 0x01
#define PF_FLUSH_GLOBAL 0x02
u_int8_t flush;
+
+ struct {
+ struct pf_addr addr;
+ u_int16_t port;
+ } divert;
};
/* rule flags */
@@ -1284,6 +1289,14 @@ struct pf_tagname {
int ref;
};
+struct pf_divert {
+ union {
+ struct in_addr ipv4;
+ struct in6_addr ipv6;
+ } addr;
+ u_int16_t port;
+};
+
#define PFFRAG_FRENT_HIWAT 5000 /* Number of fragment entries */
#define PFFRAG_FRAG_HIWAT 1000 /* Number of fragmented packets */
#define PFFRAG_FRCENT_HIWAT 50000 /* Number of fragment cache entries */
@@ -1592,6 +1605,7 @@ extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
u_int8_t);
void pf_rm_rule(struct pf_rulequeue *,
struct pf_rule *);
+struct pf_divert *pf_find_divert(struct mbuf *);
#ifdef INET
int pf_test(int, struct ifnet *, struct mbuf **, struct ether_header *);