added HA resync option to (re-)integrate nodes to a cluster
[strongswan.git] / src / charon / plugins / ha_sync / ha_sync_ctl.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "ha_sync_ctl.h"
19
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/select.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <pthread.h>
27
28 #include <processing/jobs/callback_job.h>
29
30 #define HA_SYNC_FIFO IPSEC_PIDDIR "/charon.ha"
31
32 typedef struct private_ha_sync_ctl_t private_ha_sync_ctl_t;
33
34 /**
35 * Private data of an ha_sync_ctl_t object.
36 */
37 struct private_ha_sync_ctl_t {
38
39 /**
40 * Public ha_sync_ctl_t interface.
41 */
42 ha_sync_ctl_t public;
43
44 /**
45 * Segments to control
46 */
47 ha_sync_segments_t *segments;
48
49 /**
50 * FIFO reader thread
51 */
52 callback_job_t *job;
53 };
54
55 /**
56 * FIFO dispatching function
57 */
58 static job_requeue_t dispatch_fifo(private_ha_sync_ctl_t *this)
59 {
60 int fifo, old;
61 char buf[8];
62 u_int segment;
63
64 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
65 fifo = open(HA_SYNC_FIFO, O_RDONLY);
66 pthread_setcancelstate(old, NULL);
67 if (fifo == -1)
68 {
69 DBG1(DBG_CFG, "opening HA sync fifo failed: %s", strerror(errno));
70 sleep(1);
71 return JOB_REQUEUE_FAIR;
72 }
73
74 memset(buf, 0, sizeof(buf));
75 if (read(fifo, buf, sizeof(buf)-1) > 1)
76 {
77 segment = atoi(&buf[1]);
78 if (segment)
79 {
80 switch (buf[0])
81 {
82 case '+':
83 this->segments->activate(this->segments, segment);
84 break;
85 case '-':
86 this->segments->deactivate(this->segments, segment);
87 break;
88 case '*':
89 this->segments->resync(this->segments, segment);
90 break;
91 default:
92 break;
93 }
94 }
95 }
96 close(fifo);
97
98 return JOB_REQUEUE_DIRECT;
99 }
100
101 /**
102 * Implementation of ha_sync_ctl_t.destroy.
103 */
104 static void destroy(private_ha_sync_ctl_t *this)
105 {
106 this->job->cancel(this->job);
107 free(this);
108 }
109
110 /**
111 * See header
112 */
113 ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_segments_t *segments)
114 {
115 private_ha_sync_ctl_t *this = malloc_thing(private_ha_sync_ctl_t);
116
117 this->public.destroy = (void(*)(ha_sync_ctl_t*))destroy;
118
119 if (access(HA_SYNC_FIFO, R_OK|W_OK) != 0)
120 {
121 if (mkfifo(HA_SYNC_FIFO, 600) != 0)
122 {
123 DBG1(DBG_CFG, "creating HA sync FIFO %s failed: %s",
124 HA_SYNC_FIFO, strerror(errno));
125 }
126 }
127
128 this->segments = segments;
129 this->job = callback_job_create((callback_job_cb_t)dispatch_fifo,
130 this, NULL, NULL);
131 charon->processor->queue_job(charon->processor, (job_t*)this->job);
132 return &this->public;
133 }
134