8 #include <netinet/in.h>
12 #include "libsmooth.h"
17 struct keyvalue
*kv
= NULL
;
18 FILE *ifacefile
= NULL
;
20 char redif
[STRING_SIZE
];
21 char blueif
[STRING_SIZE
];
22 char orangeif
[STRING_SIZE
];
23 char enablered
[STRING_SIZE
] = "off";
24 char enableblue
[STRING_SIZE
] = "off";
25 char enableorange
[STRING_SIZE
] = "off";
28 char OVPNINPUT
[STRING_SIZE
] = "OVPNINPUT";
29 char OVPNBLOCK
[STRING_SIZE
] = "OVPNBLOCK";
30 char OVPNNAT
[STRING_SIZE
] = "OVPNNAT";
31 char WRAPPERVERSION
[STRING_SIZE
] = "ipfire-2.2.4";
33 struct connection_struct
{
34 char name
[STRING_SIZE
];
35 char type
[STRING_SIZE
];
36 char proto
[STRING_SIZE
];
37 char status
[STRING_SIZE
];
38 char local_subnet
[STRING_SIZE
];
39 char transfer_subnet
[STRING_SIZE
];
40 char role
[STRING_SIZE
];
41 char port
[STRING_SIZE
];
42 struct connection_struct
*next
;
45 typedef struct connection_struct connection
;
47 void exithandler(void)
58 printf("Wrapper for OpenVPN %s-debug\n", WRAPPERVERSION
);
60 printf("Wrapper for OpenVPN %s\n", WRAPPERVERSION
);
62 printf("openvpnctrl <option>\n");
63 printf(" Valid options are:\n");
64 printf(" -s --start\n");
65 printf(" starts OpenVPN (implicitly creates chains and firewall rules)\n");
66 printf(" -k --kill\n");
67 printf(" kills/stops OpenVPN\n");
68 printf(" -r --restart\n");
69 printf(" restarts OpenVPN (implicitly creates chains and firewall rules)\n");
70 printf(" -sn2n --start-net-2-net\n");
71 printf(" starts all net2net connections\n");
72 printf(" you may pass a connection name to the switch to only start a specific one\n");
73 printf(" -kn2n --kill-net-2-net\n");
74 printf(" kills all net2net connections\n");
75 printf(" you may pass a connection name to the switch to only start a specific one\n");
76 printf(" -d --display\n");
77 printf(" displays OpenVPN status to syslog\n");
78 printf(" -fwr --firewall-rules\n");
79 printf(" removes current OpenVPN chains and rules and resets them according to the config\n");
80 printf(" -sdo --start-daemon-only\n");
81 printf(" starts OpenVPN daemon only\n");
85 connection
*getConnections() {
88 if (!(fp
= fopen(CONFIG_ROOT
"/ovpn/ovpnconfig", "r"))) {
89 fprintf(stderr
, "Could not open openvpn n2n configuration file.\n");
93 char line
[STRING_SIZE
] = "";
94 char result
[STRING_SIZE
] = "";
97 connection
*conn_first
= NULL
;
98 connection
*conn_last
= NULL
;
99 connection
*conn_curr
;
101 while ((fgets(line
, STRING_SIZE
, fp
) != NULL
)) {
102 if (line
[strlen(line
) - 1] == '\n')
103 line
[strlen(line
) - 1] = '\0';
105 conn_curr
= (connection
*)malloc(sizeof(connection
));
106 memset(conn_curr
, 0, sizeof(connection
));
108 if (conn_first
== NULL
) {
109 conn_first
= conn_curr
;
111 conn_last
->next
= conn_curr
;
113 conn_last
= conn_curr
;
116 char *lineptr
= &line
;
118 if (*lineptr
== NULL
)
122 while (*lineptr
!= NULL
) {
123 if (*lineptr
== ',') {
127 *resultptr
++ = *lineptr
++;
132 strcpy(conn_curr
->status
, result
);
133 } else if (count
== 2) {
134 strcpy(conn_curr
->name
, result
);
135 } else if (count
== 4) {
136 strcpy(conn_curr
->type
, result
);
137 } else if (count
== 7) {
138 strcpy(conn_curr
->role
, result
);
139 } else if (count
== 9) {
140 strcpy(conn_curr
->local_subnet
, result
);
141 } else if (count
== 28) {
142 strcpy(conn_curr
->transfer_subnet
, result
);
143 } else if (count
== 29) {
144 strcpy(conn_curr
->proto
, result
);
145 } else if (count
== 30) {
146 strcpy(conn_curr
->port
, result
);
158 int readPidFile(const char *pidfile
) {
159 FILE *fp
= fopen(pidfile
, "r");
165 fscanf(fp
, "%d", &pid
);
171 void ovpnInit(void) {
172 // Read OpenVPN configuration
173 kv
= initkeyvalues();
174 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings")) {
175 fprintf(stderr
, "Cannot read ovpn settings\n");
179 if (!findkey(kv
, "ENABLED", enablered
)) {
183 if (!findkey(kv
, "ENABLED_BLUE", enableblue
)){
187 if (!findkey(kv
, "ENABLED_ORANGE", enableorange
)){
192 // read interface settings
194 // details for the red int
195 memset(redif
, 0, STRING_SIZE
);
196 if ((ifacefile
= fopen(CONFIG_ROOT
"/red/iface", "r")))
198 if (fgets(redif
, STRING_SIZE
, ifacefile
))
200 if (redif
[strlen(redif
) - 1] == '\n')
201 redif
[strlen(redif
) - 1] = '\0';
206 if (!VALID_DEVICE(redif
))
208 memset(redif
, 0, STRING_SIZE
);
213 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
214 fprintf(stderr
, "Cannot read ethernet settings\n");
218 if (strcmp(enableblue
, "on") == 0) {
219 if (!findkey(kv
, "BLUE_DEV", blueif
)) {
224 if (strcmp(enableorange
, "on") == 0) {
225 if (!findkey(kv
, "ORANGE_DEV", orangeif
)) {
232 void executeCommand(char *command
) {
234 printf(strncat(command
, "\n", 2));
236 safe_system(strncat(command
, " >/dev/null 2>&1", 17));
239 void addRule(const char *chain
, const char *interface
, const char *protocol
, const char *port
) {
240 char command
[STRING_SIZE
];
242 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -i %s -p %s --dport %s -j ACCEPT",
243 chain
, interface
, protocol
, port
);
244 executeCommand(command
);
247 void flushChain(char *chain
) {
248 char str
[STRING_SIZE
];
250 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -F %s", chain
);
254 void flushChainNAT(char *chain
) {
255 char str
[STRING_SIZE
];
257 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -t nat -F %s", chain
);
261 char* calcTransferNetAddress(const connection
* conn
) {
262 char *subnetmask
= strdup(conn
->transfer_subnet
);
263 char *address
= strsep(&subnetmask
, "/");
265 if ((address
== NULL
) || (subnetmask
== NULL
)) {
269 in_addr_t _address
= inet_addr(address
);
270 in_addr_t _subnetmask
= inet_addr(subnetmask
);
271 _address
&= _subnetmask
;
273 if (strcmp(conn
->role
, "server") == 0) {
275 } else if (strcmp(conn
->role
, "client") == 0) {
281 struct in_addr address_info
;
282 address_info
.s_addr
= _address
;
284 return inet_ntoa(address_info
);
287 fprintf(stderr
, "Could not determine transfer net address: %s\n", conn
->name
);
293 char* getLocalSubnetAddress(const connection
* conn
) {
294 kv
= initkeyvalues();
295 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
296 fprintf(stderr
, "Cannot read ethernet settings\n");
300 const char *zones
[] = {"GREEN", "BLUE", "ORANGE", NULL
};
303 // Get net address of the local openvpn subnet.
304 char *subnetmask
= strdup(conn
->local_subnet
);
305 char *address
= strsep(&subnetmask
, "/");
307 if ((address
== NULL
) || (subnetmask
== NULL
)) {
311 in_addr_t _address
= inet_addr(address
);
312 in_addr_t _subnetmask
= inet_addr(subnetmask
);
314 in_addr_t _netaddr
= (_address
& _subnetmask
);
315 in_addr_t _broadcast
= (_address
| ~_subnetmask
);
317 char zone_address_key
[STRING_SIZE
];
318 char zone_address
[STRING_SIZE
];
324 snprintf(zone_address_key
, STRING_SIZE
, "%s_ADDRESS", zone
);
326 if (!findkey(kv
, zone_address_key
, zone_address
))
329 zone_addr
= inet_addr(zone_address
);
330 if ((zone_addr
> _netaddr
) && (zone_addr
< _broadcast
)) {
333 return strdup(zone_address
);
338 fprintf(stderr
, "Could not determine local subnet address: %s\n", conn
->name
);
344 void setFirewallRules(void) {
345 char protocol
[STRING_SIZE
] = "";
346 char dport
[STRING_SIZE
] = "";
347 char dovpnip
[STRING_SIZE
] = "";
349 kv
= initkeyvalues();
350 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings"))
352 fprintf(stderr
, "Cannot read ovpn settings\n");
356 /* we got one device, so lets proceed further */
357 if (!findkey(kv
, "DDEST_PORT", dport
)){
358 fprintf(stderr
, "Cannot read DDEST_PORT\n");
362 if (!findkey(kv
, "DPROTOCOL", protocol
)){
363 fprintf(stderr
, "Cannot read DPROTOCOL\n");
367 if (!findkey(kv
, "VPN_IP", dovpnip
)){
368 fprintf(stderr
, "Cannot read VPN_IP\n");
373 flushChain(OVPNINPUT
);
374 flushChain(OVPNBLOCK
);
375 flushChainNAT(OVPNNAT
);
377 // set firewall rules
378 if (!strcmp(enablered
, "on") && strlen(redif
))
379 addRule(OVPNINPUT
, redif
, protocol
, dport
);
380 if (!strcmp(enableblue
, "on") && strlen(blueif
))
381 addRule(OVPNINPUT
, blueif
, protocol
, dport
);
382 if (!strcmp(enableorange
, "on") && strlen(orangeif
))
383 addRule(OVPNINPUT
, orangeif
, protocol
, dport
);
385 // read connection configuration
386 connection
*conn
= getConnections();
388 // set firewall rules for n2n connections
389 char command
[STRING_SIZE
];
390 char *local_subnet_address
= NULL
;
391 char *transfer_subnet_address
= NULL
;
392 while (conn
!= NULL
) {
393 if (strcmp(conn
->type
, "net") == 0) {
394 addRule(OVPNINPUT
, redif
, conn
->proto
, conn
->port
);
396 /* Block all communication from the transfer nets. */
397 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -s %s -j DROP",
398 OVPNBLOCK
, conn
->transfer_subnet
);
399 executeCommand(command
);
401 local_subnet_address
= getLocalSubnetAddress(conn
);
402 transfer_subnet_address
= calcTransferNetAddress(conn
);
404 if ((local_subnet_address
) && (transfer_subnet_address
)) {
405 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -t nat -A %s -s %s -j SNAT --to-source %s",
406 OVPNNAT
, transfer_subnet_address
, local_subnet_address
);
407 executeCommand(command
);
415 void stopDaemon(void) {
416 char command
[STRING_SIZE
];
418 int pid
= readPidFile("/var/run/openvpn.pid");
423 fprintf(stderr
, "Killing PID %d.\n", pid
);
426 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f /var/run/openvpn.pid");
427 executeCommand(command
);
430 void startDaemon(void) {
431 char command
[STRING_SIZE
];
433 if (!((strcmp(enablered
, "on") == 0) || (strcmp(enableblue
, "on") == 0) || (strcmp(enableorange
, "on") == 0))) {
434 fprintf(stderr
, "OpenVPN is not enabled on any interface\n");
437 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
438 executeCommand(command
);
439 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --config /var/ipfire/ovpn/server.conf");
440 executeCommand(command
);
444 int startNet2Net(char *name
) {
445 connection
*conn
= NULL
;
446 connection
*conn_iter
;
448 conn_iter
= getConnections();
451 if ((strcmp(conn_iter
->type
, "net") == 0) && (strcmp(conn_iter
->name
, name
) == 0)) {
455 conn_iter
= conn_iter
->next
;
459 fprintf(stderr
, "Connection not found.\n");
463 if (strcmp(conn
->status
, "on") != 0) {
464 fprintf(stderr
, "Connection '%s' is not enabled.\n", conn
->name
);
468 fprintf(stderr
, "Starting connection %s...\n", conn
->name
);
470 char configfile
[STRING_SIZE
];
471 snprintf(configfile
, STRING_SIZE
- 1, CONFIG_ROOT
"/ovpn/n2nconf/%s/%s.conf",
472 conn
->name
, conn
->name
);
474 FILE *fp
= fopen(configfile
, "r");
476 fprintf(stderr
, "Could not find configuration file for connection '%s' at '%s'.\n",
477 conn
->name
, configfile
);
482 // Make sure all firewall rules are up to date.
485 char command
[STRING_SIZE
];
486 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
487 executeCommand(command
);
488 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --config %s", configfile
);
489 executeCommand(command
);
494 int killNet2Net(char *name
) {
495 connection
*conn
= NULL
;
496 connection
*conn_iter
;
498 conn_iter
= getConnections();
501 if (strcmp(conn_iter
->name
, name
) == 0) {
505 conn_iter
= conn_iter
->next
;
509 fprintf(stderr
, "Connection not found.\n");
513 char pidfile
[STRING_SIZE
];
514 snprintf(pidfile
, STRING_SIZE
- 1, "/var/run/%sn2n.pid", conn
->name
);
516 int pid
= readPidFile(pidfile
);
518 fprintf(stderr
, "Could not read pid file of connection %s.", conn
->name
);
522 fprintf(stderr
, "Killing connection %s (PID %d)...\n", conn
->name
, pid
);
525 char command
[STRING_SIZE
];
526 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f %s", pidfile
);
527 executeCommand(command
);
532 void startAllNet2Net() {
533 int exitcode
= 0, _exitcode
= 0;
535 connection
*conn
= getConnections();
538 /* Skip all connections that are not of type "net" or disabled. */
539 if ((strcmp(conn
->type
, "net") != 0) || (strcmp(conn
->status
, "on") != 0)) {
544 _exitcode
= startNet2Net(conn
->name
);
547 if (_exitcode
> exitcode
) {
548 exitcode
= _exitcode
;
555 void killAllNet2Net() {
556 int exitcode
= 0, _exitcode
= 0;
558 connection
*conn
= getConnections();
561 /* Skip all connections that are not of type "net". */
562 if (strcmp(conn
->type
, "net") != 0) {
567 _exitcode
= killNet2Net(conn
->name
);
570 if (_exitcode
> exitcode
) {
571 exitcode
= _exitcode
;
578 void displayopenvpn(void) {
579 char command
[STRING_SIZE
];
581 snprintf(command
, STRING_SIZE
- 1, "/bin/killall -sSIGUSR2 openvpn");
582 executeCommand(command
);
585 int main(int argc
, char *argv
[]) {
594 if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
595 startNet2Net(argv
[2]);
598 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
599 killNet2Net(argv
[2]);
607 if( (strcmp(argv
[1], "-k") == 0) || (strcmp(argv
[1], "--kill") == 0) ) {
611 else if( (strcmp(argv
[1], "-d") == 0) || (strcmp(argv
[1], "--display") == 0) ) {
618 if( (strcmp(argv
[1], "-s") == 0) || (strcmp(argv
[1], "--start") == 0) ) {
623 else if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
627 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
631 else if( (strcmp(argv
[1], "-sdo") == 0) || (strcmp(argv
[1], "--start-daemon-only") == 0) ) {
635 else if( (strcmp(argv
[1], "-r") == 0) || (strcmp(argv
[1], "--restart") == 0) ) {
641 else if( (strcmp(argv
[1], "-fwr") == 0) || (strcmp(argv
[1], "--firewall-rules") == 0) ) {