summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/pfctl/parse.y31
-rw-r--r--sbin/pfctl/pfctl_parser.c6
-rw-r--r--sys/net/pf.c127
-rw-r--r--sys/net/pfvar.h15
4 files changed, 125 insertions, 54 deletions
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 05b74b0ae62..cf7c1dffe7a 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.167 2002/10/11 12:57:53 camield Exp $ */
+/* $OpenBSD: parse.y,v 1.168 2002/10/14 12:58:28 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -1362,14 +1362,14 @@ rport : STRING {
;
redirection : /* empty */ { $$ = NULL; }
- | ARROW address {
+ | ARROW host {
$$ = malloc(sizeof(struct redirection));
if ($$ == NULL)
err(1, "redirection: malloc");
$$->address = $2;
$$->rport.a = $$->rport.b = $$->rport.t = 0;
}
- | ARROW address PORT rport {
+ | ARROW host PORT rport {
$$ = malloc(sizeof(struct redirection));
if ($$ == NULL)
err(1, "redirection: malloc");
@@ -1440,7 +1440,7 @@ natrule : no NAT interface af proto fromto redirection
}
;
-binatrule : no BINAT interface af proto FROM address TO ipspec redirection
+binatrule : no BINAT interface af proto FROM host TO ipspec redirection
{
struct pf_binat binat;
@@ -1482,8 +1482,10 @@ binatrule : no BINAT interface af proto FROM address TO ipspec redirection
YYERROR;
}
binat.af = $7->af;
- memcpy(&binat.saddr, &$7->addr,
- sizeof(binat.saddr));
+ memcpy(&binat.saddr.addr, &$7->addr.addr,
+ sizeof(binat.saddr.addr));
+ memcpy(&binat.smask, &$7->mask,
+ sizeof(binat.smask));
free($7);
}
if ($9 != NULL) {
@@ -1504,8 +1506,8 @@ binatrule : no BINAT interface af proto FROM address TO ipspec redirection
YYERROR;
}
binat.af = $9->af;
- memcpy(&binat.daddr, &$9->addr,
- sizeof(binat.daddr));
+ memcpy(&binat.daddr.addr, &$9->addr.addr,
+ sizeof(binat.daddr.addr));
memcpy(&binat.dmask, &$9->mask,
sizeof(binat.dmask));
binat.dnot = $9->not;
@@ -1542,8 +1544,17 @@ binatrule : no BINAT interface af proto FROM address TO ipspec redirection
YYERROR;
}
binat.af = n->af;
- memcpy(&binat.raddr, &n->addr,
- sizeof(binat.raddr));
+ memcpy(&binat.raddr.addr, &n->addr.addr,
+ sizeof(binat.raddr.addr));
+ memcpy(&binat.rmask, &n->mask,
+ sizeof(binat.rmask));
+ if (!PF_AZERO(&binat.smask, binat.af) &&
+ !PF_AEQ(&binat.smask,
+ &binat.rmask, binat.af)) {
+ yyerror("'binat' source mask and "
+ "redirect mask must be the same");
+ YYERROR;
+ }
free($10->address);
free($10);
}
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index 5b7f23cdbfe..6c1d84a9a5c 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfctl_parser.c,v 1.99 2002/10/07 13:23:46 henning Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.100 2002/10/14 12:58:28 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -462,7 +462,7 @@ print_binat(struct pf_binat *b)
printf("proto %u ", b->proto);
}
printf("from ");
- print_addr(&b->saddr, NULL, b->af);
+ print_addr(&b->saddr, &b->smask, b->af);
printf(" ");
printf("to ");
if (!PF_AZERO(&b->daddr.addr, b->af) || !PF_AZERO(&b->dmask, b->af)) {
@@ -474,7 +474,7 @@ print_binat(struct pf_binat *b)
printf("any ");
if (!b->no) {
printf("-> ");
- print_addr(&b->raddr, NULL, b->af);
+ print_addr(&b->raddr, &b->rmask, b->af);
}
printf("\n");
}
diff --git a/sys/net/pf.c b/sys/net/pf.c
index a0359e45d18..488fc41d91f 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.254 2002/10/08 05:12:08 kjc Exp $ */
+/* $OpenBSD: pf.c,v 1.255 2002/10/14 12:58:27 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -194,7 +194,8 @@ struct pf_nat *pf_get_nat(struct ifnet *, u_int8_t,
struct pf_addr *, u_int16_t,
struct pf_addr *, u_int16_t, int);
struct pf_binat *pf_get_binat(int, struct ifnet *, u_int8_t,
- struct pf_addr *, struct pf_addr *, int);
+ struct pf_addr *, struct pf_addr *,
+ struct pf_addr *, int);
struct pf_rdr *pf_get_rdr(struct ifnet *, u_int8_t,
struct pf_addr *, struct pf_addr *, u_int16_t, int);
int pf_test_tcp(struct pf_rule **, int, struct ifnet *,
@@ -221,6 +222,10 @@ int pf_test_state_other(struct pf_state **, int,
void *pf_pull_hdr(struct mbuf *, int, void *, int,
u_short *, u_short *, int);
void pf_calc_skip_steps(struct pf_rulequeue *);
+#ifdef INET6
+void pf_poolmask(struct pf_addr *, struct pf_addr*,
+ struct pf_addr *, struct pf_addr *, u_int8_t);
+#endif /* INET6 */
int pf_get_sport(u_int8_t, u_int8_t,
struct pf_addr *, struct pf_addr *,
u_int16_t, u_int16_t *, u_int16_t, u_int16_t);
@@ -446,12 +451,16 @@ pf_compare_binats(struct pf_binat *a, struct pf_binat *b)
return (1);
if (PF_ANEQ(&a->saddr.addr, &b->saddr.addr, a->af))
return (1);
+ if (PF_ANEQ(&a->smask, &b->smask, a->af))
+ return (1);
if (PF_ANEQ(&a->daddr.addr, &b->daddr.addr, a->af))
return (1);
if (PF_ANEQ(&a->dmask, &b->dmask, a->af))
return (1);
if (PF_ANEQ(&a->raddr.addr, &b->raddr.addr, a->af))
return (1);
+ if (PF_ANEQ(&a->rmask, &b->rmask, a->af))
+ return (1);
if (strcmp(a->ifname, b->ifname))
return (1);
return (0);
@@ -1362,6 +1371,32 @@ pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
return (pf_match(op, a1, a2, g));
}
+#ifdef INET6
+void
+pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr,
+ struct pf_addr *rmask, struct pf_addr *saddr, u_int8_t af)
+{
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
+ ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
+ break;
+#endif /* INET */
+ case AF_INET6:
+ naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
+ ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
+ naddr->addr32[1] = (raddr->addr32[1] & rmask->addr32[1]) |
+ ((rmask->addr32[1] ^ 0xffffffff ) & saddr->addr32[1]);
+ naddr->addr32[2] = (raddr->addr32[2] & rmask->addr32[2]) |
+ ((rmask->addr32[2] ^ 0xffffffff ) & saddr->addr32[2]);
+ naddr->addr32[3] = (raddr->addr32[3] & rmask->addr32[3]) |
+ ((rmask->addr32[3] ^ 0xffffffff ) & saddr->addr32[3]);
+ break;
+ }
+}
+#endif /* INET6 */
+
int
pf_get_sport(u_int8_t af, u_int8_t proto,
struct pf_addr *daddr, struct pf_addr *raddr,
@@ -1465,12 +1500,9 @@ pf_get_nat(struct ifnet *ifp, u_int8_t proto, struct pf_addr *saddr,
struct pf_binat *
pf_get_binat(int direction, struct ifnet *ifp, u_int8_t proto,
- struct pf_addr *saddr, struct pf_addr *daddr, int af)
+ struct pf_addr *saddr, struct pf_addr *daddr, struct pf_addr *naddr, int af)
{
struct pf_binat *b, *bm = NULL;
- struct pf_addr fullmask;
-
- memset(&fullmask, 0xff, sizeof(fullmask));
b = TAILQ_FIRST(pf_binats_active);
while (b && bm == NULL) {
@@ -1479,7 +1511,7 @@ pf_get_binat(int direction, struct ifnet *ifp, u_int8_t proto,
(!b->af || b->af == af) &&
(b->saddr.addr_dyn == NULL ||
!b->saddr.addr_dyn->undefined) &&
- PF_MATCHA(0, &b->saddr.addr, &fullmask, saddr, af) &&
+ PF_MATCHA(0, &b->saddr.addr, &b->smask, saddr, af) &&
(b->daddr.addr_dyn == NULL ||
!b->daddr.addr_dyn->undefined) &&
PF_MATCHA(b->dnot, &b->daddr.addr, &b->dmask, daddr, af))
@@ -1489,7 +1521,7 @@ pf_get_binat(int direction, struct ifnet *ifp, u_int8_t proto,
(!b->af || b->af == af) &&
(b->raddr.addr_dyn == NULL ||
!b->raddr.addr_dyn->undefined) &&
- PF_MATCHA(0, &b->raddr.addr, &fullmask, saddr, af) &&
+ PF_MATCHA(0, &b->raddr.addr, &b->rmask, saddr, af) &&
(b->daddr.addr_dyn == NULL ||
!b->daddr.addr_dyn->undefined) &&
PF_MATCHA(b->dnot, &b->daddr.addr, &b->dmask, daddr, af))
@@ -1497,14 +1529,29 @@ pf_get_binat(int direction, struct ifnet *ifp, u_int8_t proto,
else
b = TAILQ_NEXT(b, entries);
}
- if (bm && bm->no)
- return (NULL);
- if (bm && direction == PF_OUT && bm->raddr.addr_dyn != NULL &&
- bm->raddr.addr_dyn->undefined)
- return (NULL);
- if (bm && direction == PF_IN && bm->saddr.addr_dyn != NULL &&
- bm->saddr.addr_dyn->undefined)
- return (NULL);
+ if (bm) {
+ if (bm->no)
+ return (NULL);
+ switch (direction) {
+ case PF_OUT:
+ if (bm->raddr.addr_dyn != NULL &&
+ bm->raddr.addr_dyn->undefined)
+ return (NULL);
+ else
+ PF_POOLMASK(naddr, &bm->raddr.addr,
+ &bm->rmask, saddr, af);
+ break;
+ case PF_IN:
+ if (bm->saddr.addr_dyn != NULL &&
+ bm->saddr.addr_dyn->undefined)
+ return (NULL);
+ else
+ PF_POOLMASK(naddr, &bm->saddr.addr,
+ &bm->smask, saddr, af);
+ break;
+ }
+ }
+
return (bm);
}
@@ -1609,7 +1656,7 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct pf_nat *nat = NULL;
struct pf_binat *binat = NULL;
struct pf_rdr *rdr = NULL;
- struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr, naddr;
struct tcphdr *th = pd->hdr.tcp;
u_int16_t bport, nport = 0, af = pd->af;
int lookup = -1;
@@ -1624,11 +1671,11 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT */
if ((binat = pf_get_binat(PF_OUT, ifp, IPPROTO_TCP,
- saddr, daddr, af)) != NULL) {
+ saddr, daddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, saddr, af);
bport = th->th_sport;
pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
- &th->th_sum, &binat->raddr.addr, th->th_sport, 0, af);
+ &th->th_sum, &naddr, th->th_sport, 0, af);
rewrite++;
}
/* check outgoing packet for NAT */
@@ -1669,11 +1716,11 @@ pf_test_tcp(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
/* check incoming packet for BINAT */
else if ((binat = pf_get_binat(PF_IN, ifp, IPPROTO_TCP,
- daddr, saddr, af)) != NULL) {
+ daddr, saddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, daddr, af);
bport = th->th_dport;
pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
- &th->th_sum, &binat->saddr.addr, th->th_dport, 0, af);
+ &th->th_sum, &naddr, th->th_dport, 0, af);
rewrite++;
}
}
@@ -1875,7 +1922,7 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct pf_nat *nat = NULL;
struct pf_binat *binat = NULL;
struct pf_rdr *rdr = NULL;
- struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr, naddr;
struct udphdr *uh = pd->hdr.udp;
u_int16_t bport, nport = 0, af = pd->af;
int lookup = -1;
@@ -1890,11 +1937,11 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT */
if ((binat = pf_get_binat(PF_OUT, ifp, IPPROTO_UDP,
- saddr, daddr, af)) != NULL) {
+ saddr, daddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, saddr, af);
bport = uh->uh_sport;
pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
- &uh->uh_sum, &binat->raddr.addr, uh->uh_sport, 1, af);
+ &uh->uh_sum, &naddr, uh->uh_sport, 1, af);
rewrite++;
}
/* check outgoing packet for NAT */
@@ -1936,11 +1983,11 @@ pf_test_udp(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
/* check incoming packet for BINAT */
else if ((binat = pf_get_binat(PF_IN, ifp, IPPROTO_UDP,
- daddr, saddr, af)) != NULL) {
+ daddr, saddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, daddr, af);
bport = uh->uh_dport;
pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
- &uh->uh_sum, &binat->saddr.addr, uh->uh_dport, 1, af);
+ &uh->uh_sum, &naddr, uh->uh_dport, 1, af);
rewrite++;
}
}
@@ -2118,7 +2165,7 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct pf_nat *nat = NULL;
struct pf_binat *binat = NULL;
struct pf_rdr *rdr = NULL;
- struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr, naddr;
struct pf_rule *r;
u_short reason;
u_int16_t icmpid, af = pd->af;
@@ -2163,19 +2210,19 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT */
if ((binat = pf_get_binat(PF_OUT, ifp, IPPROTO_ICMP,
- saddr, daddr, af)) != NULL) {
+ saddr, daddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, saddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
- binat->raddr.addr.v4.s_addr, 0);
+ naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
- &binat->raddr.addr, 0);
+ &naddr, 0);
rewrite++;
break;
#endif /* INET6 */
@@ -2224,19 +2271,19 @@ pf_test_icmp(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
/* check incoming packet for BINAT */
else if ((binat = pf_get_binat(PF_IN, ifp, IPPROTO_ICMP,
- daddr, saddr, af)) != NULL) {
+ daddr, saddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, daddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&daddr->v4.s_addr,
- pd->ip_sum, binat->saddr.addr.v4.s_addr, 0);
+ pd->ip_sum, naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
- &binat->saddr.addr, 0);
+ &naddr, 0);
rewrite++;
break;
#endif /* INET6 */
@@ -2383,7 +2430,7 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
struct pf_nat *nat = NULL;
struct pf_binat *binat = NULL;
struct pf_rdr *rdr = NULL;
- struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst, baddr, naddr;
u_int8_t af = pd->af;
u_short reason;
@@ -2393,18 +2440,18 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
if (direction == PF_OUT) {
/* check outgoing packet for BINAT */
if ((binat = pf_get_binat(PF_OUT, ifp, pd->proto,
- saddr, daddr, af)) != NULL) {
+ saddr, daddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, saddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
- binat->raddr.addr.v4.s_addr, 0);
+ naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- PF_ACPY(saddr, &binat->raddr.addr, af);
+ PF_ACPY(saddr, &naddr, af);
break;
#endif /* INET6 */
}
@@ -2448,18 +2495,18 @@ pf_test_other(struct pf_rule **rm, int direction, struct ifnet *ifp,
}
/* check incoming packet for BINAT */
else if ((binat = pf_get_binat(PF_IN, ifp, pd->proto,
- daddr, saddr, af)) != NULL) {
+ daddr, saddr, &naddr, af)) != NULL) {
PF_ACPY(&baddr, daddr, af);
switch (af) {
#ifdef INET
case AF_INET:
pf_change_a(&daddr->v4.s_addr,
- pd->ip_sum, binat->saddr.addr.v4.s_addr, 0);
+ pd->ip_sum, naddr.v4.s_addr, 0);
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- PF_ACPY(daddr, &binat->saddr.addr, af);
+ PF_ACPY(daddr, &naddr, af);
break;
#endif /* INET6 */
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index e35ff183e45..63593bd7cc0 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.97 2002/10/10 12:29:33 mickey Exp $ */
+/* $OpenBSD: pfvar.h,v 1.98 2002/10/14 12:58:28 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -143,6 +143,9 @@ struct pf_addr_dyn {
#define PF_ACPY(a, b, f) \
pf_addrcpy(a, b, f)
+#define PF_POOLMASK(a, b, c, d, f) \
+ pf_poolmask(a, b, c, d, f)
+
#else
/* Just IPv6 */
@@ -172,6 +175,9 @@ struct pf_addr_dyn {
#define PF_ACPY(a, b, f) \
pf_addrcpy(a, b, f)
+#define PF_POOLMASK(a, b, c, d, f) \
+ pf_poolmask(a, b, c, d, f)
+
#else
/* Just IPv4 */
@@ -192,6 +198,11 @@ struct pf_addr_dyn {
#define PF_ACPY(a, b, f) \
(a)->v4.s_addr = (b)->v4.s_addr
+#define PF_POOLMASK(a, b, c, d, f) \
+ do { \
+ (a)->addr32[0] = ((b)->addr32[0] & (c)->addr32[0]) | \
+ (((c)->addr32[0] ^ 0xffffffff ) & (d)->addr32[0]); \
+ } while (0)
#endif /* PF_INET_ONLY */
#endif /* PF_INET6_ONLY */
@@ -360,7 +371,9 @@ struct pf_binat {
struct pf_addr_wrap saddr;
struct pf_addr_wrap daddr;
struct pf_addr_wrap raddr;
+ struct pf_addr smask;
struct pf_addr dmask;
+ struct pf_addr rmask;
u_int8_t af;
u_int8_t proto;
u_int8_t dnot;