Added more error checking, cleaned up the code
authorGregor Riepl <onitake@gmail.com>
Tue, 20 Jul 2010 23:44:09 +0000 (01:44 +0200)
committerGregor Riepl <onitake@gmail.com>
Tue, 20 Jul 2010 23:44:09 +0000 (01:44 +0200)
Prepared code for configuration file feature

main.c

diff --git a/main.c b/main.c
index b3bb6c4..e659c84 100644 (file)
--- a/main.c
+++ b/main.c
@@ -8,8 +8,8 @@
 #include <sys/types.h>
 #include <sys/sysctl.h>
 #include <sys/wait.h>
+#include <arpa/inet.h>
 #include <dbus/dbus.h>
-//#include <hal/libhal.h>
 
 static const char *INETDEV = "gprs0";
 static const char *DEVICES[] = {
@@ -36,37 +36,11 @@ static const char *ENDADDRESSES[] = {
 static int running;
 static unsigned int active;
 
-static void sigIntHandler(int sig) {
+static void siginthandler(int sig) {
        fprintf(stderr, "SIGINIT received, exiting\n");
        running = 0;
 }
 
-/*static void deviceAdded(LibHalContext *ctx, const char *udi) {
-       DBusError err;
-       dbus_error_init(&err);
-       char *device = libhal_device_get_property_string(ctx, udi, "net.interface", &err);
-       if (!device) {
-               if (dbus_error_is_set(&err)) {
-                       fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
-                       dbus_error_free(&err);
-               }
-       }
-       printf("Device %s added.\n", device);
-}
-
-static void deviceRemoved(LibHalContext *ctx, const char *udi) {
-       DBusError err;
-       dbus_error_init(&err);
-       char *device = libhal_device_get_property_string(ctx, udi, "net.interface", &err);
-       if (!device) {
-               if (dbus_error_is_set(&err)) {
-                       fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
-                       dbus_error_free(&err);
-               }
-       }
-       printf("Device %s removed.\n", device);
-}*/
-
 static int launch(const char *args[]) {
        pid_t pid = fork();
        if (pid == 0) {
@@ -96,77 +70,131 @@ static int launch(const char *args[]) {
        return 0;
 }
 
-static void added(const char *device, const char *inetdev, const char *address, const char *startaddress, const char *endaddress) {
+static void added(const char *device, const char *inetdev, struct in_addr address, struct in_addr startaddress, struct in_addr endaddress) {
        printf("Got org.kernel.kevent.add on %s\n", device);
-       const char *ifconfig[] = { "/sbin/ifconfig", device, address, "up", NULL };
-       launch(ifconfig);
-       const char *modprobe[] = { "/sbin/modprobe", "ipt_MASQUERADE", NULL };
-       launch(modprobe);
-       const char *iptables[] = { "/usr/sbin/iptables", "-t", "nat", "-A", "POSTROUTING", "-o", inetdev, "-j", "MASQUERADE", NULL };
-       launch(iptables);
+       char ascaddress[16];
+       if (inet_ntop(AF_INET, &address, ascaddress, sizeof(ascaddress)) == NULL) {
+               fprintf(stderr, "Can't convert address for device %s\n", device);
+               return;
+       }
+       char ascstartaddress[16];
+       if (inet_ntop(AF_INET, &startaddress, ascstartaddress, sizeof(ascstartaddress)) == NULL) {
+               fprintf(stderr, "Can't convert start address for device %s\n", device);
+               return;
+       }
+       char ascendaddress[16];
+       if (inet_ntop(AF_INET, &endaddress, ascendaddress, sizeof(ascendaddress)) == NULL) {
+               fprintf(stderr, "Can't convert end address for device %s\n", device);
+               return;
+       }
        char *runfile = NULL;
-       asprintf(&runfile, "/var/run/tethering.%s.pid", device);
+       if (asprintf(&runfile, "/var/run/tethering.%s.pid", device) == -1) {
+               fprintf(stderr, "Can't construct PID file name for device %s: %s\n", device, strerror(errno));
+               return;
+       }
        char *range = NULL;
-       asprintf(&range, "%s-%s,3600", startaddress, endaddress);
-       const char *dnsmasq[] = { "/sbin/start-stop-daemon", "-S", "-p", runfile, "-m", "-b", "-x", "/usr/sbin/dnsmasq", "--", "-k", "-I", "lo", "-i", device, "-a", address, "-z", "-F", range, NULL };
-       launch(dnsmasq);
-       free(range);
-       free(runfile);
+       if (asprintf(&range, "%s-%s,3600", ascstartaddress, ascendaddress) == -1) {
+               fprintf(stderr, "Can't construct address range parameter for device %s: %s\n", device, strerror(errno));
+               free(runfile);
+               return;
+       }
+       const char *ifconfig[] = { "/sbin/ifconfig", device, ascaddress, "up", NULL };
+       const char *modprobe[] = { "/sbin/modprobe", "ipt_MASQUERADE", NULL };
+       const char *iptables[] = { "/usr/sbin/iptables", "-t", "nat", "-A", "POSTROUTING", "-o", inetdev, "-j", "MASQUERADE", NULL };
+       const char *dnsmasq[] = { "/sbin/start-stop-daemon", "-S", "-p", runfile, "-m", "-b", "-x", "/usr/sbin/dnsmasq", "--", "-k", "-I", "lo", "-i", device, "-a", ascaddress, "-z", "-F", range, NULL };
        char *forwsysctl = NULL;
-       asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", device);
-       int fd = open(forwsysctl, O_WRONLY, 0666);
-       if (fd < 0) {
-               perror("Can't enable forwarding on PAN device");
-       } else {
-               if (write(fd, "0", 1) == -1) {
-                       perror("Can't enable forwarding on PAN device");
-               }
-               close(fd);
+       if (asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", device) == -1) {
+               fprintf(stderr, "Can't construct sysctl path for device %s: %s\n", device, strerror(errno));
+               free(runfile);
+               free(range);
+               return;
        }
-       free(forwsysctl);
-       asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", inetdev);
-       fd = open(forwsysctl, O_WRONLY, 0666);
-       if (fd < 0) {
-               perror("Can't enable forwarding on WAN device");
-       } else {
-               if (write(fd, "0", 1) == -1) {
-                       perror("Can't enable forwarding on WAN device");
+       char *inetforwsysctl = NULL;
+       if (asprintf(&inetforwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", inetdev) == -1) {
+               fprintf(stderr, "Can't construct inet sysctl path for device %s: %s\n", device, strerror(errno));
+               free(runfile);
+               free(range);
+               free(forwsysctl);
+               return;
+       }
+
+
+       if (launch(ifconfig) == 0) {
+               if (launch(modprobe) == 0) {
+                       if (launch(iptables) == 0) {
+                               if (launch(dnsmasq) == 0) {
+                                       int ffd = open(forwsysctl, O_WRONLY, 0666);
+                                       if (ffd < 0) {
+                                               fprintf(stderr, "Can't enable forwarding on PAN device %s: %s\n", device, strerror(errno));
+                                       } else {
+                                               if (write(ffd, "1", 1) == -1) {
+                                                       fprintf(stderr, "Can't enable forwarding on PAN device %s: %s\n", device, strerror(errno));
+                                               } else {
+                                                       int ifd = open(inetforwsysctl, O_WRONLY, 0666);
+                                                       if (ifd < 0) {
+                                                               fprintf(stderr, "Can't enable forwarding on WAN device %s: %s\n", inetdev, strerror(errno));
+                                                       } else {
+                                                               if (write(ifd, "1", 1) == -1) {
+                                                                       fprintf(stderr, "Can't enable forwarding on WAN device %s: %s\n", inetdev, strerror(errno));
+                                                               }
+                                                               close(ifd);
+                                                       }
+                                               }
+                                               close(ffd);
+                                       }
+                               }
+                       }
                }
-               close(fd);
        }
+
+       free(range);
+       free(runfile);
        free(forwsysctl);
+       free(inetforwsysctl);
+
        active++;
 }
 
 static void removed(const char *device, const char *inetdev) {
        printf("Got org.kernel.kevent.remove on %s\n", device);
+
        char *runfile = NULL;
-       asprintf(&runfile, "/var/run/tethering.%s.pid", device);
+       if (asprintf(&runfile, "/var/run/tethering.%s.pid", device) == -1) {
+               fprintf(stderr, "Can't construct PID file name for device %s: %s\n", device, strerror(errno));
+               return;
+       }
        const char *dnsmasq[] = { "/sbin/start-stop-daemon", "-K", "-p", runfile, "-x", "/usr/sbin/dnsmasq", NULL };
-       launch(dnsmasq);
-       free(runfile);
        const char *iptables[] = { "/usr/sbin/iptables", "-t", "nat", "-D", "POSTROUTING", "-o", inetdev, "-j", "MASQUERADE", NULL };
+
+       // Errors are ignored here: we just disable as much as we can.
+       launch(dnsmasq);
        launch(iptables);
+
+       free(runfile);
+
        if (active > 0) active--;
        if (active == 0) {
-               char *forwsysctl = NULL;
-               asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", inetdev);
-               int fd = open(forwsysctl, O_WRONLY, 0666);
+               char *inetforwsysctl = NULL;
+               if (asprintf(&inetforwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", inetdev) == -1) {
+                       fprintf(stderr, "Can't construct inet sysctl path for device %s: %s\n", device, strerror(errno));
+                       return;
+               }
+               int fd = open(inetforwsysctl, O_WRONLY, 0666);
                if (fd < 0) {
-                       perror("Can't disable forwarding on WAN device");
+                       fprintf(stderr, "Can't enable forwarding on WAN device %s: %s\n", inetdev, strerror(errno));
                } else {
                        if (write(fd, "0", 1) == -1) {
-                               perror("Can't disable forwarding on WAN device");
+                               fprintf(stderr, "Can't enable forwarding on WAN device %s: %s\n", inetdev, strerror(errno));
                        }
                        close(fd);
                }
-               free(forwsysctl);
+               free(inetforwsysctl);
        }
 }
 
-static int finddev(const char* device, const char *devices[]) {
+static int finddev(const char* device, const char *devices[], size_t size) {
        int i;
-       for (i = 0; devices[i]; i++) {
+       for (i = 0; i < size; i++) {
                if (strcmp(device, devices[i]) == 0) {
                        return i;
                }
@@ -177,7 +205,44 @@ static int finddev(const char* device, const char *devices[]) {
 int main(int argc, const char *argv[]) {
        running = 1;
        active = 0;
-       signal(SIGINT, sigIntHandler);
+       signal(SIGINT, siginthandler);
+
+       size_t sizedevices = sizeof(DEVICES) / sizeof(DEVICES[0]);
+       const char *devices[sizedevices];
+       struct in_addr addresses[sizedevices];
+       struct in_addr startaddresses[sizedevices];
+       struct in_addr endaddresses[sizedevices];
+       size_t numdevices = 0;
+       size_t i;
+       for (i = 0; i < sizedevices; i++) {
+               int err = inet_pton(AF_INET, ADDRESSES[i], &addresses[numdevices]);
+               if (err == 0) {
+                       fprintf(stderr, "Invalid address for device %s: %s\n", DEVICES[i], ADDRESSES[i]);
+               } else if (err == -1) {
+                       fprintf(stderr, "Error converting address for device %s: %s\n", DEVICES[i], ADDRESSES[i]);
+               } else {
+                       int err = inet_pton(AF_INET, STARTADDRESSES[i], &startaddresses[numdevices]);
+                       if (err == 0) {
+                               fprintf(stderr, "Invalid DHCP start address for device %s: %s\n", DEVICES[i], STARTADDRESSES[i]);
+                       } else if (err == -1) {
+                               fprintf(stderr, "Error converting DHCP start address for device %s: %s\n", DEVICES[i], STARTADDRESSES[i]);
+                       } else {
+                               int err = inet_pton(AF_INET, ENDADDRESSES[i], &endaddresses[numdevices]);
+                               if (err == 0) {
+                                       fprintf(stderr, "Invalid DHCP end address for device %s: %s\n", DEVICES[i], ENDADDRESSES[i]);
+                               } else if (err == -1) {
+                                       fprintf(stderr, "Error converting DHCP end address for device %s: %s\n", DEVICES[i], ENDADDRESSES[i]);
+                               } else {
+                                       devices[numdevices] = DEVICES[i];
+                                       numdevices++;
+                               }
+                       }
+               }
+       }
+       
+       if (numdevices == 0) {
+               fprintf(stderr, "Warning, no devices configured. I will just sit here and wait for nicer weather.\n");
+       }
 
        DBusError err;
        dbus_error_init(&err);
@@ -189,75 +254,21 @@ int main(int argc, const char *argv[]) {
        if (!conn) {
                return 1;
        }
-       /*LibHalContext *ctx = libhal_ctx_new();
-       if (!ctx) {
-               fprintf(stderr, "Error occured: Can't create HAL context.\n");
-               return 2;
-       }
-       if (!libhal_ctx_set_dbus_connection(ctx, conn)) {
-               fprintf(stderr, "Error occured: Can't assign DBUS connection to HAL context.\n");
-               return 3;
-       }
-       if (!libhal_ctx_set_device_added(ctx, deviceAdded)) {
-               fprintf(stderr, "Error occured: Can't set device added message handler.\n");
-               return 4;
-       }
-       if (!libhal_ctx_set_device_removed(ctx, deviceRemoved)) {
-               fprintf(stderr, "Error occured: Can't set device removed message handler.\n");
-               return 4;
-       }
-       if (!libhal_ctx_init(ctx, &err)) {
-               if (dbus_error_is_set(&err)) {
-                       fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
-                       dbus_error_free(&err);
-               }
-               return 5;
-       }
-       dbus_bool_t nodisc = TRUE;
-       while (running && nodisc) {
-               nodisc = dbus_connection_read_write_dispatch(conn, 500);
-       }*/
-       //dbus_bus_add_match(conn, "type='signal',interface='org.freedesktop.Hal.Manager',member='DeviceAdded'", NULL);
-       //dbus_bus_add_match(conn, "type='signal',interface='org.freedesktop.Hal.Manager',member='DeviceRemoved'", NULL);
-       //dbus_bus_add_match(conn, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/bnep0'", NULL);
-       //dbus_bus_add_match(conn, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/usb0'", NULL);
-       int i;
-       for (i = 0; DEVICES[i]; i++) {
+
+       for (i = 0; i < numdevices; i++) {
                char *filter = NULL;
-               if (!asprintf(&filter, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/%s'", DEVICES[i])) {
-                       perror("Can't construct filter rule");
+               if (!asprintf(&filter, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/%s'", devices[i])) {
+                       fprintf(stderr, "Can't construct filter rule for device %s: %s\n", devices[i], strerror(errno));
                } else {
                        dbus_bus_add_match(conn, filter, NULL);
                }
        }
        dbus_connection_flush(conn);
+
        while (running) {
                dbus_connection_read_write(conn, 500);
                DBusMessage* msg = dbus_connection_pop_message(conn);
                if (msg) {
-                       /*if (dbus_message_is_signal(msg, "org.freedesktop.Hal.Manager", "DeviceAdded")) {
-                               DBusMessageIter args;
-                               if (!dbus_message_iter_init(msg, &args)) {
-                                       fprintf(stderr, "Message has no arguments!\n");
-                               } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
-                                       fprintf(stderr, "Argument is not a string!\n");
-                               } else {
-                                       char *sigvalue = NULL;
-                                       dbus_message_iter_get_basic(&args, &sigvalue);
-                                       fprintf(stderr, "Got DeviceAdded with value %s\n", sigvalue);
-                               }
-                       } else if (dbus_message_is_signal(msg, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
-                               DBusMessageIter args;
-                               if (!dbus_message_iter_init(msg, &args)) {
-                                       fprintf(stderr, "Message has no arguments!\n");
-                               } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
-                                       fprintf(stderr, "Argument is not a string!\n");
-                               } else {
-                                       char *sigvalue = NULL;
-                                       dbus_message_iter_get_basic(&args, &sigvalue);
-                                       fprintf(stderr, "Got DeviceRemoved with value %s\n", sigvalue);
-                               }
-                       } else */
                        if (dbus_message_is_signal(msg, "org.kernel.kevent", "add")) {
                                char **path = NULL;
                                if (!dbus_message_get_path_decomposed(msg, &path)) {
@@ -268,10 +279,10 @@ int main(int argc, const char *argv[]) {
                                        if (last == 0 || last > 6) {
                                                fprintf(stderr, "Add message has no path or path too long!\n");
                                        } else {
-                                               int index = finddev(path[last - 1], DEVICES);
+                                               int index = finddev(path[last - 1], devices, numdevices);
                                                if (index >= 0) {
                                                        
-                                                       added(DEVICES[index], INETDEV, ADDRESSES[index], STARTADDRESSES[index], ENDADDRESSES[index]);
+                                                       added(devices[index], INETDEV, addresses[index], startaddresses[index], endaddresses[index]);
                                                }
                                        }
                                        dbus_free_string_array(path);
@@ -286,9 +297,9 @@ int main(int argc, const char *argv[]) {
                                        if (last == 0 || last > 6) {
                                                fprintf(stderr, "Remove message has no path or path too long!\n");
                                        } else {
-                                               int index = finddev(path[last - 1], DEVICES);
+                                               int index = finddev(path[last - 1], devices, numdevices);
                                                if (index >= 0) {
-                                                       removed(DEVICES[index], INETDEV);
+                                                       removed(devices[index], INETDEV);
                                                }
                                        }
                                        dbus_free_string_array(path);
@@ -297,13 +308,7 @@ int main(int argc, const char *argv[]) {
                        dbus_message_unref(msg);
                }
        }
-       /*if (!libhal_ctx_shutdown(ctx, &err)) {
-               if (dbus_error_is_set(&err)) {
-                       fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
-                       dbus_error_free(&err);
-               }
-       }
-       libhal_ctx_free(ctx);*/
+
        dbus_connection_unref(conn);
        return 0;
 }