#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
-#include <arpa/inet.h>
#include <dbus/dbus.h>
+#include "device.h"
static const char *INETDEV = "gprs0";
static const char *DEVICES[] = {
NULL
};
+// Run loop active flag
static int running;
+// Number of active tethering connections
static unsigned int active;
static void siginthandler(int sig) {
return 0;
}
-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);
- 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;
- }
+static void added(Device *device, const char *inetdev) {
+ printf("Got org.kernel.kevent.add on %s\n", device->name);
char *runfile = NULL;
- 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));
+ if (asprintf(&runfile, "/var/run/tethering.%s.pid", device->name) == -1) {
+ fprintf(stderr, "Can't construct PID file name for device %s: %s\n", device->name, strerror(errno));
return;
}
char *range = NULL;
- 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));
+ if (asprintf(&range, "%s-%s,3600", device->startaddress, device->endaddress) == -1) {
+ fprintf(stderr, "Can't construct address range parameter for device %s: %s\n", device->name, strerror(errno));
free(runfile);
return;
}
- const char *ifconfig[] = { "/sbin/ifconfig", device, ascaddress, "up", NULL };
+ const char *ifconfig[] = { "/sbin/ifconfig", device->name, device->address, "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 };
+ const char *dnsmasq[] = { "/sbin/start-stop-daemon", "-S", "-p", runfile, "-m", "-b", "-x", "/usr/sbin/dnsmasq", "--", "-k", "-I", "lo", "-i", device->name, "-a", device->address, "-z", "-F", range, NULL };
char *forwsysctl = NULL;
- 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));
+ if (asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", device->name) == -1) {
+ fprintf(stderr, "Can't construct sysctl path for device %s: %s\n", device->name, strerror(errno));
free(runfile);
free(range);
return;
}
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));
+ fprintf(stderr, "Can't construct inet sysctl path for device %s: %s\n", inetdev, strerror(errno));
free(runfile);
free(range);
free(forwsysctl);
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));
+ fprintf(stderr, "Can't enable forwarding on PAN device %s: %s\n", device->name, strerror(errno));
} else {
if (write(ffd, "1", 1) == -1) {
- fprintf(stderr, "Can't enable forwarding on PAN device %s: %s\n", device, strerror(errno));
+ fprintf(stderr, "Can't enable forwarding on PAN device %s: %s\n", device->name, 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));
+ fprintf(stderr, "Can't enable forwarding on WAN device %s (path %s): %s\n", inetdev, inetforwsysctl, strerror(errno));
} else {
if (write(ifd, "1", 1) == -1) {
fprintf(stderr, "Can't enable forwarding on WAN device %s: %s\n", inetdev, strerror(errno));
active++;
}
-static void removed(const char *device, const char *inetdev) {
- printf("Got org.kernel.kevent.remove on %s\n", device);
+static void removed(Device *device, const char *inetdev) {
+ printf("Got org.kernel.kevent.remove on %s\n", device->name);
char *runfile = NULL;
- 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));
+ if (asprintf(&runfile, "/var/run/tethering.%s.pid", device->name) == -1) {
+ fprintf(stderr, "Can't construct PID file name for device %s: %s\n", device->name, strerror(errno));
return;
}
const char *dnsmasq[] = { "/sbin/start-stop-daemon", "-K", "-p", runfile, "-x", "/usr/sbin/dnsmasq", NULL };
if (active == 0) {
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));
+ fprintf(stderr, "Can't construct inet sysctl path for device %s: %s\n", inetdev, strerror(errno));
return;
}
int fd = open(inetforwsysctl, O_WRONLY, 0666);
}
}
-static int finddev(const char* device, const char *devices[], size_t size) {
- int i;
- for (i = 0; i < size; i++) {
- if (strcmp(device, devices[i]) == 0) {
- return i;
- }
- }
- return -1;
-}
-
int main(int argc, const char *argv[]) {
running = 1;
active = 0;
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;
+ Device *devices = NULL;
+ Device *node = NULL;
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++;
+ for (i = 0; DEVICES[i]; i++) {
+ Device *device = device_new(DEVICES[i]);
+ if (device) {
+ device_set_address(device, ADDRESSES[i]);
+ device_set_startaddress(device, STARTADDRESSES[i]);
+ device_set_endaddress(device, ENDADDRESSES[i]);
+ if (device_validate(device)) {
+ node = device_append(node, device);
+ if (!devices) {
+ devices = node;
}
+ } else {
+ device_delete(device);
}
}
}
-
- if (numdevices == 0) {
+
+ if (!devices) {
fprintf(stderr, "Warning, no devices configured. I will just sit here and wait for nicer weather.\n");
}
return 1;
}
- for (i = 0; i < numdevices; i++) {
+ for (node = devices; node; node = node->next) {
char *filter = NULL;
- 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));
+ if (!asprintf(&filter, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/%s'", node->name)) {
+ fprintf(stderr, "Can't construct filter rule for device %s: %s\n", node->name, strerror(errno));
} else {
dbus_bus_add_match(conn, filter, NULL);
free(filter);
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, numdevices);
- if (index >= 0) {
-
- added(devices[index], INETDEV, addresses[index], startaddresses[index], endaddresses[index]);
+ Device *device = device_search(devices, path[last - 1]);
+ if (device) {
+ added(device, INETDEV);
}
}
dbus_free_string_array(path);
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, numdevices);
- if (index >= 0) {
- removed(devices[index], INETDEV);
+ Device *device = device_search(devices, path[last - 1]);
+ if (device) {
+ removed(device, INETDEV);
}
}
dbus_free_string_array(path);
}
}
+ device_delete_all(devices);
dbus_connection_unref(conn);
return 0;
}