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/net_ctl.c | |
parent | c2c1ef90c70e5f9accfa8a65b07648fae651be03 (diff) |
Move sasyncd(8), for IPsec SA synchronization, in-tree. Work in progress.
deraadt@ ok.
Diffstat (limited to 'usr.sbin/sasyncd/net_ctl.c')
-rw-r--r-- | usr.sbin/sasyncd/net_ctl.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/usr.sbin/sasyncd/net_ctl.c b/usr.sbin/sasyncd/net_ctl.c new file mode 100644 index 00000000000..97cabfa97f4 --- /dev/null +++ b/usr.sbin/sasyncd/net_ctl.c @@ -0,0 +1,197 @@ +/* $OpenBSD: net_ctl.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/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#include "sasyncd.h" +#include "net.h" + +struct ctlmsg { + u_int32_t type; + u_int32_t data; + u_int32_t data2; +}; + +int listen_socket; + +static int +net_ctl_check_state(struct syncpeer *p, enum RUNSTATE nstate) +{ + static char *runstate[] = CARPSTATES; + + if (nstate < INIT || nstate > FAIL) { + log_msg(0, "got bad state %d from peer \"%s\"", nstate, + p->name); + net_ctl_send_error(p, CTL_STATE); + return -1; + } + if (cfgstate.runstate == MASTER && + nstate == MASTER) { + log_msg(0, "got bad state MASTER from peer \"%s\"", + p->name); + net_ctl_send_error(p, CTL_STATE); + return -1; + } + if (p->runstate != nstate) { + p->runstate = nstate; + log_msg(1, "peer \"%s\" state change to %s", p->name, + runstate[nstate]); + } + return 0; +} + +void +net_ctl_handle_msg(struct syncpeer *p, u_int8_t *msg, u_int32_t msglen) +{ + struct ctlmsg *ctl = (struct ctlmsg *)msg; + enum RUNSTATE nstate; + enum CTLTYPE ctype; + static char *ct, *ctltype[] = CTLTYPES; + + if (msglen < sizeof *ctl) { + log_msg(0, "got invalid control message from peer \"%s\"", + p->name); + net_ctl_send_error(p, CTL_UNKNOWN); + return; + } + + switch (ntohl(ctl->type)) { + case CTL_STATE: + log_msg(3, "got CTL_STATE from peer \"%s\"", p->name); + nstate = (enum RUNSTATE)ntohl(ctl->data); + if (net_ctl_check_state(p, nstate) == 0) + net_ctl_send_ack(p, CTL_STATE, cfgstate.runstate); + break; + + case CTL_ERROR: + log_msg(1, "got ERROR from peer \"%s\"", p->name); + + switch (ntohl(ctl->data)) { + case RESERVED: /* PFKEY -- nothing to do here for now */ + break; + + case CTL_STATE: + nstate = cfgstate.runstate; + carp_check_state(); + if (nstate != cfgstate.runstate) + net_ctl_send_state(p); + break; + + case CTL_UNKNOWN: + default: + break; + } + break; + + case CTL_ACK: + ctype = (enum CTLTYPE)ntohl(ctl->data); + if (ctype < RESERVED || ctype > CTL_UNKNOWN) + ct = "<unknown>"; + else + ct = ctltype[ctype]; + log_msg(3, "got %s ACK from peer \"%s\"", ct, p->name); + if (ctype == CTL_STATE) { + nstate = (enum RUNSTATE)ntohl(ctl->data2); + net_ctl_check_state(p, nstate); + } + break; + + case CTL_UNKNOWN: + default: + log_msg(1, "got unknown msg type %u from peer \"%s\"", + ntohl(ctl->type), p->name); + break; + } +} + +static int +net_ctl_send(struct syncpeer *p, u_int32_t type, u_int32_t d, u_int32_t d2) +{ + struct ctlmsg *m = (struct ctlmsg *)malloc(sizeof *m); + + if (!m) { + log_err("malloc(%u)", sizeof *m); + return -1; + } + + memset(m, 0, sizeof *m); + m->type = htonl(type); + m->data = htonl(d); + m->data2 = htonl(d2); + + return net_queue(p, MSG_SYNCCTL, (u_int8_t *)m, 0, sizeof *m); +} + +int +net_ctl_send_ack(struct syncpeer *p, enum CTLTYPE prevtype, u_int32_t code) +{ + return net_ctl_send(p, CTL_ACK, (u_int32_t)prevtype, code); +} + +int +net_ctl_send_state(struct syncpeer *p) +{ + return net_ctl_send(p, CTL_STATE, (u_int32_t)cfgstate.runstate, 0); +} + +int +net_ctl_send_error(struct syncpeer *p, enum CTLTYPE prevtype) +{ + return net_ctl_send(p, CTL_ERROR, (u_int32_t)prevtype, 0); +} + +/* After a CARP tracker state change, send an state ctl msg to all peers. */ +void +net_ctl_update_state(void) +{ + struct syncpeer *p; + static char *carpstate[] = CARPSTATES; + + /* We may have new peers available. */ + net_connect_peers(); + + for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) { + if (p->socket == -1) + continue; + log_msg(2, "sending my state %s to peer \"%s\"", + carpstate[cfgstate.runstate], p->name); + net_ctl_send_state(p); + } +} |