226f122af4c285aa7ca5895e6dfcfc9f0373e003
[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
16 #include "ha_sync_ctl.h"
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/select.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <pthread.h>
25
26 #include <processing/jobs/callback_job.h>
27
28 #define HA_SYNC_FIFO IPSEC_PIDDIR "/charon.ha"
29
30 typedef struct private_ha_sync_ctl_t private_ha_sync_ctl_t;
31
32 /**
33 * Private data of an ha_sync_ctl_t object.
34 */
35 struct private_ha_sync_ctl_t {
36
37 /**
38 * Public ha_sync_ctl_t interface.
39 */
40 ha_sync_ctl_t public;
41
42 /**
43 * Segments to control
44 */
45 ha_sync_segments_t *segments;
46
47 /**
48 * FIFO reader thread
49 */
50 callback_job_t *job;
51 };
52
53 /**
54 * FIFO dispatching function
55 */
56 static job_requeue_t dispatch_fifo(private_ha_sync_ctl_t *this)
57 {
58 int fifo, old;
59 char buf[8];
60 u_int segment;
61
62 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
63 fifo = open(HA_SYNC_FIFO, O_RDONLY);
64 pthread_setcancelstate(old, NULL);
65 if (fifo == -1)
66 {
67 DBG1(DBG_CFG, "opening HA sync fifo failed: %s", strerror(errno));
68 sleep(1);
69 return JOB_REQUEUE_FAIR;
70 }
71
72 memset(buf, 0, sizeof(buf));
73 if (read(fifo, buf, sizeof(buf)-1) > 1)
74 {
75 segment = atoi(&buf[1]);
76 if (segment)
77 {
78 switch (buf[0])
79 {
80 case '+':
81 this->segments->activate(this->segments, segment);
82 break;
83 case '-':
84 this->segments->deactivate(this->segments, segment);
85 break;
86 case '*':
87 this->segments->resync(this->segments, segment);
88 break;
89 default:
90 break;
91 }
92 }
93 }
94 close(fifo);
95
96 return JOB_REQUEUE_DIRECT;
97 }
98
99 /**
100 * Implementation of ha_sync_ctl_t.destroy.
101 */
102 static void destroy(private_ha_sync_ctl_t *this)
103 {
104 this->job->cancel(this->job);
105 free(this);
106 }
107
108 /**
109 * See header
110 */
111 ha_sync_ctl_t *ha_sync_ctl_create(ha_sync_segments_t *segments)
112 {
113 private_ha_sync_ctl_t *this = malloc_thing(private_ha_sync_ctl_t);
114
115 this->public.destroy = (void(*)(ha_sync_ctl_t*))destroy;
116
117 if (access(HA_SYNC_FIFO, R_OK|W_OK) != 0)
118 {
119 if (mkfifo(HA_SYNC_FIFO, 600) != 0)
120 {
121 DBG1(DBG_CFG, "creating HA sync FIFO %s failed: %s",
122 HA_SYNC_FIFO, strerror(errno));
123 }
124 }
125
126 this->segments = segments;
127 this->job = callback_job_create((callback_job_cb_t)dispatch_fifo,
128 this, NULL, NULL);
129 charon->processor->queue_job(charon->processor, (job_t*)this->job);
130 return &this->public;
131 }
132