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 },
{ "UnregisterCounter", "o", "", unregister_counter },
{ "CreateSession", "a{sv}o", "o", create_session },
{ "DestroySession", "o", "", destroy_session },
+ { "RequestPrivateNetwork", "", "",
+ request_private_network },
+ { "ReleasePrivateNetwork", "", "",
+ release_private_network },
{ },
};
#include <gdhcp/gdhcp.h>
+#include <gdbus.h>
+
#define BRIDGE_PROC_DIR "/proc/sys/net/bridge"
#define BRIDGE_NAME "tether"
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)
{
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;
}
disable_bridge(BRIDGE_NAME);
remove_bridge(BRIDGE_NAME);
}
+
+ if (connection == NULL)
+ return;
+
+ g_hash_table_destroy(pn_hash);
+ dbus_connection_unref(connection);
}