summaryrefslogtreecommitdiff
path: root/usr.sbin/sasyncd
diff options
context:
space:
mode:
authorHakan Olsson <ho@cvs.openbsd.org>2005-05-28 01:07:53 +0000
committerHakan Olsson <ho@cvs.openbsd.org>2005-05-28 01:07:53 +0000
commite045c7e94d280d0855ae416988e6bf0097b6c6f0 (patch)
tree8c342f99be4c3f0dacd64c19be44c13a4542de27 /usr.sbin/sasyncd
parenta3a9273fb166b3cf84b6f05ff835fb809181d0e2 (diff)
Optionally prevent syncing failover node-node SA/SPD info (master side).
Diffstat (limited to 'usr.sbin/sasyncd')
-rw-r--r--usr.sbin/sasyncd/conf.y53
-rw-r--r--usr.sbin/sasyncd/pfkey.c115
-rw-r--r--usr.sbin/sasyncd/sasyncd.conf.59
-rw-r--r--usr.sbin/sasyncd/sasyncd.h16
4 files changed, 161 insertions, 32 deletions
diff --git a/usr.sbin/sasyncd/conf.y b/usr.sbin/sasyncd/conf.y
index f824ecdb894..44dca2cf9e5 100644
--- a/usr.sbin/sasyncd/conf.y
+++ b/usr.sbin/sasyncd/conf.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: conf.y,v 1.4 2005/05/26 19:19:51 ho Exp $ */
+/* $OpenBSD: conf.y,v 1.5 2005/05/28 01:07:52 ho Exp $ */
/*
* Copyright (c) 2005 Håkan Olsson. All rights reserved.
@@ -59,6 +59,7 @@ void yyerror(const char *);
%token MODE CARP INTERFACE INTERVAL LISTEN ON PORT PEER SHAREDKEY
%token Y_SLAVE Y_MASTER INET INET6 FLUSHMODE STARTUP NEVER SYNC
+%token SKIPSLAVE
%token <string> STRING
%token <val> VALUE
%type <val> af port interval mode flushmode
@@ -70,26 +71,39 @@ settings : /* empty */
| settings setting
;
-af : /* empty */ { $$ = AF_UNSPEC; }
- | INET { $$ = AF_INET; }
- | INET6 { $$ = AF_INET6; }
+af : /* empty */ { $$ = AF_UNSPEC; }
+ | INET { $$ = AF_INET; }
+ | INET6 { $$ = AF_INET6; }
;
-port : /* empty */ { $$ = SASYNCD_DEFAULT_PORT; }
- | PORT VALUE { $$ = $2; }
+port : /* empty */ { $$ = SASYNCD_DEFAULT_PORT; }
+ | PORT VALUE { $$ = $2; }
;
-mode : MODE Y_MASTER { $$ = MASTER; }
- | MODE Y_SLAVE { $$ = SLAVE; }
+mode : Y_MASTER { $$ = MASTER; }
+ | Y_SLAVE { $$ = SLAVE; }
;
-interval : /* empty */ { $$ = CARP_DEFAULT_INTERVAL; }
- | INTERVAL VALUE { $$ = $2; }
+modes : SKIPSLAVE
+ {
+ cfgstate.flags |= SKIP_LOCAL_SAS;
+ log_msg(2, "config: not syncing SA to peers");
+ }
+ | mode
+ {
+ const char *m[] = CARPSTATES;
+ cfgstate.lockedstate = $1;
+ log_msg(2, "config: mode set to %s", m[$1]);
+ }
;
-flushmode : STARTUP { $$ = FM_STARTUP; }
- | NEVER { $$ = FM_NEVER; }
- | SYNC { $$ = FM_SYNC; }
+interval : /* empty */ { $$ = CARP_DEFAULT_INTERVAL; }
+ | INTERVAL VALUE { $$ = $2; }
+ ;
+
+flushmode : STARTUP { $$ = FM_STARTUP; }
+ | NEVER { $$ = FM_NEVER; }
+ | SYNC { $$ = FM_SYNC; }
;
setting : CARP INTERFACE STRING interval
@@ -103,8 +117,8 @@ setting : CARP INTERFACE STRING interval
}
| FLUSHMODE flushmode
{
- const char *fm[] = FLUSHMODES;
- cfgstate.flushmode = $2;
+ const char *fm[] = { "STARTUP", "NEVER", "SYNC" };
+ cfgstate.flags |= $2;
log_msg(2, "config: flush mode set to %s", fm[$2]);
}
| PEER STRING
@@ -155,12 +169,7 @@ setting : CARP INTERFACE STRING interval
($4 == AF_INET ? "(IPv4) " : ""),
$5 != SASYNCD_DEFAULT_PORT ? pstr : "");
}
- | mode
- {
- const char *m[] = CARPSTATES;
- cfgstate.lockedstate = $1;
- log_msg(2, "config: mode set to %s", m[$1]);
- }
+ | MODE modes
| SHAREDKEY STRING
{
if (cfgstate.sharedkey)
@@ -203,11 +212,11 @@ match(char *token)
{ "peer", PEER },
{ "port", PORT },
{ "sharedkey", SHAREDKEY },
+ { "skipslave", SKIPSLAVE },
{ "slave", Y_SLAVE },
{ "startup", STARTUP },
{ "sync", SYNC },
};
-
const struct keyword *k;
k = bsearch(token, keywords, sizeof keywords / sizeof keywords[0],
diff --git a/usr.sbin/sasyncd/pfkey.c b/usr.sbin/sasyncd/pfkey.c
index 109d8500ee9..8be59a1f20a 100644
--- a/usr.sbin/sasyncd/pfkey.c
+++ b/usr.sbin/sasyncd/pfkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkey.c,v 1.10 2005/05/27 18:05:27 ho Exp $ */
+/* $OpenBSD: pfkey.c,v 1.11 2005/05/28 01:07:52 ho Exp $ */
/*
* Copyright (c) 2005 Håkan Olsson. All rights reserved.
@@ -137,6 +137,108 @@ pfkey_print_type(struct sadb_msg *msg)
}
}
+static struct sadb_ext *
+pfkey_find_ext(struct sadb_msg *msg, u_int16_t type)
+{
+ struct sadb_ext *ext;
+ u_int8_t *e;
+
+ for (e = (u_int8_t *)msg + sizeof *msg;
+ e < (u_int8_t *)msg + msg->sadb_msg_len * CHUNK;
+ e += ext->sadb_ext_len * CHUNK) {
+ ext = (struct sadb_ext *)e;
+ if (ext->sadb_ext_len == 0)
+ break;
+ if (ext->sadb_ext_type != type)
+ continue;
+ return ext;
+ }
+ return NULL;
+}
+
+/* Return: 0 means ok to sync msg, 1 means to skip it */
+static int
+pfkey_msg_filter(struct sadb_msg *msg)
+{
+ struct sockaddr *src = 0, *dst = 0;
+ struct syncpeer *p;
+ struct sadb_ext *ext;
+ u_int8_t *max;
+
+ switch (msg->sadb_msg_type) {
+ case SADB_ADD:
+ /* No point in syncing LARVAL SAs */
+ if (pfkey_find_ext(msg, SADB_EXT_KEY_ENCRYPT) == 0)
+ return 1;
+ case SADB_DELETE:
+ case SADB_X_ADDFLOW:
+ case SADB_X_DELFLOW:
+ case SADB_EXPIRE:
+ /* Continue below */
+ break;
+ case SADB_FLUSH:
+ if ((cfgstate.flags & FM_MASK) == FM_NEVER)
+ return 1;
+ break;
+ default:
+ return 0;
+ }
+
+ if ((cfgstate.flags & SKIP_LOCAL_SAS) == 0)
+ return 0;
+
+ /* SRC or DST address of this msg must not be one of our peers. */
+ ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_SRC);
+ if (ext)
+ src = (struct sockaddr *)((struct sadb_address *)ext + 1);
+ ext = pfkey_find_ext(msg, SADB_EXT_ADDRESS_DST);
+ if (ext)
+ dst = (struct sockaddr *)((struct sadb_address *)ext + 1);
+ if (!src && !dst)
+ return 0;
+
+ max = (u_int8_t *)msg + msg->sadb_msg_len * CHUNK;
+ if (src && ((u_int8_t *)src + src->sa_len) > max)
+ return 1;
+ if (dst && ((u_int8_t *)dst + dst->sa_len) > max)
+ return 1;
+
+ /* Found SRC or DST, check it against our peers */
+ for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
+ if (p->socket < 0 || p->sa->sa_family !=
+ (src ? src->sa_family : dst->sa_family))
+ continue;
+
+ switch (p->sa->sa_family) {
+ case AF_INET:
+ if (src && memcmp(
+ &((struct sockaddr_in *)p->sa)->sin_addr.s_addr,
+ &((struct sockaddr_in *)src)->sin_addr.s_addr,
+ sizeof(struct in_addr)) == 0)
+ return 1;
+ if (dst && memcmp(
+ &((struct sockaddr_in *)p->sa)->sin_addr.s_addr,
+ &((struct sockaddr_in *)dst)->sin_addr.s_addr,
+ sizeof(struct in_addr)) == 0)
+ return 1;
+ break;
+ case AF_INET6:
+ if (src &&
+ memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr,
+ &((struct sockaddr_in6 *)src)->sin6_addr,
+ sizeof(struct in_addr)) == 0)
+ return 1;
+ if (dst &&
+ memcmp(&((struct sockaddr_in6 *)p->sa)->sin6_addr,
+ &((struct sockaddr_in6 *)dst)->sin6_addr,
+ sizeof(struct in_addr)) == 0)
+ return 1;
+ break;
+ }
+ }
+ return 0;
+}
+
static int
pfkey_handle_message(struct sadb_msg *m)
{
@@ -171,8 +273,7 @@ pfkey_handle_message(struct sadb_msg *m)
return 0;
}
- if (msg->sadb_msg_type == SADB_FLUSH &&
- cfgstate.flushmode == FM_NEVER) {
+ if (pfkey_msg_filter(msg)) {
free(m);
return 0;
}
@@ -359,7 +460,7 @@ pfkey_snapshot(void *v)
}
/* XXX needs moving if snapshot is called more than once per peer */
- if (cfgstate.flushmode == FM_STARTUP)
+ if ((cfgstate.flags & FM_MASK) == FM_STARTUP)
pfkey_send_flush(p);
/* Parse SADB data */
@@ -375,6 +476,9 @@ pfkey_snapshot(void *v)
/* Tweak and send this SA to the peer. */
m->sadb_msg_type = SADB_ADD;
+ if (pfkey_msg_filter(m))
+ continue;
+
/* Allocate msgbuffer, net_queue() will free it. */
sendbuf = (u_int8_t *)malloc(m->sadb_msg_len * CHUNK);
if (sendbuf) {
@@ -402,6 +506,9 @@ pfkey_snapshot(void *v)
/* Tweak msg type. */
m->sadb_msg_type = SADB_X_ADDFLOW;
+ if (pfkey_msg_filter(m))
+ continue;
+
/* Allocate msgbuffer, freed by net_queue(). */
sendbuf = (u_int8_t *)malloc(m->sadb_msg_len * CHUNK);
if (sendbuf) {
diff --git a/usr.sbin/sasyncd/sasyncd.conf.5 b/usr.sbin/sasyncd/sasyncd.conf.5
index 17e16a90b40..ad0e9143efb 100644
--- a/usr.sbin/sasyncd/sasyncd.conf.5
+++ b/usr.sbin/sasyncd/sasyncd.conf.5
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sasyncd.conf.5,v 1.7 2005/05/26 19:40:20 ho Exp $
+.\" $OpenBSD: sasyncd.conf.5,v 1.8 2005/05/28 01:07:52 ho Exp $
.\"
.\" Copyright (c) 2005 Håkan Olsson. All rights reserved.
.\"
@@ -115,6 +115,13 @@ The default is to listen to port 500.
.It Ic mode master | slave
Force the daemon to run as master or slave.
Normally only intended for debugging use.
+.It Ic mode skipslave
+Prevent the daemon from syncing SA or SPD messages where the source or
+destination address is one of the configured peers.
+Intended to permit IPsec
+.Xr pfsync 4
+protection.
+This mode is experimental.
.It Ic peer Ar address
Specify a
.Xr sasyncd 8
diff --git a/usr.sbin/sasyncd/sasyncd.h b/usr.sbin/sasyncd/sasyncd.h
index f99384a9346..c5d5ba6a798 100644
--- a/usr.sbin/sasyncd/sasyncd.h
+++ b/usr.sbin/sasyncd/sasyncd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sasyncd.h,v 1.7 2005/05/26 19:19:51 ho Exp $ */
+/* $OpenBSD: sasyncd.h,v 1.8 2005/05/28 01:07:52 ho Exp $ */
/*
* Copyright (c) 2005 Håkan Olsson. All rights reserved.
@@ -35,9 +35,6 @@
enum RUNSTATE { INIT = 0, SLAVE, MASTER, FAIL };
#define CARPSTATES { "INIT", "SLAVE", "MASTER", "FAIL" }
-enum FLUSHMODE { FM_STARTUP = 0, FM_NEVER, FM_SYNC };
-#define FLUSHMODES { "STARTUP", "NEVER", "SYNC" };
-
struct syncpeer;
struct timeval;
@@ -46,7 +43,7 @@ struct cfgstate {
enum RUNSTATE lockedstate;
int debug;
int verboselevel;
- enum FLUSHMODE flushmode;
+ u_int32_t flags;
char *carp_ifname;
int carp_check_interval;
@@ -62,6 +59,15 @@ struct cfgstate {
LIST_HEAD(, syncpeer) peerlist;
};
+/* flags */
+#define FM_STARTUP 0x0000
+#define FM_NEVER 0x0001
+#define FM_SYNC 0x0002
+#define FM_MASK 0x0003
+
+/* Do not sync SAs to/from our peers. */
+#define SKIP_LOCAL_SAS 0x0004
+
extern struct cfgstate cfgstate;
#define SASYNCD_USER "_isakmpd"