-/* $OpenBSD: parse.y,v 1.642 2014/11/20 05:51:20 jsg Exp $ */
+/* $OpenBSD: parse.y,v 1.643 2014/12/19 13:04:07 reyk Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
DYNIF_MULTIADDR($8.route.host->addr)))
r.route.opts |= PF_POOL_ROUNDROBIN;
if ($8.route.host->next != NULL) {
- if (((r.route.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) &&
- ((r.route.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_LEASTSTATES)) {
- yyerror("r.route.opts must "
- "be PF_POOL_ROUNDROBIN "
- "or PF_POOL_LEASTSTATES");
+ if (!PF_POOL_DYNTYPE(r.route.opts)) {
+ yyerror("address pool option "
+ "not supported by type");
YYERROR;
}
}
hprev = h; /* in case we need to conver to a table */
} else { /* multiple hosts */
if (rs->pool_opts.type &&
- (rs->pool_opts.type != PF_POOL_ROUNDROBIN) &&
- (rs->pool_opts.type != PF_POOL_LEASTSTATES)) {
- yyerror("only round-robin or "
- "least-states valid for multiple "
+ !PF_POOL_DYNTYPE(rs->pool_opts.type)) {
+ yyerror("pool type is not valid for multiple "
"translation or routing addresses");
return (1);
}
}
rpool->opts = rs->pool_opts.type;
- if (rpool->addr.type == PF_ADDR_TABLE ||
- DYNIF_MULTIADDR(rpool->addr))
+ if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE &&
+ (rpool->addr.type == PF_ADDR_TABLE ||
+ DYNIF_MULTIADDR(rpool->addr)))
rpool->opts |= PF_POOL_ROUNDROBIN;
- if (((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) &&
- ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_LEASTSTATES) &&
- (disallow_table(rs->rdr->host, "tables are only supported "
- "in round-robin or least-states address pools") ||
- disallow_alias(rs->rdr->host, "interface (%s) is only supported "
- "in round-robin or least-states address pools")))
+ if (!PF_POOL_DYNTYPE(rpool->opts) &&
+ (disallow_table(rs->rdr->host,
+ "tables are not supported by pool type") ||
+ disallow_alias(rs->rdr->host,
+ "interface (%s) is not supported by pool type")))
return (1);
if (rs->pool_opts.key != NULL)
-.\" $OpenBSD: pf.conf.5,v 1.539 2014/10/23 20:38:37 kspillner Exp $
+.\" $OpenBSD: pf.conf.5,v 1.540 2014/12/19 13:04:08 reyk Exp $
.\"
.\" Copyright (c) 2002, Daniel Hartmeier
.\" Copyright (c) 2003 - 2013 Henning Brauer <henning@openbsd.org>
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: October 23 2014 $
+.Dd $Mdocdate: December 19 2014 $
.Dt PF.CONF 5
.Os
.Sh NAME
.El
.Pp
When more than one redirection address or a table is specified,
-.Ar round-robin
-and
-.Ar least-states
-are the only permitted pool types.
+.Ar bitmask
+is not permitted as a pool type.
.Ss Routing
If a packet matches a rule with one of the following route options set,
the packet filter will route the packet according to the type of route option.
.Ar nat-to
and
.Ar rdr-to
-and in the routing options of filter rules, but only for
-.Ar least-states
-and
-.Ar round-robin
+and in the routing options of filter rules, but not for
+.Ar bitmask
pools.
.Pp
Tables can be defined with any of the following
-/* $OpenBSD: pf_lb.c,v 1.38 2014/12/19 12:31:03 mcbride Exp $ */
+/* $OpenBSD: pf_lb.c,v 1.39 2014/12/19 13:04:08 reyk Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
* Global variables
*/
-void pf_hash(struct pf_addr *, struct pf_addr *,
+u_int64_t pf_hash(struct pf_addr *, struct pf_addr *,
struct pf_poolhashkey *, sa_family_t);
int pf_get_sport(struct pf_pdesc *, struct pf_rule *,
struct pf_addr *, u_int16_t *, u_int16_t,
struct pf_src_node **, struct pf_pool *,
enum pf_sn_types);
-void
+u_int64_t
pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
struct pf_poolhashkey *key, sa_family_t af)
{
+ uint64_t res = 0;
#ifdef INET6
union {
uint64_t hash64;
switch (af) {
#ifdef INET
case AF_INET:
- hash->addr32[0] = SipHash24((SIPHASH_KEY *)key,
+ res = SipHash24((SIPHASH_KEY *)key,
&inaddr->addr32[0], sizeof(inaddr->addr32[0]));
+ hash->addr32[0] = res;
break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
- h.hash64 = SipHash24((SIPHASH_KEY *)key, &inaddr->addr32[0],
+ res = SipHash24((SIPHASH_KEY *)key, &inaddr->addr32[0],
4 * sizeof(inaddr->addr32[0]));
+ h.hash64 = res;
hash->addr32[0] = h.hash32[0];
hash->addr32[1] = h.hash32[1];
/*
break;
#endif /* INET6 */
}
+ return (res);
}
int
u_int16_t weight;
u_int64_t load;
u_int64_t cload;
+ u_int64_t hashidx;
+ int cnt;
if (sns[type] == NULL && rpool->opts & PF_POOL_STICKYADDR &&
(rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE &&
#ifdef INET
case AF_INET:
if (rpool->addr.p.dyn->pfid_acnt4 < 1 &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_LEASTSTATES))
+ !PF_POOL_DYNTYPE(rpool->opts))
return (1);
raddr = &rpool->addr.p.dyn->pfid_addr4;
rmask = &rpool->addr.p.dyn->pfid_mask4;
#ifdef INET6
case AF_INET6:
if (rpool->addr.p.dyn->pfid_acnt6 < 1 &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) &&
- ((rpool->opts & PF_POOL_TYPEMASK) !=
- PF_POOL_LEASTSTATES))
+ !PF_POOL_DYNTYPE(rpool->opts))
return (1);
raddr = &rpool->addr.p.dyn->pfid_addr6;
rmask = &rpool->addr.p.dyn->pfid_mask6;
#endif /* INET6 */
}
} else if (rpool->addr.type == PF_ADDR_TABLE) {
- if (((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN) &&
- ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_LEASTSTATES))
+ if (!PF_POOL_DYNTYPE(rpool->opts))
return (1); /* unsupported */
} else {
raddr = &rpool->addr.v.a.addr;
PF_POOLMASK(naddr, raddr, rmask, saddr, af);
break;
case PF_POOL_RANDOM:
- if (init_addr != NULL && PF_AZERO(init_addr, af)) {
+ if (rpool->addr.type == PF_ADDR_TABLE) {
+ cnt = rpool->addr.p.tbl->pfrkt_cnt;
+ rpool->tblidx = (int)arc4random_uniform(cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else if (rpool->addr.type == PF_ADDR_DYNIFTL) {
+ cnt = rpool->addr.p.dyn->pfid_kt->pfrkt_cnt;
+ rpool->tblidx = (int)arc4random_uniform(cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else if (init_addr != NULL && PF_AZERO(init_addr, af)) {
switch (af) {
#ifdef INET
case AF_INET:
}
break;
case PF_POOL_SRCHASH:
- pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
- PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
+ hashidx =
+ pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
+ if (rpool->addr.type == PF_ADDR_TABLE) {
+ cnt = rpool->addr.p.tbl->pfrkt_cnt;
+ rpool->tblidx = (int)(hashidx % cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else if (rpool->addr.type == PF_ADDR_DYNIFTL) {
+ cnt = rpool->addr.p.dyn->pfid_kt->pfrkt_cnt;
+ rpool->tblidx = (int)(hashidx % cnt);
+ memset(&rpool->counter, 0, sizeof(rpool->counter));
+ if (pfr_pool_get(rpool, &raddr, &rmask, af))
+ return (1);
+ PF_ACPY(naddr, &rpool->counter, af);
+ } else {
+ PF_POOLMASK(naddr, raddr, rmask,
+ (struct pf_addr *)&hash, af);
+ }
break;
case PF_POOL_ROUNDROBIN:
if (rpool->addr.type == PF_ADDR_TABLE ||