]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/misc-progs/openvpnctrl.c
openvpn: Properly remove all RRDs after a connection is removed
[ipfire-2.x.git] / src / misc-progs / openvpnctrl.c
index 2af537272b209fa73c5ff0355d9464946aa5dde9..5d3f8af73b43ba7b8c6f734ae74648c93bfae567 100644 (file)
@@ -1,3 +1,4 @@
+#define _XOPEN_SOURCE 500
 #include <signal.h>
 #include <stdio.h>
 #include <string.h>
@@ -7,6 +8,7 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <fcntl.h>
+#include <ftw.h>
 #include "setuid.h"
 #include "netutil.h"
 #include "libsmooth.h"
@@ -73,6 +75,9 @@ void usage(void)
        printf(" -kn2n --kill-net-2-net\n");
        printf("      kills all net2net connections\n");
        printf("      you may pass a connection name to the switch to only start a specific one\n");
+       printf(" -drrd --delete-rrd\n");
+       printf("      Deletes the RRD data for a specific client\n");
+       printf("      you need to pass a connection name (RW) to the switch to delete the directory (case sensitive)\n");
        printf(" -d   --display\n");
        printf("      displays OpenVPN status to syslog\n");
        printf(" -fwr --firewall-rules\n");
@@ -168,6 +173,29 @@ int readPidFile(const char *pidfile) {
        return pid;
 }
 
+int readExternalAddress(char* address) {
+       FILE *fp = fopen("/var/ipfire/red/local-ipaddress", "r");
+       if (!fp)
+               goto ERROR;
+
+       int r = fscanf(fp, "%s", address);
+       fclose(fp);
+
+       if (r < 0)
+               goto ERROR;
+
+       /* In case the read IP address is not valid, we empty
+        * the content of address and return non-zero. */
+       if (!VALID_IP(address))
+               goto ERROR;
+
+       return 0;
+
+ERROR:
+       address = NULL;
+       return 1;
+}
+
 void ovpnInit(void) {
        // Read OpenVPN configuration
        kv = initkeyvalues();
@@ -342,6 +370,7 @@ ERROR:
 }
 
 void setFirewallRules(void) {
+       char command[STRING_SIZE];
        char protocol[STRING_SIZE] = "";
        char dport[STRING_SIZE] = "";
        char dovpnip[STRING_SIZE] = "";
@@ -382,11 +411,15 @@ void setFirewallRules(void) {
        if (!strcmp(enableorange, "on") && strlen(orangeif))
                addRule(OVPNINPUT, orangeif, protocol, dport);
 
+       /* Allow ICMP error messages to pass. */
+       snprintf(command, STRING_SIZE - 1, "/sbin/iptables -A %s -p icmp"
+               " -m conntrack --ctstate RELATED -j RETURN", OVPNBLOCK);
+       executeCommand(command);
+
        // read connection configuration
        connection *conn = getConnections();
 
        // set firewall rules for n2n connections
-       char command[STRING_SIZE];
        char *local_subnet_address = NULL;
        char *transfer_subnet_address = NULL;
        while (conn != NULL) {
@@ -438,6 +471,10 @@ void startDaemon(void) {
                executeCommand(command);
                snprintf(command, STRING_SIZE-1, "/usr/sbin/openvpn --config /var/ipfire/ovpn/server.conf");
                executeCommand(command);
+               snprintf(command, STRING_SIZE-1, "/bin/chown root.nobody /var/run/ovpnserver.log");
+               executeCommand(command);
+               snprintf(command, STRING_SIZE-1, "/bin/chmod 644 /var/run/ovpnserver.log");
+               executeCommand(command);
        }
 }
 
@@ -482,10 +519,18 @@ int startNet2Net(char *name) {
        // Make sure all firewall rules are up to date.
        setFirewallRules();
 
+       // Get the external IP address.
+       char address[STRING_SIZE] = "";
+       int r = readExternalAddress(address);
+       if (r) {
+               fprintf(stderr, "Could not read the external address\n");
+               exit(1);
+       }
+
        char command[STRING_SIZE];
        snprintf(command, STRING_SIZE-1, "/sbin/modprobe tun");
        executeCommand(command);
-       snprintf(command, STRING_SIZE-1, "/usr/sbin/openvpn --config %s", configfile);
+       snprintf(command, STRING_SIZE-1, "/usr/sbin/openvpn --local %s --config %s", address, configfile);
        executeCommand(command);
 
        return 0;
@@ -529,6 +574,49 @@ int killNet2Net(char *name) {
        return 0;
 }
 
+
+static int recursive_remove_callback(const char* fpath, const struct stat* sb, int typeflag, struct FTW* ftwbuf) {
+       int rv = remove(fpath);
+       if (rv)
+               perror(fpath);
+
+       return rv;
+}
+
+static int recursive_remove(const char* path) {
+       return nftw(path, recursive_remove_callback, 64, FTW_DEPTH | FTW_PHYS);
+}
+
+int deleterrd(char *name) {
+       char rrd_dir[STRING_SIZE];
+
+       connection *conn = getConnections();
+       while(conn) {
+               if (strcmp(conn->name, name) != 0) {
+                       conn = conn->next;
+                       continue;
+               }
+
+               // Handle RW connections
+               if (strcmp(conn->type, "host") == 0) {
+                       snprintf(rrd_dir, STRING_SIZE - 1, "/var/log/rrd/collectd/localhost/openvpn-%s", name);
+
+               // Handle N2N connections
+               } else if (strcmp(conn->type, "net") == 0) {
+                       snprintf(rrd_dir, STRING_SIZE - 1, "/var/log/rrd/collectd/localhost/openvpn-%s-n2n/", name);
+
+               // Unhandled connection type
+               } else {
+                       conn = conn->next;
+                       continue;
+               }
+
+               return recursive_remove(rrd_dir);
+       }
+
+       return 1;
+}
+
 void startAllNet2Net() {
        int exitcode = 0, _exitcode = 0;
 
@@ -598,6 +686,10 @@ int main(int argc, char *argv[]) {
                else if( (strcmp(argv[1], "-kn2n") == 0) || (strcmp(argv[1], "--kill-net-2-net") == 0) ) {
                        killNet2Net(argv[2]);
                        return 0;
+               }
+               else if( (strcmp(argv[1], "-drrd") == 0) || (strcmp(argv[1], "--delete-rrd") == 0) ) {
+                       deleterrd(argv[2]);
+                       return 0;
                } else {
                        usage();
                        return 1;