1 /*-
2  * Copyright (c) 2009-2010 The FreeBSD Foundation
3  * Copyright (c) 2010 Mikolaj Golub <to.my.trociny@gmail.com>
4  * All rights reserved.
5  *
6  * This software wss developed by Mikolaj Golub. The source is derived
7  * from HAST developed by Pawel Jakub Dawidek under sponsorship from
8  * the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  */
32 
33 #ifndef	_HAST_H_
34 #define	_HAST_H_
35 
36 #include <sys/cdefs.h>
37 #include <sys/types.h>
38 
39 #ifdef HAVE_DEFINE_TAILQ_FOREACH_SAFE_SYS_QUEUE_H
40 #include <sys/queue.h>
41 #else
42 #include "queue.h"
43 #endif
44 #include <sys/socket.h>
45 
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 
49 #include <limits.h>
50 #include <pthread.h>
51 #include <stdbool.h>
52 #include <stdint.h>
53 
54 #include "auth.h"
55 #include "proto.h"
56 
57 #define	HAST_PROTO_VERSION	0
58 
59 #define	EHAST_OK		0
60 #define	EHAST_NOENTRY		1
61 #define	EHAST_INVALID		2
62 #define	EHAST_NOMEMORY		3
63 #define	EHAST_UNIMPLEMENTED	4
64 #define	EHAST_AUTHFAILED	5
65 
66 #define HASTREQ_TYPE_UNKNOWN	0
67 #define HASTREQ_TYPE_CONTROL	1
68 #define HASTREQ_TYPE_COMPLAINT	2
69 
70 #define	HASTCTL_CMD_UNKNOWN	0
71 #define	HASTCTL_CMD_SETROLE	1
72 #define	HASTCTL_CMD_STATUS	2
73 
74 #define	HAST_ROLE_UNDEF		0
75 #define	HAST_ROLE_INIT		1
76 #define	HAST_ROLE_PRIMARY	2
77 #define	HAST_ROLE_SECONDARY	3
78 #define	HAST_ROLE_WATCHDOG	4
79 
80 #define	HAST_STATE_UNKNOWN	0
81 #define	HAST_STATE_READYTORUN	1
82 #define	HAST_STATE_STARTING	2
83 #define	HAST_STATE_RUN		3
84 #define	HAST_STATE_STOPPING	4
85 #define	HAST_STATE_STOPPED	5
86 #define	HAST_STATE_FAILED	6
87 
88 #define HIO_UNDEF		0
89 #define HIO_STATE		1
90 
91 #define	HAST_TIMEOUT	5
92 #define	HAST_CONFIG	"/usr/local/etc/hastmon.conf"
93 #define	HAST_CONTROL	"/var/run/hastmonctl"
94 #define	HAST_PORT	8458
95 #define	HAST_LISTEN	"tcp4://0.0.0.0:8458"
96 #define	HAST_PIDFILE	"/var/run/hastmon.pid"
97 #define HAST_ATTEMPTS	5
98 #define HAST_HBEAT_INT	10
99 #define HAST_CMPLNT_CNT	3
100 #define HAST_CMPLNT_INT	60
101 
102 #define	HAST_ADDRSIZE	1024
103 #define	HAST_TOKEN_SIZE	16
104 #define HAST_KEYMAX	1024
105 
106 struct hastmon_config {
107 	/* Address to communicate with hastctl(8). */
108 	char	 hc_controladdr[HAST_ADDRSIZE];
109 	/* Protocol-specific data. */
110 	struct proto_conn *hc_controlconn;
111 	/* Incoming control connection. */
112 	struct proto_conn *hc_controlin;
113 	/* Address to listen on. */
114 	char	 hc_listenaddr[HAST_ADDRSIZE];
115 	/* Protocol-specific data. */
116 	struct proto_conn *hc_listenconn;
117 	/* Global list of addresses that can connect to us. */
118 	TAILQ_HEAD(, hast_address) hc_friends;
119 	/* List of resources. */
120 	TAILQ_HEAD(, hast_resource) hc_resources;
121 };
122 
123 /*
124  * Structure that describes single resource.
125  */
126 struct hast_resource {
127 	/* Resource name. */
128 	char	hr_name[NAME_MAX];
129 
130 	/* Path to a program to execute on various events. */
131 	char	hr_exec[PATH_MAX];
132 
133 	/* Resource unique identifier. */
134 	uint64_t hr_resuid;
135 
136 	/* This node priority being primary for the resourse. */
137 	int hr_priority;
138 
139 	/* Resource role: HAST_ROLE_{INIT,PRIMARY,SECONDARY,WATCHDOG}. */
140 	int	hr_role;
141 	/* Previous resource role: HAST_ROLE_{INIT,PRIMARY,SECONDARY,WATCHDOG}. */
142 	int	hr_previous_role;
143 	/* Resource role on start: HAST_ROLE_{INIT,PRIMARY,SECONDARY,WATCHDOG}. */
144 	int	hr_role_on_start;
145 	/* PID of child worker process. 0 - no child. */
146 	pid_t	hr_workerpid;
147 	/* Control connection between parent and child. */
148 	struct proto_conn *hr_ctrl;
149 	/* Events from child to parent. */
150 	struct proto_conn *hr_event;
151 	/* Connection timeout. */
152 	int	hr_timeout;
153 	/* Resource state: HAST_STATE_{UNKNOWN,STARTING,RUN,STOPPING,STOPPED,FAILED}. */
154 	int	hr_local_state;
155 	/* Number of attemps to start resource. */
156 	int	hr_local_attempts;
157 	/* Number of attemps after which the resourse is considered failed. */
158 	int	hr_local_attempts_max;
159 
160 	/* Time of the last received STATUS request from a remote (watchdog). */
161 	time_t	hr_remote_lastcheck;
162 
163 	/* Per resource list of addresses that can connect to us. */
164 	TAILQ_HEAD(, hast_address) hr_friends;
165 
166 	/* Key used for authentication. */
167 	struct hast_auth hr_key;
168 
169 	/* Number of remote components. */
170 	int hr_remote_cnt;
171 
172 	/* List of remote components. */
173 	TAILQ_HEAD(, hast_remote) hr_remote;
174 
175 	/* Number of complaints we want to receive before failovering. */
176 	int	hr_complaint_critical_cnt;
177 	/* Period of time (in sec) complaints are counted. */
178 	int	hr_complaint_interval;
179 
180 	/* Period of time (in sec) between heartbeats. */
181 	int	hr_heartbeat_interval;
182 
183 	/* Complaints. */
184 	TAILQ_HEAD(, hast_complaint) hr_complaints;
185 
186 	/* Locked used to synchronize access to resourse. */
187 	pthread_mutex_t hr_lock;
188 
189 	/* Next resource. */
190 	TAILQ_ENTRY(hast_resource) hr_next;
191 };
192 
193 struct hast_remote {
194 	/* Address of the remote component. */
195 	char	r_addr[HAST_ADDRSIZE];
196 	/* Connection for incoming data. */
197 	struct proto_conn *r_in;
198 	/* Connection for outgoing data. */
199 	struct proto_conn *r_out;
200 	/* Token to verify both in and out connection are coming from
201 	   the same node (not necessarily from the same address). */
202 	unsigned char r_token[HAST_TOKEN_SIZE];
203 	/* Remote role: HAST_ROLE_{INIT,PRIMARY,SECONDARY,WATCHDOG}. */
204 	int	r_role;
205 	/* Remote state: HAST_STATE_{UNKNOWN,STARTING,RUN,STOPPING,STOPPED}. */
206 	int	r_state;
207 	/* Pointer to resurce */
208 	struct hast_resource	*r_res;
209 	/* This component number */
210 	int r_ncomp;
211 	/* Next remote. */
212 	TAILQ_ENTRY(hast_remote) r_next;
213 };
214 
215 struct hast_address {
216 	char	a_addr[HAST_ADDRSIZE];
217 	TAILQ_ENTRY(hast_address) a_next;
218 };
219 
220 struct hast_complaint {
221 	time_t	c_time;
222 	TAILQ_ENTRY(hast_complaint) c_next;
223 };
224 
225 struct hastmon_config *yy_config_parse(const char *config, bool exitonerror);
226 void yy_resource_free(struct hast_resource *res);
227 void yy_config_free(struct hastmon_config *config);
228 
229 void yyerror(const char *);
230 int yylex(void);
231 int yyparse(void);
232 
233 #endif	/* !_HAST_H_ */
234