summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--network/common.c95
-rw-r--r--network/common.h6
-rw-r--r--network/connection.c6
-rw-r--r--network/server.c6
4 files changed, 99 insertions, 14 deletions
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 <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <net/if.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/bnep.h>
+#include <glib.h>
+
#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));