]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/misc-progs/ipsecctrl.c
ipsecctrl: Call ipsec-interfaces script when turning up/shutting down connections
[people/pmueller/ipfire-2.x.git] / src / misc-progs / ipsecctrl.c
CommitLineData
05207d69
MT
1/*
2 *
3 * File originally from the Smoothwall project
4 * (c) 2001 Smoothwall Team
5 *
05207d69
MT
6 */
7
8#include "libsmooth.h"
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <signal.h>
52e54c1c 16
05207d69 17#include "setuid.h"
52e54c1c 18#include "netutil.h"
05207d69 19
5fd30232
MT
20/*
21 This module is responsible for start stop of the vpn system.
22
23 1) it allows AH & ESP to get in from interface where a vpn is mounted
69dcc425 24 The NAT traversal is used on the udp 4500 port.
5fd30232
MT
25
26 2) it starts the ipsec daemon
69dcc425
CS
27 The RED interface is a problem because it can be up or down a startup.
28 Then, the state change and it must not affect other VPN mounted on
29 other interface.
30 Unfortunatly, openswan 1 cannot do that correctly. It cannot use an
31 interface without restarting everything.
5fd30232
MT
32
33*/
34
05207d69 35void usage() {
69dcc425
CS
36 fprintf (stderr, "Usage:\n");
37 fprintf (stderr, "\tipsecctrl S [connectionkey]\n");
38 fprintf (stderr, "\tipsecctrl D [connectionkey]\n");
39 fprintf (stderr, "\tipsecctrl R\n");
db073a10 40 fprintf (stderr, "\tipsecctrl I\n");
69dcc425
CS
41 fprintf (stderr, "\t\tS : Start/Restart Connection\n");
42 fprintf (stderr, "\t\tD : Stop Connection\n");
43 fprintf (stderr, "\t\tR : Reload Certificates and Secrets\n");
db073a10 44 fprintf (stderr, "\t\tI : Print Statusinfo\n");
05207d69
MT
45}
46
8fcb9253
MT
47static void ipsec_reload() {
48 /* Re-read all configuration files and secrets and
49 * reload the daemon (#10339).
50 */
51 safe_system("/usr/sbin/ipsec rereadall >/dev/null 2>&1");
52 safe_system("/usr/sbin/ipsec reload >/dev/null 2>&1");
53}
54
5fd30232
MT
55/*
56 return values from the vpn config file or false if not 'on'
57*/
58int decode_line (char *s,
69dcc425
CS
59 char **key,
60 char **name,
9f0b5c9f 61 char **type
69dcc425
CS
62 ) {
63 int count = 0;
64 *key = NULL;
65 *name = NULL;
66 *type = NULL;
67
68 if (s[strlen(s) - 1] == '\n')
69 s[strlen(s) - 1] = '\0';
70
71 char *result = strsep(&s, ",");
72 while (result) {
73 if (count == 0)
74 *key = result;
75 if ((count == 1) && strcmp(result, "on") != 0)
76 return 0; // a disabled line
77 if (count == 2)
78 *name = result;
79 if (count == 4)
80 *type = result;
69dcc425
CS
81 count++;
82 result = strsep(&s, ",");
83 }
84
85 // check other syntax
86 if (! *name)
87 return 0;
88
89 if (strspn(*name, LETTERS_NUMBERS) != strlen(*name)) {
90 fprintf(stderr, "Bad connection name: %s\n", *name);
91 return 0;
92 }
93
94 if (! (strcmp(*type, "host") == 0 || strcmp(*type, "net") == 0)) {
95 fprintf(stderr, "Bad connection type: %s\n", *type);
96 return 0;
97 }
98
69dcc425
CS
99 //it's a valid & active line
100 return 1;
5fd30232
MT
101}
102
103/*
104 issue ipsec commmands to turn on connection 'name'
105*/
9f0b5c9f
MT
106void turn_connection_on(char *name, char *type) {
107 /*
108 * To bring up a connection, we need to reload the configuration
109 * and issue ipsec up afterwards. To make sure the connection
110 * is not established from the start, we bring it down in advance.
111 */
6e2ba31b 112 char command[STRING_SIZE];
6e2ba31b 113
9f0b5c9f 114 // Bring down the connection (if established).
6e2ba31b 115 snprintf(command, STRING_SIZE - 1,
9f0b5c9f 116 "/usr/sbin/ipsec down %s >/dev/null", name);
6e2ba31b 117 safe_system(command);
6e2ba31b 118
6c920b19
MT
119 // Reload the IPsec firewall policy
120 safe_system("/usr/lib/firewall/ipsec-policy >/dev/null");
80fbd899 121
3446a172
MT
122 // Create or destroy interfaces
123 safe_system("/usr/local/bin/ipsec-interfaces >/dev/null");
124
8e2683f7
MT
125 // Reload the configuration into the daemon (#10339).
126 ipsec_reload();
6e2ba31b 127
9f0b5c9f
MT
128 // Bring the connection up again.
129 snprintf(command, STRING_SIZE - 1,
b89ae1a4 130 "/usr/sbin/ipsec stroke up-nb %s >/dev/null", name);
9f0b5c9f 131 safe_system(command);
5fd30232 132}
9f0b5c9f 133
5fd30232
MT
134/*
135 issue ipsec commmands to turn off connection 'name'
136*/
137void turn_connection_off (char *name) {
9f0b5c9f
MT
138 /*
139 * To turn off a connection, all SAs must be turned down.
140 * After that, the configuration must be reloaded.
141 */
69dcc425 142 char command[STRING_SIZE];
9f0b5c9f
MT
143
144 // Bring down the connection.
3e077ef3 145 snprintf(command, STRING_SIZE - 1,
9f0b5c9f 146 "/usr/sbin/ipsec down %s >/dev/null", name);
3e077ef3 147 safe_system(command);
6e2ba31b 148
9f0b5c9f 149 // Reload, so the connection is dropped.
8e2683f7 150 ipsec_reload();
4f6790a7 151
6c920b19
MT
152 // Reload the IPsec firewall policy
153 safe_system("/usr/lib/firewall/ipsec-policy >/dev/null");
3446a172
MT
154
155 // Create or destroy interfaces
156 safe_system("/usr/local/bin/ipsec-interfaces >/dev/null");
8e2683f7
MT
157}
158
05207d69 159int main(int argc, char *argv[]) {
69dcc425
CS
160 struct keyvalue *kv = NULL;
161
162 if (argc < 2) {
163 usage();
164 exit(1);
165 }
166 if (!(initsetuid()))
167 exit(1);
6cf8bc91
MT
168
169 FILE *file = NULL;
ba149d47
AF
170
171 if (strcmp(argv[1], "I") == 0) {
9f0b5c9f 172 safe_system("/usr/sbin/ipsec status");
ba149d47
AF
173 exit(0);
174 }
175
176 if (strcmp(argv[1], "R") == 0) {
8e2683f7 177 ipsec_reload();
ba149d47
AF
178 exit(0);
179 }
180
69dcc425
CS
181 /* FIXME: workaround for pclose() issue - still no real idea why
182 * this is happening */
183 signal(SIGCHLD, SIG_DFL);
184
185 /* handle operations that doesn't need start the ipsec system */
186 if (argc == 2) {
187 if (strcmp(argv[1], "D") == 0) {
9f0b5c9f 188 safe_system("/usr/sbin/ipsec stop >/dev/null 2>&1");
6cf8bc91 189 safe_system("/usr/lib/firewall/ipsec-policy >/dev/null");
3446a172 190 safe_system("/usr/local/bin/ipsec-interfaces >/dev/null");
69dcc425
CS
191 exit(0);
192 }
69dcc425
CS
193 }
194
69dcc425
CS
195 /* read vpn config */
196 kv=initkeyvalues();
197 if (!readkeyvalues(kv, CONFIG_ROOT "/vpn/settings"))
198 {
199 fprintf(stderr, "Cannot read vpn settings\n");
200 exit(1);
201 }
202
203 /* check is the vpn system is enabled */
204 {
205 char s[STRING_SIZE];
206 findkey(kv, "ENABLED", s);
207 freekeyvalues(kv);
208 if (strcmp (s, "on") != 0)
209 exit(0);
210 }
211
69dcc425
CS
212 char s[STRING_SIZE];
213
6cf8bc91 214 // start the system
69dcc425 215 if ((argc == 2) && strcmp(argv[1], "S") == 0) {
6c920b19 216 safe_system("/usr/lib/firewall/ipsec-policy >/dev/null");
3446a172 217 safe_system("/usr/local/bin/ipsec-interfaces >/dev/null");
9f0b5c9f 218 safe_system("/usr/sbin/ipsec restart >/dev/null");
69dcc425
CS
219 exit(0);
220 }
221
222 // it is a selective start or stop
223 // second param is only a number 'key'
224 if ((argc == 2) || strspn(argv[2], NUMBERS) != strlen(argv[2])) {
9f0b5c9f 225 fprintf(stderr, "Bad arg: %s\n", argv[2]);
69dcc425
CS
226 usage();
227 exit(1);
228 }
229
230 // search the vpn pointed by 'key'
231 if (!(file = fopen(CONFIG_ROOT "/vpn/config", "r"))) {
69dcc425
CS
232 fprintf(stderr, "Couldn't open vpn settings file");
233 exit(1);
234 }
235 while (fgets(s, STRING_SIZE, file) != NULL) {
236 char *key;
237 char *name;
238 char *type;
9f0b5c9f 239 if (!decode_line(s,&key,&name,&type))
69dcc425
CS
240 continue;
241
69dcc425
CS
242 // is it the 'key' requested ?
243 if (strcmp(argv[2], key) != 0)
244 continue;
9f0b5c9f 245
69dcc425
CS
246 // Start or Delete this Connection
247 if (strcmp(argv[1], "S") == 0)
248 turn_connection_on (name, type);
9f0b5c9f 249 else if (strcmp(argv[1], "D") == 0)
69dcc425
CS
250 turn_connection_off (name);
251 else {
69dcc425
CS
252 fprintf(stderr, "Bad command\n");
253 exit(1);
254 }
255 }
256 fclose(file);
9f0b5c9f 257
69dcc425 258 return 0;
05207d69 259}