1 #define _XOPEN_SOURCE 500
9 #include <netinet/in.h>
14 #include "libsmooth.h"
19 struct keyvalue
*kv
= NULL
;
20 FILE *ifacefile
= NULL
;
22 char redif
[STRING_SIZE
];
23 char blueif
[STRING_SIZE
];
24 char orangeif
[STRING_SIZE
];
25 char enablered
[STRING_SIZE
] = "off";
26 char enableblue
[STRING_SIZE
] = "off";
27 char enableorange
[STRING_SIZE
] = "off";
30 char OVPNINPUT
[STRING_SIZE
] = "OVPNINPUT";
31 char OVPNBLOCK
[STRING_SIZE
] = "OVPNBLOCK";
32 char OVPNNAT
[STRING_SIZE
] = "OVPNNAT";
33 char WRAPPERVERSION
[STRING_SIZE
] = "ipfire-2.2.4";
35 struct connection_struct
{
36 char name
[STRING_SIZE
];
37 char type
[STRING_SIZE
];
38 char proto
[STRING_SIZE
];
39 char status
[STRING_SIZE
];
40 char local_subnet
[STRING_SIZE
];
41 char transfer_subnet
[STRING_SIZE
];
42 char role
[STRING_SIZE
];
43 char port
[STRING_SIZE
];
44 struct connection_struct
*next
;
47 typedef struct connection_struct connection
;
49 void exithandler(void)
60 printf("Wrapper for OpenVPN %s-debug\n", WRAPPERVERSION
);
62 printf("Wrapper for OpenVPN %s\n", WRAPPERVERSION
);
64 printf("openvpnctrl <option>\n");
65 printf(" Valid options are:\n");
66 printf(" -s --start\n");
67 printf(" starts OpenVPN (implicitly creates chains and firewall rules)\n");
68 printf(" -k --kill\n");
69 printf(" kills/stops OpenVPN\n");
70 printf(" -r --restart\n");
71 printf(" restarts OpenVPN (implicitly creates chains and firewall rules)\n");
72 printf(" -sn2n --start-net-2-net\n");
73 printf(" starts all net2net connections\n");
74 printf(" you may pass a connection name to the switch to only start a specific one\n");
75 printf(" -kn2n --kill-net-2-net\n");
76 printf(" kills all net2net connections\n");
77 printf(" you may pass a connection name to the switch to only start a specific one\n");
78 printf(" -drrd --delete-rrd\n");
79 printf(" Deletes the RRD data for a specific client\n");
80 printf(" you need to pass a connection name (RW) to the switch to delete the directory (case sensitive)\n");
81 printf(" -d --display\n");
82 printf(" displays OpenVPN status to syslog\n");
83 printf(" -fwr --firewall-rules\n");
84 printf(" removes current OpenVPN chains and rules and resets them according to the config\n");
85 printf(" -sdo --start-daemon-only\n");
86 printf(" starts OpenVPN daemon only\n");
90 connection
*getConnections() {
93 if (!(fp
= fopen(CONFIG_ROOT
"/ovpn/ovpnconfig", "r"))) {
94 fprintf(stderr
, "Could not open openvpn n2n configuration file.\n");
98 char line
[STRING_SIZE
] = "";
99 char result
[STRING_SIZE
] = "";
102 connection
*conn_first
= NULL
;
103 connection
*conn_last
= NULL
;
104 connection
*conn_curr
;
106 while ((fgets(line
, STRING_SIZE
, fp
) != NULL
)) {
107 if (line
[strlen(line
) - 1] == '\n')
108 line
[strlen(line
) - 1] = '\0';
110 conn_curr
= (connection
*)malloc(sizeof(connection
));
111 memset(conn_curr
, 0, sizeof(connection
));
113 if (conn_first
== NULL
) {
114 conn_first
= conn_curr
;
116 conn_last
->next
= conn_curr
;
118 conn_last
= conn_curr
;
121 char *lineptr
= &line
;
123 if (*lineptr
== NULL
)
127 while (*lineptr
!= NULL
) {
128 if (*lineptr
== ',') {
132 *resultptr
++ = *lineptr
++;
137 strcpy(conn_curr
->status
, result
);
138 } else if (count
== 2) {
139 strcpy(conn_curr
->name
, result
);
140 } else if (count
== 4) {
141 strcpy(conn_curr
->type
, result
);
142 } else if (count
== 7) {
143 strcpy(conn_curr
->role
, result
);
144 } else if (count
== 9) {
145 strcpy(conn_curr
->local_subnet
, result
);
146 } else if (count
== 28) {
147 strcpy(conn_curr
->transfer_subnet
, result
);
148 } else if (count
== 29) {
149 strcpy(conn_curr
->proto
, result
);
150 } else if (count
== 30) {
151 strcpy(conn_curr
->port
, result
);
163 int readPidFile(const char *pidfile
) {
164 FILE *fp
= fopen(pidfile
, "r");
170 fscanf(fp
, "%d", &pid
);
176 int readExternalAddress(char* address
) {
177 FILE *fp
= fopen("/var/ipfire/red/local-ipaddress", "r");
181 int r
= fscanf(fp
, "%s", address
);
187 /* In case the read IP address is not valid, we empty
188 * the content of address and return non-zero. */
189 if (!VALID_IP(address
))
199 void ovpnInit(void) {
200 // Read OpenVPN configuration
201 kv
= initkeyvalues();
202 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings")) {
203 fprintf(stderr
, "Cannot read ovpn settings\n");
207 if (!findkey(kv
, "ENABLED", enablered
)) {
211 if (!findkey(kv
, "ENABLED_BLUE", enableblue
)){
215 if (!findkey(kv
, "ENABLED_ORANGE", enableorange
)){
220 // read interface settings
222 // details for the red int
223 memset(redif
, 0, STRING_SIZE
);
224 if ((ifacefile
= fopen(CONFIG_ROOT
"/red/iface", "r")))
226 if (fgets(redif
, STRING_SIZE
, ifacefile
))
228 if (redif
[strlen(redif
) - 1] == '\n')
229 redif
[strlen(redif
) - 1] = '\0';
234 if (!VALID_DEVICE(redif
))
236 memset(redif
, 0, STRING_SIZE
);
241 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
242 fprintf(stderr
, "Cannot read ethernet settings\n");
246 if (strcmp(enableblue
, "on") == 0) {
247 if (!findkey(kv
, "BLUE_DEV", blueif
)) {
252 if (strcmp(enableorange
, "on") == 0) {
253 if (!findkey(kv
, "ORANGE_DEV", orangeif
)) {
260 void executeCommand(char *command
) {
262 printf(strncat(command
, "\n", 2));
264 safe_system(strncat(command
, " >/dev/null 2>&1", 17));
267 void addRule(const char *chain
, const char *interface
, const char *protocol
, const char *port
) {
268 char command
[STRING_SIZE
];
270 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -i %s -p %s --dport %s -j ACCEPT",
271 chain
, interface
, protocol
, port
);
272 executeCommand(command
);
275 void flushChain(char *chain
) {
276 char str
[STRING_SIZE
];
278 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -F %s", chain
);
282 void flushChainNAT(char *chain
) {
283 char str
[STRING_SIZE
];
285 snprintf(str
, STRING_SIZE
- 1, "/sbin/iptables -t nat -F %s", chain
);
289 char* calcTransferNetAddress(const connection
* conn
) {
290 char *subnetmask
= strdup(conn
->transfer_subnet
);
291 char *address
= strsep(&subnetmask
, "/");
293 if ((address
== NULL
) || (subnetmask
== NULL
)) {
297 in_addr_t _address
= inet_addr(address
);
298 in_addr_t _subnetmask
= inet_addr(subnetmask
);
299 _address
&= _subnetmask
;
301 if (strcmp(conn
->role
, "server") == 0) {
303 } else if (strcmp(conn
->role
, "client") == 0) {
309 struct in_addr address_info
;
310 address_info
.s_addr
= _address
;
312 return inet_ntoa(address_info
);
315 fprintf(stderr
, "Could not determine transfer net address: %s\n", conn
->name
);
321 char* getLocalSubnetAddress(const connection
* conn
) {
322 kv
= initkeyvalues();
323 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ethernet/settings")) {
324 fprintf(stderr
, "Cannot read ethernet settings\n");
328 const char *zones
[] = {"GREEN", "BLUE", "ORANGE", NULL
};
331 // Get net address of the local openvpn subnet.
332 char *subnetmask
= strdup(conn
->local_subnet
);
333 char *address
= strsep(&subnetmask
, "/");
335 if ((address
== NULL
) || (subnetmask
== NULL
)) {
339 in_addr_t _address
= inet_addr(address
);
340 in_addr_t _subnetmask
= inet_addr(subnetmask
);
342 in_addr_t _netaddr
= (_address
& _subnetmask
);
343 in_addr_t _broadcast
= (_address
| ~_subnetmask
);
345 char zone_address_key
[STRING_SIZE
];
346 char zone_address
[STRING_SIZE
];
352 snprintf(zone_address_key
, STRING_SIZE
, "%s_ADDRESS", zone
);
354 if (!findkey(kv
, zone_address_key
, zone_address
))
357 zone_addr
= inet_addr(zone_address
);
358 if ((zone_addr
> _netaddr
) && (zone_addr
< _broadcast
)) {
361 return strdup(zone_address
);
366 fprintf(stderr
, "Could not determine local subnet address: %s\n", conn
->name
);
372 void setFirewallRules(void) {
373 char command
[STRING_SIZE
];
374 char protocol
[STRING_SIZE
] = "";
375 char dport
[STRING_SIZE
] = "";
376 char dovpnip
[STRING_SIZE
] = "";
378 kv
= initkeyvalues();
379 if (!readkeyvalues(kv
, CONFIG_ROOT
"/ovpn/settings"))
381 fprintf(stderr
, "Cannot read ovpn settings\n");
385 /* we got one device, so lets proceed further */
386 if (!findkey(kv
, "DDEST_PORT", dport
)){
387 fprintf(stderr
, "Cannot read DDEST_PORT\n");
391 if (!findkey(kv
, "DPROTOCOL", protocol
)){
392 fprintf(stderr
, "Cannot read DPROTOCOL\n");
396 if (!findkey(kv
, "VPN_IP", dovpnip
)){
397 fprintf(stderr
, "Cannot read VPN_IP\n");
402 flushChain(OVPNINPUT
);
403 flushChain(OVPNBLOCK
);
404 flushChainNAT(OVPNNAT
);
406 // set firewall rules
407 if (!strcmp(enablered
, "on") && strlen(redif
))
408 addRule(OVPNINPUT
, redif
, protocol
, dport
);
409 if (!strcmp(enableblue
, "on") && strlen(blueif
))
410 addRule(OVPNINPUT
, blueif
, protocol
, dport
);
411 if (!strcmp(enableorange
, "on") && strlen(orangeif
))
412 addRule(OVPNINPUT
, orangeif
, protocol
, dport
);
414 /* Allow ICMP error messages to pass. */
415 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -p icmp"
416 " -m conntrack --ctstate RELATED -j RETURN", OVPNBLOCK
);
417 executeCommand(command
);
419 // read connection configuration
420 connection
*conn
= getConnections();
422 // set firewall rules for n2n connections
423 char *local_subnet_address
= NULL
;
424 char *transfer_subnet_address
= NULL
;
425 while (conn
!= NULL
) {
426 if (strcmp(conn
->type
, "net") == 0) {
427 addRule(OVPNINPUT
, redif
, conn
->proto
, conn
->port
);
429 /* Block all communication from the transfer nets. */
430 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -A %s -s %s -j DROP",
431 OVPNBLOCK
, conn
->transfer_subnet
);
432 executeCommand(command
);
434 local_subnet_address
= getLocalSubnetAddress(conn
);
435 transfer_subnet_address
= calcTransferNetAddress(conn
);
437 if ((local_subnet_address
) && (transfer_subnet_address
)) {
438 snprintf(command
, STRING_SIZE
- 1, "/sbin/iptables -t nat -A %s -s %s -j SNAT --to-source %s",
439 OVPNNAT
, transfer_subnet_address
, local_subnet_address
);
440 executeCommand(command
);
448 void stopDaemon(void) {
449 char command
[STRING_SIZE
];
451 int pid
= readPidFile("/var/run/openvpn.pid");
456 fprintf(stderr
, "Killing PID %d.\n", pid
);
459 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f /var/run/openvpn.pid");
460 executeCommand(command
);
463 void startDaemon(void) {
464 char command
[STRING_SIZE
];
466 if (!((strcmp(enablered
, "on") == 0) || (strcmp(enableblue
, "on") == 0) || (strcmp(enableorange
, "on") == 0))) {
467 fprintf(stderr
, "OpenVPN is not enabled on any interface\n");
470 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
471 executeCommand(command
);
472 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --config /var/ipfire/ovpn/server.conf");
473 executeCommand(command
);
474 snprintf(command
, STRING_SIZE
-1, "/bin/chown root.nobody /var/run/ovpnserver.log");
475 executeCommand(command
);
476 snprintf(command
, STRING_SIZE
-1, "/bin/chmod 644 /var/run/ovpnserver.log");
477 executeCommand(command
);
481 int startNet2Net(char *name
) {
482 connection
*conn
= NULL
;
483 connection
*conn_iter
;
485 conn_iter
= getConnections();
488 if ((strcmp(conn_iter
->type
, "net") == 0) && (strcmp(conn_iter
->name
, name
) == 0)) {
492 conn_iter
= conn_iter
->next
;
496 fprintf(stderr
, "Connection not found.\n");
500 if (strcmp(conn
->status
, "on") != 0) {
501 fprintf(stderr
, "Connection '%s' is not enabled.\n", conn
->name
);
505 fprintf(stderr
, "Starting connection %s...\n", conn
->name
);
507 char configfile
[STRING_SIZE
];
508 snprintf(configfile
, STRING_SIZE
- 1, CONFIG_ROOT
"/ovpn/n2nconf/%s/%s.conf",
509 conn
->name
, conn
->name
);
511 FILE *fp
= fopen(configfile
, "r");
513 fprintf(stderr
, "Could not find configuration file for connection '%s' at '%s'.\n",
514 conn
->name
, configfile
);
519 // Make sure all firewall rules are up to date.
522 // Get the external IP address.
523 char address
[STRING_SIZE
] = "";
524 int r
= readExternalAddress(address
);
526 fprintf(stderr
, "Could not read the external address\n");
530 char command
[STRING_SIZE
];
531 snprintf(command
, STRING_SIZE
-1, "/sbin/modprobe tun");
532 executeCommand(command
);
533 snprintf(command
, STRING_SIZE
-1, "/usr/sbin/openvpn --local %s --config %s", address
, configfile
);
534 executeCommand(command
);
539 int killNet2Net(char *name
) {
540 connection
*conn
= NULL
;
541 connection
*conn_iter
;
543 conn_iter
= getConnections();
546 if (strcmp(conn_iter
->name
, name
) == 0) {
550 conn_iter
= conn_iter
->next
;
554 fprintf(stderr
, "Connection not found.\n");
558 char pidfile
[STRING_SIZE
];
559 snprintf(pidfile
, STRING_SIZE
- 1, "/var/run/%sn2n.pid", conn
->name
);
561 int pid
= readPidFile(pidfile
);
563 fprintf(stderr
, "Could not read pid file of connection %s.", conn
->name
);
567 fprintf(stderr
, "Killing connection %s (PID %d)...\n", conn
->name
, pid
);
570 char command
[STRING_SIZE
];
571 snprintf(command
, STRING_SIZE
- 1, "/bin/rm -f %s", pidfile
);
572 executeCommand(command
);
578 static int recursive_remove_callback(const char* fpath
, const struct stat
* sb
, int typeflag
, struct FTW
* ftwbuf
) {
579 int rv
= remove(fpath
);
586 static int recursive_remove(const char* path
) {
587 return nftw(path
, recursive_remove_callback
, 64, FTW_DEPTH
| FTW_PHYS
);
590 int deleterrd(char *name
) {
591 char rrd_dir
[STRING_SIZE
];
593 connection
*conn
= getConnections();
595 if (strcmp(conn
->name
, name
) != 0) {
600 // Handle RW connections
601 if (strcmp(conn
->type
, "host") == 0) {
602 snprintf(rrd_dir
, STRING_SIZE
- 1, "/var/log/rrd/collectd/localhost/openvpn-%s", name
);
604 // Handle N2N connections
605 } else if (strcmp(conn
->type
, "net") == 0) {
606 snprintf(rrd_dir
, STRING_SIZE
- 1, "/var/log/rrd/collectd/localhost/openvpn-%s-n2n/", name
);
608 // Unhandled connection type
614 return recursive_remove(rrd_dir
);
620 void startAllNet2Net() {
621 int exitcode
= 0, _exitcode
= 0;
623 connection
*conn
= getConnections();
626 /* Skip all connections that are not of type "net" or disabled. */
627 if ((strcmp(conn
->type
, "net") != 0) || (strcmp(conn
->status
, "on") != 0)) {
632 _exitcode
= startNet2Net(conn
->name
);
635 if (_exitcode
> exitcode
) {
636 exitcode
= _exitcode
;
643 void killAllNet2Net() {
644 int exitcode
= 0, _exitcode
= 0;
646 connection
*conn
= getConnections();
649 /* Skip all connections that are not of type "net". */
650 if (strcmp(conn
->type
, "net") != 0) {
655 _exitcode
= killNet2Net(conn
->name
);
658 if (_exitcode
> exitcode
) {
659 exitcode
= _exitcode
;
666 void displayopenvpn(void) {
667 char command
[STRING_SIZE
];
669 snprintf(command
, STRING_SIZE
- 1, "/bin/killall -sSIGUSR2 openvpn");
670 executeCommand(command
);
673 int main(int argc
, char *argv
[]) {
682 if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
683 startNet2Net(argv
[2]);
686 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
687 killNet2Net(argv
[2]);
690 else if( (strcmp(argv
[1], "-drrd") == 0) || (strcmp(argv
[1], "--delete-rrd") == 0) ) {
699 if( (strcmp(argv
[1], "-k") == 0) || (strcmp(argv
[1], "--kill") == 0) ) {
703 else if( (strcmp(argv
[1], "-d") == 0) || (strcmp(argv
[1], "--display") == 0) ) {
710 if( (strcmp(argv
[1], "-s") == 0) || (strcmp(argv
[1], "--start") == 0) ) {
715 else if( (strcmp(argv
[1], "-sn2n") == 0) || (strcmp(argv
[1], "--start-net-2-net") == 0) ) {
719 else if( (strcmp(argv
[1], "-kn2n") == 0) || (strcmp(argv
[1], "--kill-net-2-net") == 0) ) {
723 else if( (strcmp(argv
[1], "-sdo") == 0) || (strcmp(argv
[1], "--start-daemon-only") == 0) ) {
727 else if( (strcmp(argv
[1], "-r") == 0) || (strcmp(argv
[1], "--restart") == 0) ) {
733 else if( (strcmp(argv
[1], "-fwr") == 0) || (strcmp(argv
[1], "--firewall-rules") == 0) ) {