summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Wooding <kjell@cvs.openbsd.org>2001-07-01 17:16:04 +0000
committerKjell Wooding <kjell@cvs.openbsd.org>2001-07-01 17:16:04 +0000
commit0834bde8262d89fe0a1b8f247c760c2ef2ee40fe (patch)
treec71dcaa9b2c24e868ed133b741278e6837283cd9
parent88de2e0615dc2d5e815c81c7c23d6dd7066bd40d (diff)
Add port ranges to the rdr directive. Connections can be redirected
to either a range of the same size, or a single port. Redirects between ranges of different sizes are not supported. Eg: rdr dc0 10.0.0.0/24 port 60000:61000 -> 127.0.0.1 port 65530:* proto udp rdr xl0 0.0.0.0/0 port 6660:6669 -> 127.0.0.1 port 6667 proto tcp This replaces the wildcard port patch (when port = 0), as it should no longer be necessary. ok dhartmei@
-rw-r--r--sbin/pfctl/pfctl_parser.c28
-rw-r--r--sys/net/pf.c39
-rw-r--r--sys/net/pfvar.h8
3 files changed, 63 insertions, 12 deletions
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 74d9418ba6b..074407a5640 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.23 2001/07/01 17:04:13 kjell Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.24 2001/07/01 17:16:02 kjell Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -282,9 +282,14 @@ print_rdr(struct pf_rdr *r)
printf("/");
print_addr(r->dmask);
}
- printf(" port %u -> ", ntohs(r->dport));
+ printf(" port %u", ntohs(r->dport));
+ if (r->opts & PF_DPORT_RANGE)
+ printf(":%u", ntohs(r->dport2));
+ printf(" -> ");
print_addr(r->raddr);
printf(" port %u", ntohs(r->rport));
+ if (r->opts & PF_RPORT_RANGE)
+ printf(":*");
switch (r->proto) {
case IPPROTO_TCP:
printf(" proto tcp");
@@ -979,7 +984,7 @@ parse_nat(int n, char *l, struct pf_nat *nat)
int
parse_rdr(int n, char *l, struct pf_rdr *rdr)
{
- char *w;
+ char *w, *s;
memset(rdr, 0, sizeof(struct pf_rdr));
w = next_word(&l);
@@ -1017,7 +1022,17 @@ parse_rdr(int n, char *l, struct pf_rdr *rdr)
return (0);
}
w = next_word(&l);
- rdr->dport = htons(next_number(&w));
+ /* check for port range */
+ if ((s = strchr(w, ':')) == NULL) {
+ rdr->dport = htons(next_number(&w));
+ rdr->dport2 = rdr->dport;
+ } else {
+ *s++ = '\0';
+ rdr->dport = htons(next_number(&w));
+ rdr->dport2 = htons(next_number(&s));
+ rdr->opts |= PF_DPORT_RANGE;
+ }
+
w = next_word(&l);
/* -> */
@@ -1037,6 +1052,11 @@ parse_rdr(int n, char *l, struct pf_rdr *rdr)
return (0);
}
w = next_word(&l);
+ /* check if redirected port is a range */
+ if ((s = strchr(w, ':')) != NULL) {
+ rdr->opts |= PF_RPORT_RANGE;
+ }
+
rdr->rport = htons(next_number(&w));
w = next_word(&l);
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 98e4763553a..acd5f1de851 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.90 2001/07/01 11:22:45 dhartmei Exp $ */
+/* $OpenBSD: pf.c,v 1.91 2001/07/01 17:16:03 kjell Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -183,6 +183,7 @@ int pf_match_addr(u_int8_t, u_int32_t, u_int32_t,
u_int32_t);
int pf_match_port(u_int8_t, u_int16_t, u_int16_t,
u_int16_t);
+u_int16_t pf_map_port_range(struct pf_rdr *, u_int16_t);
struct pf_nat *pf_get_nat(struct ifnet *, u_int8_t, u_int32_t);
struct pf_rdr *pf_get_rdr(struct ifnet *, u_int8_t, u_int32_t,
u_int16_t);
@@ -1343,7 +1344,8 @@ pf_get_rdr(struct ifnet *ifp, u_int8_t proto, u_int32_t addr, u_int16_t port)
if (r->ifp == ifp &&
(!r->proto || r->proto == proto) &&
pf_match_addr(r->not, r->daddr, r->dmask, addr) &&
- ((r->dport == 0) || (r->dport == port)))
+ (ntohs(port) >= ntohs(r->dport)) &&
+ (ntohs(port) <= ntohs(r->dport2)))
rm = r;
else
r = TAILQ_NEXT(r, entries);
@@ -1365,6 +1367,18 @@ pf_get_rdr(struct ifnet *ifp, u_int8_t proto, u_int32_t addr, u_int16_t port)
pf_status.counters[x]++; \
} while (0)
+u_int16_t
+pf_map_port_range(struct pf_rdr *rdr, u_int16_t port)
+{
+ u_int32_t nport;
+
+ nport = ntohs(rdr->rport) - ntohs(rdr->dport) + ntohs(port);
+ /* wrap around if necessary */
+ if (nport > 65535)
+ nport -= 65535;
+ return htons((u_int16_t)nport);
+}
+
int
pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
int ipoff, int off, struct ip *h, struct tcphdr *th)
@@ -1372,7 +1386,7 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
struct pf_nat *nat = NULL;
struct pf_rdr *rdr = NULL;
u_int32_t baddr;
- u_int16_t bport;
+ u_int16_t bport, nport;
struct pf_rule *r, *rm = NULL;
u_short reason;
int rewrite = 0;
@@ -1394,9 +1408,14 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
th->th_dport)) != NULL) {
baddr = h->ip_dst.s_addr;
bport = th->th_dport;
+ if (rdr->opts & PF_RPORT_RANGE)
+ nport = pf_map_port_range(rdr, th->th_dport);
+ else
+ nport = rdr->rport;
+
pf_change_ap(&h->ip_dst.s_addr, &th->th_dport,
- &h->ip_sum, &th->th_sum, rdr->raddr,
- rdr->rport ? rdr->rport : th->th_dport);
+ &h->ip_sum, &th->th_sum, rdr->raddr, nport);
+
rewrite++;
}
}
@@ -1519,7 +1538,7 @@ pf_test_udp(int direction, struct ifnet *ifp, struct mbuf *m,
struct pf_nat *nat = NULL;
struct pf_rdr *rdr = NULL;
u_int32_t baddr;
- u_int16_t bport;
+ u_int16_t bport, nport;
struct pf_rule *r, *rm = NULL;
u_short reason;
int rewrite = 0;
@@ -1541,9 +1560,15 @@ pf_test_udp(int direction, struct ifnet *ifp, struct mbuf *m,
uh->uh_dport)) != NULL) {
baddr = h->ip_dst.s_addr;
bport = uh->uh_dport;
+ if (rdr->opts & PF_RPORT_RANGE)
+ nport = pf_map_port_range(rdr, uh->uh_dport);
+ else
+ nport = rdr->rport;
+
pf_change_ap(&h->ip_dst.s_addr, &uh->uh_dport,
&h->ip_sum, &uh->uh_sum, rdr->raddr,
- rdr->rport ? rdr->rport : uh->uh_dport);
+ nport);
+
rewrite++;
}
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 5c581e8043c..0ca01b88afb 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.26 2001/06/29 03:09:14 angelos Exp $ */
+/* $OpenBSD: pfvar.h,v 1.27 2001/07/01 17:16:03 kjell Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -119,11 +119,17 @@ struct pf_rdr {
u_int32_t dmask;
u_int32_t raddr;
u_int16_t dport;
+ u_int16_t dport2;
u_int16_t rport;
u_int8_t proto;
u_int8_t not;
+ u_int8_t opts;
};
+/* flags for RDR options */
+#define PF_DPORT_RANGE 0x01 /* Dest port uses range */
+#define PF_RPORT_RANGE 0x02 /* RDR'ed port uses range */
+
/* Reasons code for passing/dropping a packet */
#define PFRES_MATCH 0 /* Explicit match of a rule */
#define PFRES_BADOFF 1 /* Bad offset for pull_hdr */