]> git.ipfire.org Git - ipfire-2.x.git/blob - src/misc-progs/restartsquid.c
git-svn-id: http://svn.ipfire.org/svn/ipfire/IPFire/source@16 ea5c0bd1-69bd-2848...
[ipfire-2.x.git] / src / misc-progs / restartsquid.c
1 /* SmoothWall helper program - restartsquid
2 *
3 * This program is distributed under the terms of the GNU General Public
4 * Licence. See the file COPYING for details.
5 *
6 * (c) Lawrence Manning, 2001
7 * Restarting squid with transparent proxying.
8 *
9 * 05/02/2004 - Roy Walker <rwalker@miracomnetwork.com>
10 * Exclude red network from transparent proxy to allow browsing to alias IPs
11 * Read in VPN settings and exclude each VPN network from transparent proxy
12 *
13 * $Id: restartsquid.c,v 1.7.2.8 2005/04/22 18:44:37 rkerr Exp $
14 *
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <pwd.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include "libsmooth.h"
26 #include "setuid.h"
27
28 int main(int argc, char *argv[])
29 {
30 int fd = -1;
31 int enable = 0;
32 int enablevpn = 0;
33 int transparent = 0;
34 int enable_blue = 0;
35 int transparent_blue = 0;
36 int running = 0;
37 struct stat st;
38 FILE *ipfile;
39 char localip[STRING_SIZE] = "";
40 struct keyvalue *net = NULL;
41 struct keyvalue *squid = NULL;
42 char buffer[STRING_SIZE];
43 char proxy_port[STRING_SIZE];
44 char s[STRING_SIZE];
45 char green_dev[STRING_SIZE] = "";
46 char blue_dev[STRING_SIZE] = "";
47 char red_netaddress[STRING_SIZE] = "";
48 char red_netmask[STRING_SIZE] = "";
49 char configtype[STRING_SIZE] = "";
50 char redtype[STRING_SIZE] = "";
51 char enableredvpn[STRING_SIZE] = "";
52 char enablebluevpn[STRING_SIZE] = "";
53
54 if (!(initsetuid()))
55 exit(1);
56
57 /* Kill running squid */
58 safe_system("/sbin/iptables -t nat -F SQUID");
59 safe_system("/usr/sbin/squid -k shutdown >/dev/null 2>/dev/null");
60 sleep(5);
61 safe_system("/bin/killall -9 squid >/dev/null 2>/dev/null");
62
63 /* See if proxy is enabled and / or transparent */
64 if ((fd = open(CONFIG_ROOT "/proxy/enable", O_RDONLY)) != -1)
65 {
66 close(fd);
67 enable = 1;
68 }
69 if ((fd = open(CONFIG_ROOT "/proxy/transparent", O_RDONLY)) != -1)
70 {
71 close(fd);
72 transparent = 1;
73 }
74 if ((fd = open(CONFIG_ROOT "/proxy/enable_blue", O_RDONLY)) != -1)
75 {
76 close(fd);
77 enable_blue = 1;
78 }
79 if ((fd = open(CONFIG_ROOT "/proxy/transparent_blue", O_RDONLY)) != -1)
80 {
81 close(fd);
82 transparent_blue = 1;
83 }
84
85 /* Read the network configuration */
86 net=initkeyvalues();
87 if (!readkeyvalues(net, CONFIG_ROOT "/ethernet/settings"))
88 {
89 fprintf(stderr, "Cannot read ethernet settings\n");
90 exit(1);
91 }
92 if (!findkey(net, "GREEN_DEV", green_dev))
93 {
94 fprintf(stderr, "Cannot read GREEN_DEV\n");
95 exit(1);
96 }
97 if (!VALID_DEVICE(green_dev))
98 {
99 fprintf(stderr, "Bad GREEN_DEV: %s\n", green_dev);
100 exit(1);
101 }
102 if (!findkey(net, "CONFIG_TYPE", configtype))
103 {
104 fprintf(stderr, "Cannot read CONFIG_TYPE\n");
105 exit(1);
106 }
107
108 findkey(net, "RED_TYPE", redtype);
109 findkey(net, "RED_NETADDRESS", red_netaddress);
110 findkey(net, "RED_NETMASK", red_netmask);
111 findkey(net, "BLUE_DEV", blue_dev);
112 freekeyvalues(net);
113
114 /* See if VPN software is enabled */
115 net=initkeyvalues();
116 if (!readkeyvalues(net, CONFIG_ROOT "/vpn/settings"))
117 {
118 fprintf(stderr, "Cannot read vpn settings\n");
119 exit(1);
120 }
121 findkey(net, "ENABLED", enableredvpn);
122 findkey(net, "ENABLED_BLUE", enablebluevpn);
123 freekeyvalues(net);
124 if ( (!strcmp(enableredvpn, "on") && VALID_IP(localip)) ||
125 (!strcmp(enablebluevpn, "on") && VALID_DEVICE(blue_dev)) ) {
126 enablevpn = 1;
127 }
128
129 /* Retrieve the Squid pid file */
130 if ((fd = open("/var/run/squid.pid", O_RDONLY)) != -1)
131 {
132 close(fd);
133 running = 1;
134 }
135
136 /* Retrieve the RED ip address */
137 stat(CONFIG_ROOT "/red/local-ipaddress", &st);
138 if (S_ISREG(st.st_mode)) {
139 if (!(ipfile = fopen(CONFIG_ROOT "/red/local-ipaddress", "r")))
140 {
141 fprintf(stderr, "Couldn't open ip file\n");
142 exit(0);
143 }
144 if (fgets(localip, STRING_SIZE, ipfile))
145 {
146 if (localip[strlen(localip) - 1] == '\n')
147 localip[strlen(localip) - 1] = '\0';
148 }
149 fclose(ipfile);
150 if (!VALID_IP(localip))
151 {
152 fprintf(stderr, "Bad ip: %s\n", localip);
153 exit(0);
154 }
155 }
156
157 /* See if we need to flush the cache */
158 if (argc >=2) {
159 if (strcmp(argv[1], "-f") == 0) {
160 if (stat("/var/log/cache/swap.state", &st) == 0) {
161 struct passwd *pw;
162 if((pw = getpwnam("squid"))) {
163 endpwent(); /* probably paranoia, but just in case.. */
164 unpriv_system("/bin/echo > /var/log/cache/swap.state", pw->pw_uid, pw->pw_gid);
165 } else { endpwent(); }
166 }
167 }
168 }
169
170 if (enable || enable_blue)
171 {
172 safe_system("/usr/sbin/squid -D -z");
173 safe_system("/usr/sbin/squid -D");
174 }
175
176 /* Retrieve the proxy port */
177 if (transparent || transparent_blue) {
178 squid=initkeyvalues();
179
180 if (!readkeyvalues(squid, CONFIG_ROOT "/proxy/settings"))
181 {
182 fprintf(stderr, "Cannot read proxy settings\n");
183 exit(1);
184 }
185
186 if (!(findkey(squid, "PROXY_PORT", proxy_port)))
187 {
188 strcpy (proxy_port, "800");
189 } else {
190 if(strspn(proxy_port, NUMBERS) != strlen(proxy_port))
191 {
192 fprintf(stderr, "Invalid proxy port: %s, defaulting to 800\n", proxy_port);
193 strcpy(proxy_port, "800");
194 }
195 }
196 freekeyvalues(squid);
197 }
198
199 if (transparent && enable) {
200 int count;
201 char *result;
202 char *name;
203 char *type;
204 char *running;
205 char *vpn_network_mask;
206 char *vpn_netaddress;
207 char *vpn_netmask;
208 FILE *file = NULL;
209 char *conn_enabled;
210
211 /* Darren Critchley - check to see if RED VPN is enabled before mucking with rules */
212 if (!strcmp(enableredvpn, "on")) {
213 /* Read the /vpn/config file - no check to see if VPN is enabled */
214 if (!(file = fopen(CONFIG_ROOT "/vpn/config", "r"))) {
215 fprintf(stderr, "Couldn't open vpn config file");
216 exit(1);
217 }
218
219 while (fgets(s, STRING_SIZE, file) != NULL) {
220 if (s[strlen(s) - 1] == '\n')
221 s[strlen(s) - 1] = '\0';
222 running = strdup (s);
223 result = strsep(&running, ",");
224 count = 0;
225 name = NULL;
226 type = NULL;
227 vpn_network_mask = NULL;
228 conn_enabled = NULL;
229 while (result) {
230 if (count == 1)
231 conn_enabled = result;
232 if (count == 2)
233 name = result;
234 if (count == 4)
235 type = result;
236 if (count == 12 )
237 vpn_network_mask = result;
238 count++;
239 result = strsep(&running, ",");
240 }
241
242 if (strspn(name, LETTERS_NUMBERS) != strlen(name)) {
243 fprintf(stderr, "Bad connection name: %s\n", name);
244 exit(1);
245 }
246
247 if (! (strcmp(type, "net") == 0)) {
248 continue;
249 }
250
251 /* Darren Critchley - new check to see if connection is enabled */
252 if (! (strcmp(conn_enabled, "on") == 0)) {
253 continue;
254 }
255
256 result = strsep(&vpn_network_mask, "/");
257 count = 0;
258 vpn_netaddress = NULL;
259 vpn_netmask = NULL;
260 while (result) {
261 if (count == 0)
262 vpn_netaddress = result;
263 if (count == 1)
264 vpn_netmask = result;
265 count++;
266 result = strsep(&vpn_network_mask, "/");
267 }
268
269 if (!VALID_IP(vpn_netaddress)) {
270 fprintf(stderr, "Bad network for vpn connection %s: %s\n", name, vpn_netaddress);
271 continue;
272 }
273
274 if ((!VALID_IP(vpn_netmask)) && (!VALID_SHORT_MASK(vpn_netmask))) {
275 fprintf(stderr, "Bad mask for vpn connection %s: %s\n", name, vpn_netmask);
276 continue;
277 }
278
279 memset(buffer, 0, STRING_SIZE);
280 if( snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp -d %s/%s --dport 80 -j RETURN", green_dev, vpn_netaddress, vpn_netmask) >= STRING_SIZE )
281 {
282 fprintf(stderr, "Command too long\n");
283 exit(1);
284 }
285 safe_system(buffer);
286 }
287 }
288
289 memset(buffer, 0, STRING_SIZE);
290 if ( ( (strcmp(configtype, "2")==0) || (strcmp(configtype, "3")==0) ||
291 (strcmp(configtype, "6")==0) || (strcmp(configtype, "7")==0) ) &&
292 (VALID_IP(red_netaddress)) && (VALID_IP(red_netmask)) &&
293 (strcmp(redtype, "STATIC")==0) )
294 {
295 memset(buffer, 0, STRING_SIZE);
296 if( snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp -d %s/%s --dport 80 -j RETURN", green_dev, red_netaddress, red_netmask) >= STRING_SIZE )
297 {
298 fprintf(stderr, "Command too long\n");
299 exit(1);
300 }
301 safe_system(buffer);
302 } else if (VALID_IP(localip)) {
303 memset(buffer, 0, STRING_SIZE);
304 if( snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp -d %s --dport 80 -j RETURN", green_dev, localip) >= STRING_SIZE )
305 {
306 fprintf(stderr, "Command too long\n");
307 exit(1);
308 }
309 safe_system(buffer);
310 }
311
312 memset(buffer, 0, STRING_SIZE);
313 if( snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp --dport 80 -j REDIRECT --to-port %s", green_dev, proxy_port) >= STRING_SIZE )
314 {
315 fprintf(stderr, "Command too long\n");
316 exit(1);
317 }
318 safe_system(buffer);
319 }
320
321 if (transparent_blue && enable_blue) {
322 int count;
323 char *result;
324 char *name;
325 char *type;
326 char *running;
327 char *vpn_network_mask;
328 char *vpn_netaddress;
329 char *vpn_netmask;
330 char *conn_enabled;
331 FILE *file = NULL;
332
333 if (! VALID_DEVICE(blue_dev))
334 {
335 fprintf(stderr, "Bad BLUE_DEV: %s\n", blue_dev);
336 exit(1);
337 }
338
339 /* Darren Critchley - check to see if BLUE VPN is enabled before mucking with rules */
340 if (!strcmp(enablebluevpn, "on")) {
341 /* Read the /vpn/config file - no check to see if VPN is enabled */
342 if (!(file = fopen(CONFIG_ROOT "/vpn/config", "r"))) {
343 fprintf(stderr, "Couldn't open vpn config file");
344 exit(1);
345 }
346 while (fgets(s, STRING_SIZE, file) != NULL) {
347 if (s[strlen(s) - 1] == '\n')
348 s[strlen(s) - 1] = '\0';
349 running = strdup (s);
350 result = strsep(&running, ",");
351 count = 0;
352 name = NULL;
353 type = NULL;
354 vpn_network_mask = NULL;
355 conn_enabled = NULL;
356 while (result) {
357 if (count == 1)
358 conn_enabled = result;
359 if (count == 2)
360 name = result;
361 if (count == 4)
362 type = result;
363 if (count == 12 )
364 vpn_network_mask = result;
365 count++;
366 result = strsep(&running, ",");
367 }
368
369 if (strspn(name, LETTERS_NUMBERS) != strlen(name)) {
370 fprintf(stderr, "Bad connection name: %s\n", name);
371 exit(1);
372 }
373
374 if (! (strcmp(type, "net") == 0)) {
375 continue;
376 }
377
378 /* Darren Critchley - new check to see if connection is enabled */
379 if (! (strcmp(conn_enabled, "on") == 0)) {
380 continue;
381 }
382
383 result = strsep(&vpn_network_mask, "/");
384 count = 0;
385 vpn_netaddress = NULL;
386 vpn_netmask = NULL;
387 while (result) {
388 if (count == 0)
389 vpn_netaddress = result;
390 if (count == 1)
391 vpn_netmask = result;
392 count++;
393 result = strsep(&vpn_network_mask, "/");
394 }
395
396 if (!VALID_IP(vpn_netaddress)) {
397 fprintf(stderr, "Bad network for vpn connection %s: %s\n", name, vpn_netaddress);
398 continue;
399 }
400
401 if ((!VALID_IP(vpn_netmask)) && (!VALID_SHORT_MASK(vpn_netmask))) {
402 fprintf(stderr, "Bad mask for vpn connection %s: %s\n", name, vpn_netmask);
403 continue;
404 }
405
406 memset(buffer, 0, STRING_SIZE);
407 if (snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp -d %s/%s --dport 80 -j RETURN", blue_dev, vpn_netaddress, vpn_netmask) >= STRING_SIZE )
408 {
409 fprintf(stderr, "Command too long\n");
410 exit(1);
411 }
412 safe_system(buffer);
413 }
414 }
415
416 memset(buffer, 0, STRING_SIZE);
417 if ( ( (strcmp(configtype, "2")==0) || (strcmp(configtype, "3")==0) ||
418 (strcmp(configtype, "6")==0) || (strcmp(configtype, "7")==0) ) &&
419 (VALID_IP(red_netaddress)) && (VALID_IP(red_netmask)) &&
420 (strcmp(redtype, "STATIC")==0) )
421 {
422 memset(buffer, 0, STRING_SIZE);
423 if( snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp -d %s/%s --dport 80 -j RETURN", blue_dev, red_netaddress, red_netmask) >= STRING_SIZE )
424 {
425 fprintf(stderr, "Command too long\n");
426 exit(1);
427 }
428 safe_system(buffer);
429 } else if (VALID_IP(localip)) {
430 memset(buffer, 0, STRING_SIZE);
431 if( snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp -d %s --dport 80 -j RETURN", blue_dev, localip) >= STRING_SIZE )
432 {
433 fprintf(stderr, "Command too long\n");
434 exit(1);
435 }
436 safe_system(buffer);
437 }
438
439 memset(buffer, 0, STRING_SIZE);
440 if( snprintf(buffer, STRING_SIZE - 1, "/sbin/iptables -t nat -A SQUID -i %s -p tcp --dport 80 -j REDIRECT --to-port %s", blue_dev, proxy_port) >= STRING_SIZE )
441 {
442 fprintf(stderr, "Command too long\n");
443 exit(1);
444 }
445 safe_system(buffer);
446 }
447
448 return 0;
449 }