diff options
-rw-r--r-- | sbin/pfctl/parse.y | 31 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 6 | ||||
-rw-r--r-- | sys/net/pf.c | 127 | ||||
-rw-r--r-- | sys/net/pfvar.h | 15 |
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; |