diff options
author | Hakan Olsson <ho@cvs.openbsd.org> | 2005-03-30 18:44:50 +0000 |
---|---|---|
committer | Hakan Olsson <ho@cvs.openbsd.org> | 2005-03-30 18:44:50 +0000 |
commit | 1e42720c7d8b17ab1489a1fac2f86ba12229ccf1 (patch) | |
tree | a6dc00bfa0b4344cecdbd733263eee02a88b53ec /usr.sbin/sasyncd/carp.c | |
parent | c2c1ef90c70e5f9accfa8a65b07648fae651be03 (diff) |
Move sasyncd(8), for IPsec SA synchronization, in-tree. Work in progress.
deraadt@ ok.
Diffstat (limited to 'usr.sbin/sasyncd/carp.c')
-rw-r--r-- | usr.sbin/sasyncd/carp.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/usr.sbin/sasyncd/carp.c b/usr.sbin/sasyncd/carp.c new file mode 100644 index 00000000000..06391e52499 --- /dev/null +++ b/usr.sbin/sasyncd/carp.c @@ -0,0 +1,176 @@ +/* $OpenBSD: carp.c,v 1.1 2005/03/30 18:44:49 ho Exp $ */ + +/* + * Copyright (c) 2005 Håkan Olsson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This code was written under funding by Multicom Security AB. + */ + + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/ip_carp.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "sasyncd.h" + +/* For some reason, ip_carp.h does not define this. */ +#define CARP_INIT 0 +#define CARP_BACKUP 1 +#define CARP_MASTER 2 + +/* Returns 1 for the CARP MASTER, 0 for BACKUP/INIT, -1 on error. */ +static enum RUNSTATE +carp_get_state(char *ifname) +{ + struct ifreq ifr; + struct carpreq carp; + int s, saved_errno; + char *state; + + if (!ifname || !*ifname) { + errno = ENOENT; + return FAIL; + } + + memset(&ifr, 0, sizeof ifr); + strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name); + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + return FAIL; + + ifr.ifr_data = (caddr_t)&carp; + if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) { + saved_errno = errno; + close(s); + errno = saved_errno; + return FAIL; + } + close(s); + + switch (carp.carpr_state) { + case CARP_INIT: + state = "INIT"; + break; + + case CARP_BACKUP: + state = "BACKUP"; + break; + + case CARP_MASTER: + state = "MASTER"; + break; + + default: + state = "<unknown>"; + break; + } + + log_msg(4, "carp_get_state: %s vhid %u state %s(%d)", ifname, + carp.carpr_vhid, state, carp.carpr_state); + + if (carp.carpr_vhid > 0) + return carp.carpr_state == CARP_MASTER ? MASTER : SLAVE; + else + return FAIL; +} + +void +carp_check_state(void) +{ + enum RUNSTATE current_state = carp_get_state(cfgstate.carp_ifname); + static char *carpstate[] = CARPSTATES; + + if (current_state < 0 || current_state > FAIL) { + log_err("carp_state_tracker: invalid result on interface " + "%s, abort", cfgstate.carp_ifname); + cfgstate.runstate = FAIL; + return; + } + + if (current_state != cfgstate.runstate) { + log_msg(1, "carp_state_tracker: switching state to %s", + carpstate[current_state]); + cfgstate.runstate = current_state; + if (current_state == MASTER) + pfkey_set_promisc(); + net_ctl_update_state(); + } +} + +static void +carp_state_tracker(void *v_arg) +{ + static int failures = 0; + u_int32_t next_check; + + carp_check_state(); + + if (cfgstate.runstate == FAIL) + if (++failures < 3) + log_err("carp_state_tracker"); + + if (failures > 5) + next_check = 600; + else + next_check = cfgstate.carp_check_interval + failures * 10; + + if (timer_add("carp_state_tracker", next_check, carp_state_tracker, + NULL)) + log_msg(0, "carp_state_tracker: failed to renew event"); + return; +} + +/* Initialize the CARP state tracker. */ +int +carp_init(void) +{ + enum RUNSTATE initial_state; + + if (cfgstate.lockedstate != INIT) { + cfgstate.runstate = cfgstate.lockedstate; + log_msg(1, "carp_init: locking runstate to %s", + cfgstate.runstate == MASTER ? "MASTER" : "SLAVE"); + return 0; + } + + initial_state = carp_get_state(cfgstate.carp_ifname); + if (initial_state == FAIL) { + fprintf(stderr, "Failed to check interface \"%s\".\n", + cfgstate.carp_ifname); + fprintf(stderr, "Correct or manually select runstate.\n"); + return -1; + } + + return timer_add("carp_state_tracker", 0, carp_state_tracker, NULL); +} |