summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connman.h3
-rw-r--r--src/manager.c38
-rw-r--r--src/tethering.c79
3 files changed, 120 insertions, 0 deletions
diff --git a/src/connman.h b/src/connman.h
index f80d16f7..ab2b52e6 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -456,6 +456,9 @@ void __connman_tethering_update_interface(const char *interface);
void __connman_tethering_set_enabled(void);
void __connman_tethering_set_disabled(void);
+int __connman_private_network_request(const char *owner);
+int __connman_private_network_release(const char *owner);
+
#include <connman/provider.h>
void __connman_provider_append_properties(struct connman_provider *provider, DBusMessageIter *iter);
diff --git a/src/manager.c b/src/manager.c
index 4afed269..05146555 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -591,6 +591,40 @@ static DBusMessage *destroy_session(DBusConnection *conn,
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
+static DBusMessage *request_private_network(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ const char *sender;
+ int err;
+
+ DBG("conn %p", conn);
+
+ sender = dbus_message_get_sender(msg);
+
+ err = __connman_private_network_request(sender);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *release_private_network(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ const char *sender;
+ int err;
+
+ DBG("conn %p", conn);
+
+ sender = dbus_message_get_sender(msg);
+
+ err = __connman_private_network_release(sender);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
static GDBusMethodTable manager_methods[] = {
{ "GetProperties", "", "a{sv}", get_properties },
{ "SetProperty", "sv", "", set_property },
@@ -615,6 +649,10 @@ static GDBusMethodTable manager_methods[] = {
{ "UnregisterCounter", "o", "", unregister_counter },
{ "CreateSession", "a{sv}o", "o", create_session },
{ "DestroySession", "o", "", destroy_session },
+ { "RequestPrivateNetwork", "", "",
+ request_private_network },
+ { "ReleasePrivateNetwork", "", "",
+ release_private_network },
{ },
};
diff --git a/src/tethering.c b/src/tethering.c
index 27f4b0da..00fa3dee 100644
--- a/src/tethering.c
+++ b/src/tethering.c
@@ -35,6 +35,8 @@
#include <gdhcp/gdhcp.h>
+#include <gdbus.h>
+
#define BRIDGE_PROC_DIR "/proc/sys/net/bridge"
#define BRIDGE_NAME "tether"
@@ -48,6 +50,13 @@
static char *default_interface = NULL;
static volatile gint tethering_enabled;
static GDHCPServer *tethering_dhcp_server = NULL;
+static DBusConnection *connection;
+static GHashTable *pn_hash;
+
+struct connman_private_network {
+ char *owner;
+ guint watch;
+};
const char *__connman_tethering_get_bridge(void)
{
@@ -368,12 +377,76 @@ void __connman_tethering_update_interface(const char *interface)
enable_nat(interface);
}
+static void remove_private_network(gpointer user_data)
+{
+ struct connman_private_network *pn = user_data;
+
+ if (pn->watch > 0) {
+ g_dbus_remove_watch(connection, pn->watch);
+ pn->watch = 0;
+ }
+
+ g_free(pn->owner);
+ g_free(pn);
+}
+
+static void owner_disconnect(DBusConnection *connection, void *user_data)
+{
+ struct connman_private_network *pn = user_data;
+
+ DBG("%s died", pn->owner);
+
+ pn->watch = 0;
+
+ g_hash_table_remove(pn_hash, pn->owner);
+}
+
+int __connman_private_network_request(const char *owner)
+{
+ struct connman_private_network *pn;
+
+ pn = g_hash_table_lookup(pn_hash, owner);
+ if (pn != NULL)
+ return -EEXIST;
+
+ pn = g_try_new0(struct connman_private_network, 1);
+ if (pn == NULL)
+ return -ENOMEM;
+
+ pn->owner = g_strdup(owner);
+ pn->watch = g_dbus_add_disconnect_watch(connection, pn->owner,
+ owner_disconnect, pn, NULL);
+
+ g_hash_table_insert(pn_hash, pn->owner, pn);
+
+ return 0;
+}
+
+int __connman_private_network_release(const char *owner)
+{
+ struct connman_private_network *pn;
+
+ pn = g_hash_table_lookup(pn_hash, owner);
+ if (pn == NULL)
+ return -EACCES;
+
+ g_hash_table_remove(pn_hash, owner);
+ return 0;
+}
+
int __connman_tethering_init(void)
{
DBG("");
tethering_enabled = 0;
+ connection = connman_dbus_get_connection();
+ if (connection == NULL)
+ return -EFAULT;
+
+ pn_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, remove_private_network);
+
return 0;
}
@@ -387,4 +460,10 @@ void __connman_tethering_cleanup(void)
disable_bridge(BRIDGE_NAME);
remove_bridge(BRIDGE_NAME);
}
+
+ if (connection == NULL)
+ return;
+
+ g_hash_table_destroy(pn_hash);
+ dbus_connection_unref(connection);
}