GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/sasyncd/net_ctl.c Lines: 0 68 0.0 %
Date: 2017-11-07 Branches: 0 33 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: net_ctl.c,v 1.11 2016/07/18 21:22:09 benno Exp $	*/
2
3
/*
4
 * Copyright (c) 2005 Håkan Olsson.  All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 */
27
28
/*
29
 * This code was written under funding by Multicom Security AB.
30
 */
31
32
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
#include <sys/time.h>
36
#include <netinet/in.h>
37
#include <arpa/inet.h>
38
39
#include <errno.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <unistd.h>
43
44
#include "sasyncd.h"
45
#include "net.h"
46
47
struct ctlmsg {
48
	u_int32_t	type;
49
	u_int32_t	data;
50
	u_int32_t	data2;
51
};
52
53
int snapcount = 0;
54
55
static int
56
net_ctl_check_state(struct syncpeer *p, enum RUNSTATE nstate)
57
{
58
	if (nstate < INIT || nstate > FAIL) {
59
		log_msg(0, "net_ctl: got bad state %d from peer \"%s\"",
60
		    nstate, p->name);
61
		net_ctl_send_error(p, CTL_STATE);
62
		return -1;
63
	}
64
	if (cfgstate.runstate == MASTER && nstate == MASTER) {
65
		log_msg(0, "net_ctl: got bad state MASTER from peer \"%s\"",
66
		    p->name);
67
		net_ctl_send_error(p, CTL_STATE);
68
		return -1;
69
	}
70
	if (p->runstate != nstate) {
71
		p->runstate = nstate;
72
		log_msg(1, "net_ctl: peer \"%s\" state change to %s", p->name,
73
		    carp_state_name(nstate));
74
	}
75
	return 0;
76
}
77
78
void
79
net_ctl_handle_msg(struct syncpeer *p, u_int8_t *msg, u_int32_t msglen)
80
{
81
	struct ctlmsg	*ctl = (struct ctlmsg *)msg;
82
	enum RUNSTATE	 nstate;
83
	enum CTLTYPE	 ctype;
84
	static char	*ct, *ctltype[] = CTLTYPES;
85
86
	if (msglen < sizeof *ctl) {
87
		log_msg(0, "net_ctl: got bad control message from peer \"%s\"",
88
		    p->name);
89
		net_ctl_send_error(p, CTL_UNKNOWN);
90
		return;
91
	}
92
93
	switch (ntohl(ctl->type)) {
94
	case CTL_ENDSNAP:
95
		log_msg(2, "net_ctl: got CTL_ENDSNAP from peer \"%s\"",
96
		    p->name);
97
98
		/* XXX More sophistication required to handle multiple peers. */
99
		if (carp_demoted) {
100
			snapcount++;
101
			if (snapcount >= cfgstate.peercnt)
102
				monitor_carpundemote(NULL);
103
		}
104
		break;
105
106
	case CTL_STATE:
107
		log_msg(2, "net_ctl: got CTL_STATE from peer \"%s\"", p->name);
108
		nstate = (enum RUNSTATE)ntohl(ctl->data);
109
		if (net_ctl_check_state(p, nstate) == 0)
110
			net_ctl_send_ack(p, CTL_STATE, cfgstate.runstate);
111
		break;
112
113
	case CTL_ERROR:
114
		log_msg(1, "net_ctl: got ERROR from peer \"%s\"", p->name);
115
116
		switch (ntohl(ctl->data)) {
117
		case RESERVED: /* PFKEY -- nothing to do here for now */
118
			break;
119
120
		case CTL_STATE:
121
			nstate = cfgstate.runstate;
122
			carp_check_state();
123
			if (nstate != cfgstate.runstate)
124
				net_ctl_send_state(p);
125
			break;
126
127
		case CTL_UNKNOWN:
128
		default:
129
			break;
130
		}
131
		break;
132
133
	case CTL_ACK:
134
		ctype = (enum CTLTYPE)ntohl(ctl->data);
135
		if (ctype < RESERVED || ctype > CTL_UNKNOWN)
136
			ct = "<unknown>";
137
		else
138
			ct = ctltype[ctype];
139
		log_msg(2, "net_ctl: got %s ACK from peer \"%s\"", ct,
140
		    p->name);
141
		if (ctype == CTL_STATE) {
142
			nstate = (enum RUNSTATE)ntohl(ctl->data2);
143
			net_ctl_check_state(p, nstate);
144
		}
145
	break;
146
147
	case CTL_UNKNOWN:
148
	default:
149
		log_msg(1, "net_ctl: got unknown msg type %u from peer \"%s\"",
150
		    ntohl(ctl->type), p->name);
151
		break;
152
	}
153
}
154
155
static int
156
net_ctl_send(struct syncpeer *p, u_int32_t type, u_int32_t d, u_int32_t d2)
157
{
158
	struct ctlmsg	*m = malloc(sizeof *m);
159
160
	if (!m) {
161
		log_err("malloc(%zu)", sizeof *m);
162
		return -1;
163
	}
164
165
	memset(m, 0, sizeof *m);
166
	m->type = htonl(type);
167
	m->data = htonl(d);
168
	m->data2 = htonl(d2);
169
170
	return net_queue(p, MSG_SYNCCTL, (u_int8_t *)m, sizeof *m);
171
}
172
173
int
174
net_ctl_send_ack(struct syncpeer *p, enum CTLTYPE prevtype, u_int32_t code)
175
{
176
	return net_ctl_send(p, CTL_ACK, (u_int32_t)prevtype, code);
177
}
178
179
int
180
net_ctl_send_state(struct syncpeer *p)
181
{
182
	return net_ctl_send(p, CTL_STATE, (u_int32_t)cfgstate.runstate, 0);
183
}
184
185
int
186
net_ctl_send_error(struct syncpeer *p, enum CTLTYPE prevtype)
187
{
188
	return net_ctl_send(p, CTL_ERROR, (u_int32_t)prevtype, 0);
189
}
190
191
int
192
net_ctl_send_endsnap(struct syncpeer *p)
193
{
194
	return net_ctl_send(p, CTL_ENDSNAP, 0, 0);
195
}
196
197
/* After a CARP tracker state change, send an state ctl msg to all peers. */
198
void
199
net_ctl_update_state(void)
200
{
201
	struct syncpeer *p;
202
203
	/* We may have new peers available.  */
204
	net_connect();
205
206
	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
207
		if (p->socket == -1)
208
			continue;
209
		log_msg(2, "net_ctl: sending my state %s to peer \"%s\"",
210
		    carp_state_name(cfgstate.runstate), p->name);
211
		net_ctl_send_state(p);
212
	}
213
}