From a87f1daabf62c0f45dfb9e1c5f21cec75477d342 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 28 Sep 2007 13:21:42 +0000 Subject: Add support for script execution. --- network/common.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++---- network/common.h | 6 +++- network/connection.c | 6 ++-- network/server.c | 6 ++-- 4 files changed, 99 insertions(+), 14 deletions(-) (limited to 'network') diff --git a/network/common.c b/network/common.c index d818829a..dce12415 100644 --- a/network/common.c +++ b/network/common.c @@ -32,17 +32,21 @@ #include #include #include +#include #include #include #include #include +#include + #include "logging.h" #include "common.h" #include "textfile.h" static int ctl; +static GSList *pids; #define PANU_UUID "00001115-0000-1000-8000-00805f9b34fb" #define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb" @@ -59,6 +63,27 @@ static struct { { NULL } }; +struct bnep_data { + char *devname; + int pid; +}; + +static void script_exited(GPid pid, gint status, gpointer data) +{ + struct bnep_data *bnep = data; + + if (WIFEXITED(status)) + debug("%d exited with status %d", pid, WEXITSTATUS(status)); + else + debug("%d was killed by signal %d", pid, WTERMSIG(status)); + + g_spawn_close_pid(pid); + pid = 0; + + g_free(bnep->devname); + pids = g_slist_remove(pids, bnep); +} + uint16_t bnep_service_id(const char *svc) { int i; @@ -183,26 +208,82 @@ int bnep_connadd(int sk, uint16_t role, char *dev) return 0; } -int bnep_if_up(const char *devname, int up) +static void bnep_setup(gpointer data) { - int sd, err; +} + +int bnep_if_up(const char *devname, const char *script) +{ + int sd, err, pid; struct ifreq ifr; + const char *argv[3]; + struct bnep_data *bnep; sd = socket(AF_INET6, SOCK_DGRAM, 0); + memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, devname); - if (up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; + ifr.ifr_flags |= IFF_UP; - if((ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr)) < 0) { + if ((ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr)) < 0) { err = errno; error("Could not bring up %d. %s(%d)", devname, strerror(err), err); return -err; } + if (!script) + return 0; + + argv[0] = script; + argv[1] = devname; + argv[2] = NULL; + if (!g_spawn_async(NULL, (char **) argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD, bnep_setup, + (gpointer) devname, &pid, NULL)) { + error("Unable to execute %s", argv[0]); + return -1; + } + + bnep = g_new0(struct bnep_data, 1); + bnep->devname = g_strdup(devname); + bnep->pid = pid; + pids = g_slist_append(pids, bnep); + g_child_watch_add(pid, script_exited, bnep); + + return pid; +} + +int bnep_if_down(const char *devname) +{ + int sd, err; + struct ifreq ifr; + GSList *l; + + sd = socket(AF_INET6, SOCK_DGRAM, 0); + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, devname); + + ifr.ifr_flags &= ~IFF_UP; + + if ((ioctl(sd, SIOCSIFFLAGS, (caddr_t) &ifr)) < 0) { + err = errno; + error("Could not bring down %d. %s(%d)", devname, strerror(err), + err); + return -err; + } + + for(l = pids; l; l = g_slist_next(l)) { + struct bnep_data *bnep = l->data; + + if (strcmp(devname, bnep->devname) == 0) { + if (kill(bnep->pid, SIGTERM) < 0) + error("kill(%d, SIGTERM): %s (%d)", bnep->pid, + strerror(errno), errno); + break; + } + } + return 0; } diff --git a/network/common.h b/network/common.h index 1d8b57de..de9d753d 100644 --- a/network/common.h +++ b/network/common.h @@ -21,6 +21,9 @@ * */ +#define MAX_PATH_LENGTH 64 /* D-Bus path */ +#define NETWORK_PATH "/org/bluez/network" + int bnep_init(void); int bnep_cleanup(void); @@ -32,6 +35,7 @@ int bnep_kill_connection(bdaddr_t *dst); int bnep_kill_all_connections(void); int bnep_connadd(int sk, uint16_t role, char *dev); -int bnep_if_up(const char *devname, int up); +int bnep_if_up(const char *devname, const char *script); +int bnep_if_down(const char *devname); int read_remote_name(bdaddr_t *src, bdaddr_t *dst, char *buf, size_t size); diff --git a/network/connection.c b/network/connection.c index e6a6c151..fb1b2cdf 100644 --- a/network/connection.c +++ b/network/connection.c @@ -157,7 +157,7 @@ static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond, goto failed; } - bnep_if_up(nc->dev, TRUE); + bnep_if_up(nc->dev, nc->script); dbus_connection_emit_signal(connection, nc->path, NETWORK_CONNECTION_INTERFACE, "Connected", @@ -515,7 +515,7 @@ static DBusHandlerResult connection_disconnect(DBusConnection *conn, return DBUS_HANDLER_RESULT_HANDLED; } - bnep_if_up(nc->dev, FALSE); + bnep_if_down(nc->dev); bnep_kill_connection(&nc->dst); reply = dbus_message_new_method_return(msg); @@ -590,7 +590,7 @@ static void connection_free(struct network_conn *nc) g_free(nc->path); if (nc->state == CONNECTED) { - bnep_if_up(nc->dev, FALSE); + bnep_if_down(nc->dev); bnep_kill_connection(&nc->dst); } diff --git a/network/server.c b/network/server.c index 76be55b3..b1257760 100644 --- a/network/server.c +++ b/network/server.c @@ -337,14 +337,14 @@ static void authorization_callback(DBusPendingCall *pcall, void *data) info("Authorization succedded. New connection: %s", devname); response = BNEP_SUCCESS; - if (bridge_add_interface("pan0", devname) < 0) { + if (bridge_add_interface(ns->bridge, devname) < 0) { error("Can't add %s to the bridge: %s(%d)", devname, strerror(errno), errno); goto failed; } - bnep_if_up(devname, TRUE); - bnep_if_up("pan0", TRUE); + bnep_if_up(devname, NULL); + bnep_if_up(ns->bridge, NULL); ns->clients = g_slist_append(ns->clients, g_strdup(s->address)); -- cgit