Send connman mailing list submissions to
[email protected]
To subscribe or unsubscribe via the World Wide Web, visit
https://lists.01.org/mailman/listinfo/connman
or, via email, send a message with subject or body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."
Today's Topics:
1. Re: Crash when running connmand along iwd (Daniel Wagner)
2. Re: [PATCHv6 6/6] wps: add new WPS API for technology
(Daniel Wagner)
3. [PATCH] wifi: implemented feature of tracking tethering
clients (Vasyl Vavrychuk)
----------------------------------------------------------------------
Message: 1
Date: Sun, 28 Oct 2018 22:10:22 +0100
From: Daniel Wagner <[email protected]>
To: Doron Behar <[email protected]>
Cc: [email protected]
Subject: Re: Crash when running connmand along iwd
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8; format=flowed
On 10/28/2018 09:45 PM, Doron Behar wrote:
> Confirmed, thanks.
Okay.
> You have no idea how much I am thrilled connman is being developed and
> that it takes Linux networking to such a wonderful and comfortable
> place.
Thanks!
> Can't wait for the next release.
You are right, the last release is already a few months ago and we have
a bunch of bug fixes and a couple of new features ready.
> Thanks again for creating this beautifully designed software.
:)
Thanks,
Daniel
------------------------------
Message: 2
Date: Sun, 28 Oct 2018 22:21:52 +0100
From: Daniel Wagner <[email protected]>
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCHv6 6/6] wps: add new WPS API for technology
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8; format=flowed
Hi Natsuki-san,
On 10/11/2018 06:07 PM, [email protected] wrote:
> +void connman_technology_add_wps_offered(struct connman_technology
> *technology,
> + const char *path)
> +{
> + char *dup_path = g_strdup(path);
> +
> + if (!dup_path)
> + return;
This check is not necessary, because g_strdup() will panic call abort()
when it fails to allocate memory. So we never get here in this case.
> + technology->wps_offered =
> + g_slist_append(technology->wps_offered, dup_path);
> +}
> +
> +static void append_wps_service_structs(DBusMessageIter *iter, void
> *user_data)
> +{
> + struct connman_technology *technology = user_data;
> + GSList *list;
> +
> + for (list = technology->wps_offered; list; list = list->next) {
> + const char *ident = list->data;
> + struct connman_service *service;
> +
> + service = __connman_service_lookup_from_ident(ident);
> + if (!service)
> + continue;
> + __connman_service_append_struct(service, iter);
> + }
> +}
> +
> +static DBusMessage
> +*create_reply_start_sta_wps_success(
> + struct connman_technology *technology,
> + DBusMessage *reply)
Go with this formatting:
static DBusMessage *create_reply_start_sta_wps_success(
struct connman_technolog *technology,
DBusMessage *reply)
> +{
> + DBusMessage *msg;
> +
> + msg = dbus_message_new_method_return(reply);
> + if (!msg)
> + return NULL;
> +
> + __connman_dbus_append_objpath_dict_array(msg,
> + append_wps_service_structs,
> + technology);
> +
> + return msg;
> +}
> +
> +static void free_wps_offered(gpointer data, gpointer user_data)
> +{
> + if (!data)
> + return;
> +
> + g_free(data);
> +}
> +
> +void
> +connman_technology_reply_start_sta_wps(struct connman_technology *technology,
> + int error)
> +{
> + DBusMessage *reply;
> +
> + if (!technology->wps_reply)
> + return;
> +
> + if (!error) {
> + reply = create_reply_start_sta_wps_success(technology,
> + technology->wps_reply);
> + } else
> + reply = __connman_error_failed(technology->wps_reply, -error);
> +
> + g_dbus_send_message(connection, reply);
> +
> + dbus_message_unref(technology->wps_reply);
> + technology->wps_reply = NULL;
> +
> + g_slist_foreach(technology->wps_offered, free_wps_offered, NULL);
> + g_slist_free(technology->wps_offered);
You can write this as
g_slist_free_full(technology->wps_offered, g_free);
and remove free_wps_offered() completely.
> + technology->wps_offered = NULL;
> +}
> +
> +static int start_wps(struct connman_technology *technology,
> + DBusMessage *msg, enum connman_technology_wps_mode mode)
> +{
> + GSList *tech_drivers;
> + DBusMessageIter iter;
> + enum connman_peer_wps_method wps_method;
> + const char *auth;
> + int err, result = -EOPNOTSUPP;
> +
> + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
> + return -EOPNOTSUPP;
> +
> + __sync_synchronize();
Please remove __sync_synchronize(). This has no effect in a single
threaded application.
> + if (!technology->enabled)
> + return -EACCES;
> +
> + if (!dbus_message_iter_init(msg, &iter))
> + return -EINVAL;
> +
> + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
> + return -EINVAL;
> +
> + dbus_message_iter_get_basic(&iter, &auth);
> +
> + wps_method = __connman_check_wps_method(auth);
> + if (wps_method == CONNMAN_PEER_WPS_UNKNOWN)
> + return -EINVAL;
> + if (wps_method == CONNMAN_PEER_WPS_PBC)
> + auth = NULL;
> +
> + for (tech_drivers = technology->driver_list; tech_drivers;
> + tech_drivers = g_slist_next(tech_drivers)) {
> + struct connman_technology_driver *driver = tech_drivers->data;
> +
> + if (!driver ||
> + !driver->start_wps ||
> + driver->type != CONNMAN_SERVICE_TYPE_WIFI)
> + continue;
hmm, at least write this way:
if (!driver || !driver->start_wps ||
driver->type != CONNMAN_SERVICE_TYPE_WIFI)
continue;
> +
> + err = driver->start_wps(technology, mode, auth);
> +
> + if (result == -EINPROGRESS)
> + continue;
> +
> + if (err == -EINPROGRESS)
> + result = err;
> + }
> +
> + return result;
> +}
> +
> +static DBusMessage *start_ap_wps(DBusConnection *conn, DBusMessage *msg,
> + void *user_data)
> +{
> + struct connman_technology *technology = user_data;
> + int err;
> +
> + /* It is required to enable tethering before starting WPS in AP mode */
> + if (!technology->tethering) {
> + DBG("Error: Tethering is required");
This doesn't look like a real error. I suggest you just remove this DBG
because you send out this:
> + return __connman_error_permission_denied(msg);
which is observable.
Thanks,
Daniel
------------------------------
Message: 3
Date: Mon, 29 Oct 2018 00:37:26 +0200
From: Vasyl Vavrychuk <[email protected]>
To: [email protected]
Cc: Daniel Wagner <[email protected]>, Vasyl Vavrychuk
<[email protected]>
Subject: [PATCH] wifi: implemented feature of tracking tethering
clients
Message-ID: <[email protected]>
wpa_supplicant supports StaAuthorized StaDeauthorized D-Bus signal that
we handle and store information. Then stored information about connected
tethering clients is exposed via GetTetheringClients method and
TetheringClientsChanged signal of manager.
---
Makefile.am | 3 +-
client/commands.c | 27 ++++++++
client/tethering.c | 62 +++++++++++++++++++
client/tethering.h | 38 ++++++++++++
doc/manager-api.txt | 12 ++++
gsupplicant/gsupplicant.h | 4 ++
gsupplicant/supplicant.c | 64 +++++++++++++++++++
include/tethering.h | 36 +++++++++++
plugins/wifi.c | 29 +++++++++
src/connman.h | 3 +
src/manager.c | 24 ++++++++
src/tethering.c | 126 ++++++++++++++++++++++++++++++++++++++
12 files changed, 427 insertions(+), 1 deletion(-)
create mode 100644 client/tethering.c
create mode 100644 client/tethering.h
create mode 100644 include/tethering.h
diff --git a/Makefile.am b/Makefile.am
index d6dfbf1c..4614cb90 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,7 +12,7 @@ include_HEADERS = include/log.h include/plugin.h \
include/storage.h include/provision.h \
include/session.h include/ipaddress.h include/agent.h \
include/inotify.h include/peer.h include/machine.h \
- include/acd.h
+ include/acd.h include/tethering.h
nodist_include_HEADERS = include/version.h
@@ -308,6 +308,7 @@ client_connmanctl_SOURCES = client/dbus_helpers.h
client/dbus_helpers.c \
client/input.h client/input.c \
client/agent.h client/agent.c \
client/peers.h client/peers.c \
+ client/tethering.h client/tethering.c \
client/vpnconnections.h client/vpnconnections.c \
client/main.c
diff --git a/client/commands.c b/client/commands.c
index bf3531fd..26d2c509 100644
--- a/client/commands.c
+++ b/client/commands.c
@@ -318,6 +318,18 @@ static int peers_list(DBusMessageIter *iter,
return 0;
}
+static int tethering_clients_list(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
+ if (!error) {
+ __connmanctl_tethering_clients_list(iter);
+ fprintf(stdout, "\n");
+ } else
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
static int object_properties(DBusMessageIter *iter,
const char *error, void *user_data)
{
@@ -639,6 +651,19 @@ static int cmd_tether(char *args[], int num, struct
connman_option *options)
return tether_set(args[1], set_tethering);
}
+static int cmd_tethering_clients(char *args[], int num, struct connman_option
*options)
+{
+ char *path;
+
+ if (num > 1)
+ return -E2BIG;
+
+ return __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetTetheringClients",
+ tethering_clients_list, NULL, NULL, NULL);
+}
+
static int scan_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
@@ -2730,6 +2755,8 @@ static const struct {
NULL, cmd_tether,
"Enable, disable tethering, set SSID and passphrase for wifi",
lookup_tether },
+ { "tethering_clients", NULL, NULL,
cmd_tethering_clients,
+ "Display tethering clients", NULL },
{ "services", "[<service>]", service_options, cmd_services,
"Display services", lookup_service_arg },
{ "peers", "[peer]", NULL, cmd_peers,
diff --git a/client/tethering.c b/client/tethering.c
new file mode 100644
index 00000000..ce3688a4
--- /dev/null
+++ b/client/tethering.c
@@ -0,0 +1,62 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdio.h>
+
+#include "tethering.h"
+
+void __connmanctl_tethering_clients_list(DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+ char *addr = NULL;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return;
+
+ dbus_message_iter_recurse(iter, &array);
+ while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic(&array, &addr);
+
+ fprintf(stdout, "%s", addr);
+
+ if (dbus_message_iter_has_next(&array))
+ fprintf(stdout, "\n");
+
+ dbus_message_iter_next(&array);
+ }
+
+ dbus_message_iter_next(iter);
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return;
+
+ dbus_message_iter_recurse(iter, &array);
+ while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic(&array, &addr);
+
+ fprintf(stdout, "\n%s %s", "removed", addr);
+
+ if (dbus_message_iter_has_next(&array))
+ fprintf(stdout, "\n");
+
+ dbus_message_iter_next(&array);
+ }
+}
diff --git a/client/tethering.h b/client/tethering.h
new file mode 100644
index 00000000..c6b58de1
--- /dev/null
+++ b/client/tethering.h
@@ -0,0 +1,38 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __CONNMANCTL_TETHERING_H
+#define __CONNMANCTL_TETHERING_H
+
+#include <dbus/dbus.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __connmanctl_tethering_clients_list(DBusMessageIter *iter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMANCTL_TETHERING_H */
diff --git a/doc/manager-api.txt b/doc/manager-api.txt
index 2d2739ff..bfb07bd3 100644
--- a/doc/manager-api.txt
+++ b/doc/manager-api.txt
@@ -46,6 +46,11 @@ Methods dict GetProperties()
Possible Errors: [service].Error.InvalidArguments
+ array{string} GetTetheringClients() [experimental]
+
+ Returns a sorted list of MAC addresses of clients
+ connected to tethered technologies.
+
object ConnectProvider(dict provider) [deprecated]
Connect to a VPN specified by the given provider
@@ -255,6 +260,13 @@ Signals TechnologyAdded(object path, dict
properties)
object changes. For that it is required to watch the
PropertyChanged signal of the peer object.
+ TetheringClientsChanged(array{string}, array{string})
[experimental]
+
+ This signal indicates a change in the tethering clients.
+ List of all tethering clients currently registered
connman is
+ passed via the first array. And a list of tethering
clients that
+ have been removed via the second array.
+
PropertyChanged(string name, variant value)
This signal indicates a changed value of the given
diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h
index db61595b..bfb52db7 100644
--- a/gsupplicant/gsupplicant.h
+++ b/gsupplicant/gsupplicant.h
@@ -352,6 +352,10 @@ struct _GSupplicantCallbacks {
void (*network_changed) (GSupplicantNetwork *network,
const char *property);
void (*network_associated) (GSupplicantNetwork *network);
+ void (*sta_authorized) (GSupplicantInterface *interface,
+ const char *addr);
+ void (*sta_deauthorized) (GSupplicantInterface *interface,
+ const char *addr);
void (*peer_found) (GSupplicantPeer *peer);
void (*peer_lost) (GSupplicantPeer *peer);
void (*peer_changed) (GSupplicantPeer *peer,
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 0cb621b9..12391482 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -614,6 +614,30 @@ static void callback_network_associated(GSupplicantNetwork
*network)
callbacks_pointer->network_associated(network);
}
+static void callback_sta_authorized(GSupplicantInterface *interface,
+ const char *addr)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->sta_authorized)
+ return;
+
+ callbacks_pointer->sta_authorized(interface, addr);
+}
+
+static void callback_sta_deauthorized(GSupplicantInterface *interface,
+ const char *addr)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->sta_deauthorized)
+ return;
+
+ callbacks_pointer->sta_deauthorized(interface, addr);
+}
+
static void callback_peer_found(GSupplicantPeer *peer)
{
if (!callbacks_pointer)
@@ -2731,6 +2755,44 @@ static void signal_network_removed(const char *path,
DBusMessageIter *iter)
interface_network_removed(iter, interface);
}
+static void signal_sta_authorized(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ DBusMessageIter array;
+ const char *addr = NULL;
+
+ SUPPLICANT_DBG("");
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ dbus_message_iter_get_basic(iter, &addr);
+ if (!addr)
+ return;
+
+ callback_sta_authorized(interface, addr);
+}
+
+static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ DBusMessageIter array;
+ const char *addr = NULL;
+
+ SUPPLICANT_DBG("");
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ dbus_message_iter_get_basic(iter, &addr);
+ if (!addr)
+ return;
+
+ callback_sta_deauthorized(interface, addr);
+}
+
static void signal_bss_changed(const char *path, DBusMessageIter *iter)
{
GSupplicantInterface *interface;
@@ -3505,6 +3567,8 @@ static struct {
{ SUPPLICANT_INTERFACE ".Interface", "BSSRemoved",
signal_bss_removed },
{ SUPPLICANT_INTERFACE ".Interface", "NetworkAdded",
signal_network_added },
{ SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved",
signal_network_removed },
+ { SUPPLICANT_INTERFACE ".Interface", "StaAuthorized",
signal_sta_authorized },
+ { SUPPLICANT_INTERFACE ".Interface", "StaDeauthorized",
signal_sta_deauthorized },
{ SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed
},
diff --git a/include/tethering.h b/include/tethering.h
new file mode 100644
index 00000000..0d29b235
--- /dev/null
+++ b/include/tethering.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Connection Manager
+ *
+ * Copyright (C) 2007-2013 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __CONNMAN_TETHERING_H
+#define __CONNMAN_TETHERING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __connman_tethering_client_register(const char *addr);
+void __connman_tethering_client_unregister(const char *addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMAN_TETHERING_H */
diff --git a/plugins/wifi.c b/plugins/wifi.c
index e437daeb..6fa20312 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -55,6 +55,7 @@
#include <connman/provision.h>
#include <connman/utsname.h>
#include <connman/machine.h>
+#include <connman/tethering.h>
#include <gsupplicant/gsupplicant.h>
@@ -2985,6 +2986,32 @@ static void network_associated(GSupplicantNetwork
*network)
interface_state(interface);
}
+static void sta_authorized(GSupplicantInterface *interface,
+ const char *addr)
+{
+ struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
+
+ DBG("wifi %p station %s authorized", wifi, addr);
+
+ if (!wifi || !wifi->tethering)
+ return;
+
+ __connman_tethering_client_register(addr);
+}
+
+static void sta_deauthorized(GSupplicantInterface *interface,
+ const char *addr)
+{
+ struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
+
+ DBG("wifi %p station %s deauthorized", wifi, addr);
+
+ if (!wifi || !wifi->tethering)
+ return;
+
+ __connman_tethering_client_unregister(addr);
+}
+
static void apply_peer_services(GSupplicantPeer *peer,
struct connman_peer *connman_peer)
{
@@ -3205,6 +3232,8 @@ static const GSupplicantCallbacks callbacks = {
.network_removed = network_removed,
.network_changed = network_changed,
.network_associated = network_associated,
+ .sta_authorized = sta_authorized,
+ .sta_deauthorized = sta_deauthorized,
.peer_found = peer_found,
.peer_lost = peer_lost,
.peer_changed = peer_changed,
diff --git a/src/connman.h b/src/connman.h
index 13553833..dfcacc62 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -630,12 +630,15 @@ bool __connman_config_get_bool(GKeyFile *key_file,
bool __connman_config_address_provisioned(const char *address,
const char *netmask);
+#include <connman/tethering.h>
+
int __connman_tethering_init(void);
void __connman_tethering_cleanup(void);
const char *__connman_tethering_get_bridge(void);
int __connman_tethering_set_enabled(void);
void __connman_tethering_set_disabled(void);
+void __connman_tethering_list_clients(DBusMessageIter *array);
int __connman_private_network_request(DBusMessage *msg, const char *owner);
int __connman_private_network_release(const char *path);
diff --git a/src/manager.c b/src/manager.c
index d15ce203..b2de863c 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -214,6 +214,27 @@ static DBusMessage *get_peers(DBusConnection *conn,
return reply;
}
+static DBusMessage *get_tethering_clients(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, array;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+
+ __connman_tethering_list_clients(&array);
+
+ dbus_message_iter_close_container(&iter, &array);
+ return reply;
+}
+
static DBusMessage *connect_provider(DBusConnection *conn,
DBusMessage *msg, void *data)
{
@@ -519,6 +540,9 @@ static const GDBusMethodTable manager_methods[] = {
{ GDBUS_METHOD("GetPeers",
NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
get_peers) },
+ { GDBUS_METHOD("GetTetheringClients",
+ NULL, GDBUS_ARGS({ "tethering_clients", "as" }),
+ get_tethering_clients) },
{ GDBUS_DEPRECATED_ASYNC_METHOD("ConnectProvider",
GDBUS_ARGS({ "provider", "a{sv}" }),
GDBUS_ARGS({ "path", "o" }),
diff --git a/src/tethering.c b/src/tethering.c
index d222afca..61951075 100644
--- a/src/tethering.c
+++ b/src/tethering.c
@@ -61,6 +61,13 @@ static struct connman_ippool *dhcp_ippool = NULL;
static DBusConnection *connection;
static GHashTable *pn_hash;
+static GHashTable *clients_table = NULL;
+
+struct _clients_notify {
+ int id;
+ GHashTable *remove;
+} *clients_notify;
+
struct connman_private_network {
char *owner;
char *path;
@@ -181,6 +188,18 @@ static void tethering_restart(struct connman_ippool *pool,
void *user_data)
__connman_tethering_set_enabled();
}
+static void unregister_client(gpointer key,
+ gpointer value, gpointer user_data)
+{
+ const char *addr = key;
+ __connman_tethering_client_unregister(addr);
+}
+
+static void unregister_all_clients(void)
+{
+ g_hash_table_foreach(clients_table, unregister_client, NULL);
+}
+
int __connman_tethering_set_enabled(void)
{
int index;
@@ -301,6 +320,8 @@ void __connman_tethering_set_disabled(void)
if (__sync_fetch_and_sub(&tethering_enabled, 1) != 1)
return;
+ unregister_all_clients();
+
__connman_ipv6pd_cleanup();
index = connman_inet_ifindex(BRIDGE_NAME);
@@ -327,6 +348,21 @@ void __connman_tethering_set_disabled(void)
DBG("tethering stopped");
}
+static void append_client(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ const char *addr = key;
+ DBusMessageIter *array = user_data;
+
+ dbus_message_iter_append_basic(array, DBUS_TYPE_STRING,
+ &addr);
+}
+
+void __connman_tethering_list_clients(DBusMessageIter *array)
+{
+ g_hash_table_foreach(clients_table, append_client, array);
+}
+
static void setup_tun_interface(unsigned int flags, unsigned change,
void *data)
{
@@ -440,6 +476,70 @@ static void ippool_disconnect(struct connman_ippool *pool,
void *user_data)
g_hash_table_remove(pn_hash, pn->path);
}
+static gboolean client_send_changed(gpointer data)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter, array;
+
+ DBG("");
+
+ clients_notify->id = 0;
+
+ signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE,
"TetheringClientsChanged");
+ if (!signal)
+ return FALSE;
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+
+ g_hash_table_foreach(clients_table, append_client, &array);
+
+ dbus_message_iter_close_container(&iter, &array);
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+
+ g_hash_table_foreach(clients_notify->remove, append_client, &array);
+
+ dbus_message_iter_close_container(&iter, &array);
+
+ dbus_connection_send(connection, signal, NULL);
+ dbus_message_unref(signal);
+
+ g_hash_table_remove_all(clients_notify->remove);
+
+ return FALSE;
+}
+
+static void client_schedule_changed(void)
+{
+ if (clients_notify->id != 0)
+ return;
+
+ clients_notify->id = g_timeout_add(100, client_send_changed, NULL);
+}
+
+static void client_added(const char *addr)
+{
+ DBG("client %s", addr);
+
+ g_hash_table_remove(clients_notify->remove, addr);
+
+ client_schedule_changed();
+}
+
+static void client_removed(const char *addr)
+{
+ DBG("client %s", addr);
+
+ g_hash_table_replace(clients_notify->remove, g_strdup(addr), NULL);
+
+ client_schedule_changed();
+}
+
int __connman_private_network_request(DBusMessage *msg, const char *owner)
{
struct connman_private_network *pn;
@@ -529,6 +629,18 @@ int __connman_private_network_release(const char *path)
return 0;
}
+void __connman_tethering_client_register(const char *addr)
+{
+ g_hash_table_insert(clients_table, g_strdup(addr), NULL);
+ client_added(addr);
+}
+
+void __connman_tethering_client_unregister(const char *addr)
+{
+ g_hash_table_remove(clients_table, g_strdup(addr));
+ client_removed(addr);
+}
+
int __connman_tethering_init(void)
{
DBG("");
@@ -542,6 +654,12 @@ int __connman_tethering_init(void)
pn_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
NULL, remove_private_network);
+ clients_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ clients_notify = g_new0(struct _clients_notify, 1);
+ clients_notify->remove = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
return 0;
}
@@ -562,5 +680,13 @@ void __connman_tethering_cleanup(void)
return;
g_hash_table_destroy(pn_hash);
+
+ g_hash_table_destroy(clients_notify->remove);
+ g_free(clients_notify);
+ clients_notify = NULL;
+
+ g_hash_table_destroy(clients_table);
+ clients_table = NULL;
+
dbus_connection_unref(connection);
}
--
2.19.1
------------------------------
Subject: Digest Footer
_______________________________________________
connman mailing list
[email protected]
https://lists.01.org/mailman/listinfo/connman
------------------------------
End of connman Digest, Vol 36, Issue 25
***************************************