diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2008-05-09 02:44:56 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2008-05-09 02:44:56 +0000 |
commit | 6b5278216d3e945e7764e8fb4d6084731d9c1d42 (patch) | |
tree | e16579e8549035c8a3ce6525cf6278091980d103 /sys/net | |
parent | bf10d8a20a778604168423fc81c27ee72bc63285 (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.c | 54 | ||||
-rw-r--r-- | sys/net/pfvar.h | 16 |
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 *); |