summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hartmeier <dhartmei@cvs.openbsd.org>2001-07-09 10:30:59 +0000
committerDaniel Hartmeier <dhartmei@cvs.openbsd.org>2001-07-09 10:30:59 +0000
commitb2e5ab0e0fbf50909c74b8c819ec38eca710d485 (patch)
tree43d42e97d27b67323356cb753294a7fc72d826dc
parent21b67dfa00b0d641557b13a4209b13f43617172a (diff)
Extend nat/rdr syntax. Add source/destination selection. Make
interface optional. Suggested by rdump@river.com. nat [on [!] <ifname>] from (any | [!] <addr>[/<mask>]) to (any | [!] <addr>[/<mask>]) -> <addr> [proto (tcp | udp | icmp)] rdr [on [!] <ifname>] from (any | [!] <addr>[/<mask>]) to (any | [!] <addr>[/<mask>]) port <a>[:<b>] -> <addr> port <c>[:*] [proto (tcp | udp | icmp)]
-rw-r--r--etc/nat.conf6
-rw-r--r--sbin/pfctl/pfctl_parser.c238
-rw-r--r--sys/net/pf.c83
-rw-r--r--sys/net/pfvar.h12
4 files changed, 236 insertions, 103 deletions
diff --git a/etc/nat.conf b/etc/nat.conf
index d8779f242d3..463b0089c1e 100644
--- a/etc/nat.conf
+++ b/etc/nat.conf
@@ -1,4 +1,4 @@
-# $OpenBSD: nat.conf,v 1.2 2001/06/26 22:58:31 smart Exp $
+# $OpenBSD: nat.conf,v 1.3 2001/07/09 10:30:58 dhartmei Exp $
#
# See nat.conf(5) for syntax and examples
#
@@ -9,10 +9,10 @@
# translated as coming from 192.168.1.1. a state is created for such packets,
# and incoming packets will be redirected to the internal address.
-# nat ext0 10.0.0.0/8 -> 192.168.1.1
+# nat on ext0 from 10.0.0.0/8 to any -> 192.168.1.1
# rdr: packets coming in through ext0 with destination 192.168.1.1:1234 will
# be redirected to 10.1.1.1:5678. a state is created for such packets, and
# outgoing packets will be translated as coming from the external address.
-# rdr ext0 192.168.1.1/32 port 1234 -> 10.1.1.1 port 5678 proto tcp
+# rdr on ext0 from any to 192.168.1.1/32 port 1234 -> 10.1.1.1 port 5678 proto tcp
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 6a979969a9a..1c2d39e8752 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.28 2001/07/06 21:19:54 chris Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.29 2001/07/09 10:30:58 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -263,27 +263,48 @@ void
print_nat(struct pf_nat *n)
{
printf("nat ");
- if (n->ifnot)
- printf("! ");
- printf("%s ", n->ifname);
- if (n->not)
- printf("! ");
- print_addr(n->saddr);
- if (n->smask != 0xFFFFFFFF) {
- printf("/");
- print_addr(n->smask);
+ if (n->ifname[0]) {
+ printf("on ");
+ if (n->ifnot)
+ printf("! ");
+ printf("%s ", n->ifname);
}
- printf(" -> ");
- print_addr(n->daddr);
+ printf("from ");
+ if (n->saddr || n->smask) {
+ if (n->snot)
+ printf("! ");
+ print_addr(n->saddr);
+ if (n->smask != 0xFFFFFFFF) {
+ printf("/");
+ print_addr(n->smask);
+ }
+ printf(" ");
+ } else
+ printf("any ");
+ printf("to ");
+ if (n->daddr || n->dmask) {
+ if (n->dnot)
+ printf("! ");
+ print_addr(n->daddr);
+ if (n->dmask != 0xFFFFFFFF) {
+ printf("/");
+ print_addr(n->dmask);
+ }
+ printf(" ");
+ } else
+ printf("any ");
+ printf("-> ");
+ print_addr(n->raddr);
+ printf(" ");
switch (n->proto) {
case IPPROTO_TCP:
- printf(" proto tcp");
+ printf("proto tcp");
break;
case IPPROTO_UDP:
- printf(" proto udp");
+ printf("proto udp");
break;
case IPPROTO_ICMP:
- printf(" proto icmp");
+ printf("proto icmp");
break;
}
printf("\n");
@@ -293,30 +314,52 @@ void
print_rdr(struct pf_rdr *r)
{
printf("rdr ");
- if (r->ifnot)
- printf("! ");
- printf("%s ", r->ifname);
- if (r->not)
- printf("! ");
- print_addr(r->daddr);
- if (r->dmask != 0xFFFFFFFF) {
- printf("/");
- print_addr(r->dmask);
+ if (r->ifname[0]) {
+ printf("on ");
+ if (r->ifnot)
+ printf("! ");
+ printf("%s ", r->ifname);
}
- printf(" port %u", ntohs(r->dport));
+ printf("from ");
+ if (r->saddr || r->smask) {
+ if (r->snot)
+ printf("! ");
+ print_addr(r->saddr);
+ if (r->smask != 0xFFFFFFFF) {
+ printf("/");
+ print_addr(r->smask);
+ }
+ printf(" ");
+ } else
+ printf("any ");
+ printf("to ");
+ if (r->daddr || r->dmask) {
+ if (r->dnot)
+ printf("! ");
+ print_addr(r->daddr);
+ if (r->dmask != 0xFFFFFFFF) {
+ printf("/");
+ print_addr(r->dmask);
+ }
+ printf(" ");
+ } else
+ printf("any ");
+ 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));
+ printf(" ");
+ printf("port %u", ntohs(r->rport));
if (r->opts & PF_RPORT_RANGE)
printf(":*");
+ printf(" ");
switch (r->proto) {
case IPPROTO_TCP:
- printf(" proto tcp");
+ printf("proto tcp");
break;
case IPPROTO_UDP:
- printf(" proto udp");
+ printf("proto udp");
break;
}
printf("\n");
@@ -982,29 +1025,66 @@ parse_nat(int n, char *l, struct pf_nat *nat)
}
w = next_word(&l);
- /* if */
- if (!strcmp(w, "!")) {
- nat->ifnot = 1;
+ /* interface */
+ if (!strcmp(w, "on")) {
+ w = next_word(&l);
+ if (!strcmp(w, "!")) {
+ nat->ifnot = 1;
+ w = next_word(&l);
+ }
+ strncpy(nat->ifname, w, 16);
w = next_word(&l);
}
- strncpy(nat->ifname, w, 16);
- w = next_word(&l);
- /* internal addr/mask */
- if (!strcmp(w, "!")) {
- nat->not = 1;
- w = next_word(&l);
+ /* source addr/mask */
+ if (strcmp(w, "from")) {
+ error(n, "expected from, got %s\n", w);
+ return (0);
}
- nat->saddr = next_addr(&w);
- if (!*w)
- nat->smask = 0xFFFFFFFF;
- else if (*w == '/')
- nat->smask = rule_mask(next_number(&w));
+ w = next_word(&l);
+ if (!strcmp(w, "any"))
+ w = next_word(&l);
else {
- error(n, "expected /, got '%c'\n", *w);
+ if (!strcmp(w, "!")) {
+ nat->snot = 1;
+ w = next_word(&l);
+ }
+ nat->saddr = next_addr(&w);
+ if (!*w)
+ nat->smask = 0xFFFFFFFF;
+ else if (*w == '/')
+ nat->smask = rule_mask(next_number(&w));
+ else {
+ error(n, "expected /, get '%c'\n", *w);
+ return (0);
+ }
+ w = next_word(&l);
+ }
+
+ /* destination addr/mask */
+ if (strcmp(w, "to")) {
+ error(n, "expected to, got %s\n", w);
return (0);
}
w = next_word(&l);
+ if (!strcmp(w, "any"))
+ w = next_word(&l);
+ else {
+ if (!strcmp(w, "!")) {
+ nat->dnot = 1;
+ w = next_word(&l);
+ }
+ nat->daddr = next_addr(&w);
+ if (!*w)
+ nat->dmask = 0xFFFFFFFF;
+ else if (*w == '/')
+ nat->dmask = rule_mask(next_number(&w));
+ else {
+ error(n, "expected /, get '%c'\n", *w);
+ return (0);
+ }
+ w = next_word(&l);
+ }
/* -> */
if (strcmp(w, "->")) {
@@ -1014,7 +1094,7 @@ parse_nat(int n, char *l, struct pf_nat *nat)
w = next_word(&l);
/* external addr */
- nat->daddr = next_addr(&w);
+ nat->raddr = next_addr(&w);
w = next_word(&l);
/* proto */
@@ -1057,31 +1137,68 @@ parse_rdr(int n, char *l, struct pf_rdr *rdr)
}
w = next_word(&l);
- /* if */
- if (!strcmp(w, "!")) {
- rdr->ifnot = 1;
+ /* interface */
+ if (!strcmp(w, "on")) {
+ w = next_word(&l);
+ if (!strcmp(w, "!")) {
+ rdr->ifnot = 1;
+ w = next_word(&l);
+ }
+ strncpy(rdr->ifname, w, 16);
w = next_word(&l);
}
- strncpy(rdr->ifname, w, 16);
- w = next_word(&l);
- /* external addr/mask */
- if (!strcmp(w, "!")) {
- rdr->not = 1;
- w = next_word(&l);
+ /* source addr/mask */
+ if (strcmp(w, "from")) {
+ error(n, "expected from, got %s\n", w);
+ return (0);
}
- rdr->daddr = next_addr(&w);
- if (!*w)
- rdr->dmask = 0xFFFFFFFF;
- else if (*w == '/')
- rdr->dmask = rule_mask(next_number(&w));
+ w = next_word(&l);
+ if (!strcmp(w, "any"))
+ w = next_word(&l);
else {
- error(n, "expected /, got '%c'\n", *w);
+ if (!strcmp(w, "!")) {
+ rdr->snot = 1;
+ w = next_word(&l);
+ }
+ rdr->saddr = next_addr(&w);
+ if (!*w)
+ rdr->smask = 0xFFFFFFFF;
+ else if (*w == '/')
+ rdr->smask = rule_mask(next_number(&w));
+ else {
+ error(n, "expected /, get '%c'\n", *w);
+ return (0);
+ }
+ w = next_word(&l);
+ }
+
+ /* external addr/mask */
+ if (strcmp(w, "to")) {
+ error(n, "expected to, got %s\n", w);
return (0);
}
w = next_word(&l);
+ if (!strcmp(w, "any"))
+ w = next_word(&l);
+ else {
+ if (!strcmp(w, "!")) {
+ rdr->dnot = 1;
+ w = next_word(&l);
+ }
+ rdr->daddr = next_addr(&w);
+ if (!*w)
+ rdr->dmask = 0xFFFFFFFF;
+ else if (*w == '/')
+ rdr->dmask = rule_mask(next_number(&w));
+ else {
+ error(n, "expected /, get '%c'\n", *w);
+ return (0);
+ }
+ w = next_word(&l);
+ }
- /* external port */
+ /* external port (range) */
if (strcmp(w, "port")) {
error(n, "expected port, got %s\n", w);
return (0);
@@ -1097,7 +1214,6 @@ parse_rdr(int n, char *l, struct pf_rdr *rdr)
rdr->dport2 = htons(next_number(&s));
rdr->opts |= PF_DPORT_RANGE;
}
-
w = next_word(&l);
/* -> */
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 9313f50dd85..8e4f35cf0e1 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.106 2001/07/07 01:56:09 marc Exp $ */
+/* $OpenBSD: pf.c,v 1.107 2001/07/09 10:30:57 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -176,9 +176,10 @@ int pf_match_addr(u_int8_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_nat *pf_get_nat(struct ifnet *, u_int8_t, u_int32_t,
+ u_int32_t);
struct pf_rdr *pf_get_rdr(struct ifnet *, u_int8_t, u_int32_t,
- u_int16_t);
+ u_int32_t, u_int16_t);
int pf_test_tcp(int, struct ifnet *, struct mbuf *,
int, int, struct ip *, struct tcphdr *);
int pf_test_udp(int, struct ifnet *, struct mbuf *,
@@ -797,7 +798,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
error = EINVAL;
break;
}
- }
+ } else
+ rule->ifp = NULL;
TAILQ_INSERT_TAIL(pf_rules_inactive, rule, entries);
break;
}
@@ -898,12 +900,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(&pn->nat, nat, sizeof(struct pf_nat));
- nat->ifp = ifunit(nat->ifname);
- if (nat->ifp == NULL) {
- pool_put(&pf_nat_pl, nat);
- error = EINVAL;
- break;
- }
+ if (nat->ifname[0]) {
+ nat->ifp = ifunit(nat->ifname);
+ if (nat->ifp == NULL) {
+ pool_put(&pf_nat_pl, nat);
+ error = EINVAL;
+ break;
+ }
+ } else
+ nat->ifp = NULL;
TAILQ_INSERT_TAIL(pf_nats_inactive, nat, entries);
break;
}
@@ -999,12 +1004,15 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(&pr->rdr, rdr, sizeof(struct pf_rdr));
- rdr->ifp = ifunit(rdr->ifname);
- if (rdr->ifp == NULL) {
- pool_put(&pf_rdr_pl, rdr);
- error = EINVAL;
- break;
- }
+ if (rdr->ifname[0]) {
+ rdr->ifp = ifunit(rdr->ifname);
+ if (rdr->ifp == NULL) {
+ pool_put(&pf_rdr_pl, rdr);
+ error = EINVAL;
+ break;
+ }
+ } else
+ rdr->ifp = NULL;
TAILQ_INSERT_TAIL(pf_rdrs_inactive, rdr, entries);
break;
}
@@ -1389,16 +1397,17 @@ pf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p)
}
struct pf_nat *
-pf_get_nat(struct ifnet *ifp, u_int8_t proto, u_int32_t addr)
+pf_get_nat(struct ifnet *ifp, u_int8_t proto, u_int32_t saddr, u_int32_t daddr)
{
struct pf_nat *n, *nm = NULL;
n = TAILQ_FIRST(pf_nats_active);
while (n && nm == NULL) {
- if (((n->ifp == ifp && !n->ifnot) ||
+ if (((n->ifp == NULL) || (n->ifp == ifp && !n->ifnot) ||
(n->ifp != ifp && n->ifnot)) &&
(!n->proto || n->proto == proto) &&
- pf_match_addr(n->not, n->saddr, n->smask, addr))
+ pf_match_addr(n->snot, n->saddr, n->smask, saddr) &&
+ pf_match_addr(n->dnot, n->daddr, n->dmask, daddr))
nm = n;
else
n = TAILQ_NEXT(n, entries);
@@ -1407,18 +1416,20 @@ pf_get_nat(struct ifnet *ifp, u_int8_t proto, u_int32_t addr)
}
struct pf_rdr *
-pf_get_rdr(struct ifnet *ifp, u_int8_t proto, u_int32_t addr, u_int16_t port)
+pf_get_rdr(struct ifnet *ifp, u_int8_t proto, u_int32_t saddr, u_int32_t daddr,
+ u_int16_t dport)
{
struct pf_rdr *r, *rm = NULL;
r = TAILQ_FIRST(pf_rdrs_active);
while (r && rm == NULL) {
- if (((r->ifp == ifp && !r->ifnot) ||
+ if (((r->ifp == NULL) || (r->ifp == ifp && !r->ifnot) ||
(r->ifp != ifp && r->ifnot)) &&
(!r->proto || r->proto == proto) &&
- pf_match_addr(r->not, r->daddr, r->dmask, addr) &&
- (ntohs(port) >= ntohs(r->dport)) &&
- (ntohs(port) <= ntohs(r->dport2)))
+ pf_match_addr(r->snot, r->saddr, r->smask, saddr) &&
+ pf_match_addr(r->dnot, r->daddr, r->dmask, daddr) &&
+ (ntohs(dport) >= ntohs(r->dport)) &&
+ (ntohs(dport) <= ntohs(r->dport2)))
rm = r;
else
r = TAILQ_NEXT(r, entries);
@@ -1467,18 +1478,18 @@ pf_test_tcp(int direction, struct ifnet *ifp, struct mbuf *m,
if (direction == PF_OUT) {
/* check outgoing packet for NAT */
if ((nat = pf_get_nat(ifp, IPPROTO_TCP,
- h->ip_src.s_addr)) != NULL) {
+ h->ip_src.s_addr, h->ip_dst.s_addr)) != NULL) {
baddr = h->ip_src.s_addr;
bport = th->th_sport;
pf_change_ap(&h->ip_src.s_addr, &th->th_sport,
- &h->ip_sum, &th->th_sum, nat->daddr,
+ &h->ip_sum, &th->th_sum, nat->raddr,
htons(pf_next_port_tcp));
rewrite++;
}
} else {
/* check incoming packet for RDR */
- if ((rdr = pf_get_rdr(ifp, IPPROTO_TCP, h->ip_dst.s_addr,
- th->th_dport)) != NULL) {
+ if ((rdr = pf_get_rdr(ifp, IPPROTO_TCP, h->ip_src.s_addr,
+ h->ip_dst.s_addr, th->th_dport)) != NULL) {
baddr = h->ip_dst.s_addr;
bport = th->th_dport;
if (rdr->opts & PF_RPORT_RANGE)
@@ -1621,19 +1632,19 @@ pf_test_udp(int direction, struct ifnet *ifp, struct mbuf *m,
if (direction == PF_OUT) {
/* check outgoing packet for NAT */
- if ((nat = pf_get_nat(ifp, IPPROTO_UDP, h->ip_src.s_addr)) !=
- NULL) {
+ if ((nat = pf_get_nat(ifp, IPPROTO_UDP,
+ h->ip_src.s_addr, h->ip_dst.s_addr)) != NULL) {
baddr = h->ip_src.s_addr;
bport = uh->uh_sport;
pf_change_ap(&h->ip_src.s_addr, &uh->uh_sport,
- &h->ip_sum, &uh->uh_sum, nat->daddr,
+ &h->ip_sum, &uh->uh_sum, nat->raddr,
htons(pf_next_port_udp));
rewrite++;
}
} else {
/* check incoming packet for RDR */
- if ((rdr = pf_get_rdr(ifp, IPPROTO_UDP, h->ip_dst.s_addr,
- uh->uh_dport)) != NULL) {
+ if ((rdr = pf_get_rdr(ifp, IPPROTO_UDP, h->ip_src.s_addr,
+ h->ip_dst.s_addr, uh->uh_dport)) != NULL) {
baddr = h->ip_dst.s_addr;
bport = uh->uh_dport;
if (rdr->opts & PF_RPORT_RANGE)
@@ -1764,10 +1775,10 @@ pf_test_icmp(int direction, struct ifnet *ifp, struct mbuf *m,
if (direction == PF_OUT) {
/* check outgoing packet for NAT */
- if ((nat = pf_get_nat(ifp, IPPROTO_ICMP, h->ip_src.s_addr)) !=
- NULL) {
+ if ((nat = pf_get_nat(ifp, IPPROTO_ICMP,
+ h->ip_src.s_addr, h->ip_dst.s_addr)) != NULL) {
baddr = h->ip_src.s_addr;
- pf_change_a(&h->ip_src.s_addr, &h->ip_sum, nat->daddr);
+ pf_change_a(&h->ip_src.s_addr, &h->ip_sum, nat->raddr);
}
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index b451207ff13..a7176ed8141 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.31 2001/07/06 21:19:56 chris Exp $ */
+/* $OpenBSD: pfvar.h,v 1.32 2001/07/09 10:30:56 dhartmei Exp $ */
/*
* Copyright (c) 2001, Daniel Hartmeier
@@ -124,8 +124,11 @@ struct pf_nat {
u_int32_t saddr;
u_int32_t smask;
u_int32_t daddr;
+ u_int32_t dmask;
+ u_int32_t raddr;
u_int8_t proto;
- u_int8_t not;
+ u_int8_t snot;
+ u_int8_t dnot;
u_int8_t ifnot;
};
@@ -133,6 +136,8 @@ struct pf_rdr {
char ifname[IFNAMSIZ];
struct ifnet *ifp;
TAILQ_ENTRY(pf_rdr) entries;
+ u_int32_t saddr;
+ u_int32_t smask;
u_int32_t daddr;
u_int32_t dmask;
u_int32_t raddr;
@@ -140,7 +145,8 @@ struct pf_rdr {
u_int16_t dport2;
u_int16_t rport;
u_int8_t proto;
- u_int8_t not;
+ u_int8_t snot;
+ u_int8_t dnot;
u_int8_t ifnot;
u_int8_t opts;
};