9 #include <sys/sysctl.h>
11 #include <dbus/dbus.h>
12 //#include <hal/libhal.h>
14 static const char *INETDEV = "gprs0";
15 static const char *DEVICES[] = {
20 static const char *ADDRESSES[] = {
25 static const char *STARTADDRESSES[] = {
30 static const char *ENDADDRESSES[] = {
37 static unsigned int active;
39 static void sigIntHandler(int sig) {
40 fprintf(stderr, "SIGINIT received, exiting\n");
44 /*static void deviceAdded(LibHalContext *ctx, const char *udi) {
46 dbus_error_init(&err);
47 char *device = libhal_device_get_property_string(ctx, udi, "net.interface", &err);
49 if (dbus_error_is_set(&err)) {
50 fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
51 dbus_error_free(&err);
54 printf("Device %s added.\n", device);
57 static void deviceRemoved(LibHalContext *ctx, const char *udi) {
59 dbus_error_init(&err);
60 char *device = libhal_device_get_property_string(ctx, udi, "net.interface", &err);
62 if (dbus_error_is_set(&err)) {
63 fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
64 dbus_error_free(&err);
67 printf("Device %s removed.\n", device);
70 static int launch(const char *args[]) {
73 if (execv(args[0], (char **const) args) == -1) {
74 fprintf(stderr, "Error launching external process %s: %s\n", args[0], strerror(errno));
77 } else if (pid == -1) {
78 fprintf(stderr, "Can't fork external process %s: %s\n", args[0], strerror(errno));
82 if (waitpid(pid, &status, 0) == -1) {
83 perror("Error waiting for child process completion");
86 if (WIFEXITED(status)) {
87 if (WEXITSTATUS(status) != 0) {
88 fprintf(stderr, "Child process returned error: %d\n", WEXITSTATUS(status));
91 } else if (WIFSIGNALED(status)) {
92 fprintf(stderr, "Child process killed by signal: %d\n", WTERMSIG(status));
99 static void added(const char *device, const char *inetdev, const char *address, const char *startaddress, const char *endaddress) {
100 printf("Got org.kernel.kevent.add on %s\n", device);
101 const char *ifconfig[] = { "/sbin/ifconfig", device, address, "up", NULL };
103 const char *modprobe[] = { "/sbin/modprobe", "ipt_MASQUERADE", NULL };
105 const char *iptables[] = { "/usr/sbin/iptables", "-t", "nat", "-A", "POSTROUTING", "-o", inetdev, "-j", "MASQUERADE", NULL };
107 char *runfile = NULL;
108 asprintf(&runfile, "/var/run/tethering.%s.pid", device);
110 asprintf(&range, "%s-%s,3600", startaddress, endaddress);
111 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 };
115 char *forwsysctl = NULL;
116 asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", device);
117 int fd = open(forwsysctl, O_WRONLY, 0666);
119 perror("Can't enable forwarding on PAN device");
121 if (write(fd, "0", 1) == -1) {
122 perror("Can't enable forwarding on PAN device");
127 asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", inetdev);
128 fd = open(forwsysctl, O_WRONLY, 0666);
130 perror("Can't enable forwarding on WAN device");
132 if (write(fd, "0", 1) == -1) {
133 perror("Can't enable forwarding on WAN device");
141 static void removed(const char *device, const char *inetdev) {
142 printf("Got org.kernel.kevent.remove on %s\n", device);
143 char *runfile = NULL;
144 asprintf(&runfile, "/var/run/tethering.%s.pid", device);
145 const char *dnsmasq[] = { "/sbin/start-stop-daemon", "-K", "-p", runfile, "-x", "/usr/sbin/dnsmasq", NULL };
148 const char *iptables[] = { "/usr/sbin/iptables", "-t", "nat", "-D", "POSTROUTING", "-o", inetdev, "-j", "MASQUERADE", NULL };
150 if (active > 0) active--;
152 char *forwsysctl = NULL;
153 asprintf(&forwsysctl, "/proc/sys/net/ipv4/conf/%s/forwarding", inetdev);
154 int fd = open(forwsysctl, O_WRONLY, 0666);
156 perror("Can't disable forwarding on WAN device");
158 if (write(fd, "0", 1) == -1) {
159 perror("Can't disable forwarding on WAN device");
167 static int finddev(const char* device, const char *devices[]) {
169 for (i = 0; devices[i]; i++) {
170 if (strcmp(device, devices[i]) == 0) {
177 int main(int argc, const char *argv[]) {
180 signal(SIGINT, sigIntHandler);
183 dbus_error_init(&err);
184 DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
185 if (dbus_error_is_set(&err)) {
186 fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
187 dbus_error_free(&err);
192 /*LibHalContext *ctx = libhal_ctx_new();
194 fprintf(stderr, "Error occured: Can't create HAL context.\n");
197 if (!libhal_ctx_set_dbus_connection(ctx, conn)) {
198 fprintf(stderr, "Error occured: Can't assign DBUS connection to HAL context.\n");
201 if (!libhal_ctx_set_device_added(ctx, deviceAdded)) {
202 fprintf(stderr, "Error occured: Can't set device added message handler.\n");
205 if (!libhal_ctx_set_device_removed(ctx, deviceRemoved)) {
206 fprintf(stderr, "Error occured: Can't set device removed message handler.\n");
209 if (!libhal_ctx_init(ctx, &err)) {
210 if (dbus_error_is_set(&err)) {
211 fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
212 dbus_error_free(&err);
216 dbus_bool_t nodisc = TRUE;
217 while (running && nodisc) {
218 nodisc = dbus_connection_read_write_dispatch(conn, 500);
220 //dbus_bus_add_match(conn, "type='signal',interface='org.freedesktop.Hal.Manager',member='DeviceAdded'", NULL);
221 //dbus_bus_add_match(conn, "type='signal',interface='org.freedesktop.Hal.Manager',member='DeviceRemoved'", NULL);
222 //dbus_bus_add_match(conn, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/bnep0'", NULL);
223 //dbus_bus_add_match(conn, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/usb0'", NULL);
225 for (i = 0; DEVICES[i]; i++) {
227 if (!asprintf(&filter, "type='signal',interface='org.kernel.kevent',path='/org/kernel/class/net/%s'", DEVICES[i])) {
228 perror("Can't construct filter rule");
230 dbus_bus_add_match(conn, filter, NULL);
233 dbus_connection_flush(conn);
235 dbus_connection_read_write(conn, 500);
236 DBusMessage* msg = dbus_connection_pop_message(conn);
238 /*if (dbus_message_is_signal(msg, "org.freedesktop.Hal.Manager", "DeviceAdded")) {
239 DBusMessageIter args;
240 if (!dbus_message_iter_init(msg, &args)) {
241 fprintf(stderr, "Message has no arguments!\n");
242 } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
243 fprintf(stderr, "Argument is not a string!\n");
245 char *sigvalue = NULL;
246 dbus_message_iter_get_basic(&args, &sigvalue);
247 fprintf(stderr, "Got DeviceAdded with value %s\n", sigvalue);
249 } else if (dbus_message_is_signal(msg, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
250 DBusMessageIter args;
251 if (!dbus_message_iter_init(msg, &args)) {
252 fprintf(stderr, "Message has no arguments!\n");
253 } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
254 fprintf(stderr, "Argument is not a string!\n");
256 char *sigvalue = NULL;
257 dbus_message_iter_get_basic(&args, &sigvalue);
258 fprintf(stderr, "Got DeviceRemoved with value %s\n", sigvalue);
261 if (dbus_message_is_signal(msg, "org.kernel.kevent", "add")) {
263 if (!dbus_message_get_path_decomposed(msg, &path)) {
264 fprintf(stderr, "Can't get add message path!\n");
267 for (last = 0; path[last] && last <= 6; last++);
268 if (last == 0 || last > 6) {
269 fprintf(stderr, "Add message has no path or path too long!\n");
271 int index = finddev(path[last - 1], DEVICES);
274 added(DEVICES[index], INETDEV, ADDRESSES[index], STARTADDRESSES[index], ENDADDRESSES[index]);
277 dbus_free_string_array(path);
279 } else if (dbus_message_is_signal(msg, "org.kernel.kevent", "remove")) {
281 if (!dbus_message_get_path_decomposed(msg, &path)) {
282 fprintf(stderr, "Can't get remove message path!\n");
285 for (last = 0; path[last] && last <= 6; last++);
286 if (last == 0 || last > 6) {
287 fprintf(stderr, "Remove message has no path or path too long!\n");
289 int index = finddev(path[last - 1], DEVICES);
291 removed(DEVICES[index], INETDEV);
294 dbus_free_string_array(path);
297 dbus_message_unref(msg);
300 /*if (!libhal_ctx_shutdown(ctx, &err)) {
301 if (dbus_error_is_set(&err)) {
302 fprintf(stderr, "Error %s occured: %s\n", err.name, err.message);
303 dbus_error_free(&err);
306 libhal_ctx_free(ctx);*/
307 dbus_connection_unref(conn);