summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd/pfe_filter.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2008-05-07 01:49:30 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2008-05-07 01:49:30 +0000
commit53aa0d5e219b0598bf21997accb68bedbb8cae09 (patch)
treef5d06354c1e569d10b200e817b713e17b495923b /usr.sbin/relayd/pfe_filter.c
parent334c0302bd84b6762f5ed2169e9186487efcf155 (diff)
add an alternative "route to" mode to relayd redirections which maps
to pf route-to instead of the default rdr. it is a first steps towards support for "direct server return" (dsr), an asynchronous mode where the load balanced servers send the replies to a different gateway like a l3 switch/router to handle higher amounts of return traffic. because the state handling in pf isn't optimal for this case yet, it just sees half of the TCP connection, the sessions are forced to time out after fixed number of seconds. discussed with many, thought about in the onsen
Diffstat (limited to 'usr.sbin/relayd/pfe_filter.c')
-rw-r--r--usr.sbin/relayd/pfe_filter.c73
1 files changed, 54 insertions, 19 deletions
diff --git a/usr.sbin/relayd/pfe_filter.c b/usr.sbin/relayd/pfe_filter.c
index 514a78140f9..81d0444510d 100644
--- a/usr.sbin/relayd/pfe_filter.c
+++ b/usr.sbin/relayd/pfe_filter.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfe_filter.c,v 1.25 2008/05/06 11:52:49 reyk Exp $ */
+/* $OpenBSD: pfe_filter.c,v 1.26 2008/05/07 01:49:29 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -41,8 +41,9 @@
struct pfdata {
int dev;
struct pf_anchor *anchor;
- struct pfioc_trans pft;
- struct pfioc_trans_e pfte;
+ struct pfioc_trans pft[PF_RULESET_MAX];
+ struct pfioc_trans_e pfte[PF_RULESET_MAX];
+ u_int8_t pfused;
};
int transaction_init(struct relayd *, const char *);
@@ -273,24 +274,35 @@ flush_table(struct relayd *env, struct rdr *rdr)
int
transaction_init(struct relayd *env, const char *anchor)
{
- env->sc_pf->pft.size = 1;
- env->sc_pf->pft.esize = sizeof env->sc_pf->pfte;
- env->sc_pf->pft.array = &env->sc_pf->pfte;
-
- memset(&env->sc_pf->pfte, 0, sizeof env->sc_pf->pfte);
- (void)strlcpy(env->sc_pf->pfte.anchor, anchor, PF_ANCHOR_NAME_SIZE);
- env->sc_pf->pfte.rs_num = PF_RULESET_RDR;
-
- if (ioctl(env->sc_pf->dev, DIOCXBEGIN, &env->sc_pf->pft) == -1)
- return (-1);
+ int i;
+
+ for (i = 0; i < PF_RULESET_MAX; i++) {
+ env->sc_pf->pft[i].size = 1;
+ env->sc_pf->pft[i].esize = sizeof(env->sc_pf->pfte[i]);
+ env->sc_pf->pft[i].array = &env->sc_pf->pfte[i];
+
+ bzero(&env->sc_pf->pfte[i], sizeof(env->sc_pf->pfte[i]));
+ (void)strlcpy(env->sc_pf->pfte[i].anchor,
+ anchor, PF_ANCHOR_NAME_SIZE);
+ env->sc_pf->pfte[i].rs_num = i;
+
+ if (ioctl(env->sc_pf->dev, DIOCXBEGIN,
+ &env->sc_pf->pft[i]) == -1)
+ return (-1);
+ }
return (0);
}
int
transaction_commit(struct relayd *env)
{
- if (ioctl(env->sc_pf->dev, DIOCXCOMMIT, &env->sc_pf->pft) == -1)
- return (-1);
+ int i;
+
+ for (i = 0; i < PF_RULESET_MAX; i++) {
+ if (ioctl(env->sc_pf->dev, DIOCXCOMMIT,
+ &env->sc_pf->pft[i]) == -1)
+ return (-1);
+ }
return (0);
}
@@ -303,6 +315,8 @@ sync_ruleset(struct relayd *env, struct rdr *rdr, int enable)
struct sockaddr_in6 *sain6;
struct address *address;
char anchor[PF_ANCHOR_NAME_SIZE];
+ int rs;
+ struct table *t = rdr->table;
if (!(env->sc_flags & F_NEEDPF))
return;
@@ -333,7 +347,25 @@ sync_ruleset(struct relayd *env, struct rdr *rdr, int enable)
memset(&pio, 0, sizeof(pio));
(void)strlcpy(rio.anchor, anchor, sizeof(rio.anchor));
- rio.ticket = env->sc_pf->pfte.ticket;
+ if ((t->conf.flags & F_ROUTE) == 0) {
+ /* traditional redirection in the rdr-anchor */
+ rs = PF_RULESET_RDR;
+ rio.rule.action = PF_RDR;
+ } else {
+ /* re-route with pf for DSR (direct server return) */
+ rs = PF_RULESET_FILTER;
+ rio.rule.action = PF_PASS;
+ rio.rule.rt = PF_ROUTETO;
+ rio.rule.direction = PF_IN;
+ rio.rule.quick = 1; /* force first match */
+
+ /* XXX This should use a loose pf state handling */
+ rio.rule.keep_state = PF_STATE_NORMAL;
+ rio.rule.timeout[PFTM_TCP_OPENING] =
+ rdr->conf.timeout.tv_sec;
+ }
+
+ rio.ticket = env->sc_pf->pfte[rs].ticket;
if (ioctl(env->sc_pf->dev, DIOCBEGINADDRS, &pio) == -1)
fatal("sync_ruleset: cannot initialise address pool");
@@ -345,7 +377,7 @@ sync_ruleset(struct relayd *env, struct rdr *rdr, int enable)
rio.rule.dst.port_op = PF_OP_EQ;
rio.rule.dst.port[0] = address->port;
rio.rule.rtableid = -1; /* stay in the main routing table */
- rio.rule.action = PF_RDR;
+
if (strlen(rdr->conf.tag))
(void)strlcpy(rio.rule.tagname, rdr->conf.tag,
sizeof(rio.rule.tagname));
@@ -359,7 +391,6 @@ sync_ruleset(struct relayd *env, struct rdr *rdr, int enable)
rio.rule.dst.addr.v.a.addr.addr32[0] =
sain->sin_addr.s_addr;
rio.rule.dst.addr.v.a.mask.addr32[0] = 0xffffffff;
-
} else {
sain6 = (struct sockaddr_in6 *)&address->ss;
@@ -370,6 +401,9 @@ sync_ruleset(struct relayd *env, struct rdr *rdr, int enable)
}
pio.addr.addr.type = PF_ADDR_TABLE;
+ if (strlen(t->conf.ifname))
+ (void)strlcpy(pio.addr.ifname, t->conf.ifname,
+ sizeof(pio.addr.ifname));
if (strlcpy(pio.addr.addr.v.tblname, rdr->conf.name,
sizeof(pio.addr.addr.v.tblname)) >=
sizeof(pio.addr.addr.v.tblname))
@@ -385,7 +419,8 @@ sync_ruleset(struct relayd *env, struct rdr *rdr, int enable)
if (ioctl(env->sc_pf->dev, DIOCADDRULE, &rio) == -1)
fatal("cannot add rule");
- log_debug("sync_ruleset: rule added");
+ log_debug("sync_ruleset: rule added to %sanchor \"%s\"",
+ rdr->table->conf.flags & F_ROUTE ? "" : "rdr-", anchor);
}
if (transaction_commit(env) == -1)
log_warn("sync_ruleset: add rules transaction failed");