diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 2005-05-28 01:07:53 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 2005-05-28 01:07:53 +0000 |
commit | e045c7e94d280d0855ae416988e6bf0097b6c6f0 (patch) | |
tree | 8c342f99be4c3f0dacd64c19be44c13a4542de27 /usr.sbin/sasyncd | |
parent | a3a9273fb166b3cf84b6f05ff835fb809181d0e2 (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.y | 53 | ||||
-rw-r--r-- | usr.sbin/sasyncd/pfkey.c | 115 | ||||
-rw-r--r-- | usr.sbin/sasyncd/sasyncd.conf.5 | 9 | ||||
-rw-r--r-- | usr.sbin/sasyncd/sasyncd.h | 16 |
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" |