summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-11-29 10:58:59 +0100
committerThomas Haller <thaller@redhat.com>2018-12-03 12:28:45 +0100
commit1a2e767f1fd2d8b550ab61cdfabc721280cf923e (patch)
treea74939d6597dd890f7f724316a7c84e1715cd165
parent35d9169c3c4a0361c363eca8a34ed6c575a620f1 (diff)
device/shared: set ANDROID_METERED option 43 for shared connections
The problem is that updating the metered value of a shared connection is not implemented. The user needs to fully reactivate the profile for changes to take effect. That is unfortunate, especially because reapplying the route metric works in other other cases.
-rw-r--r--src/devices/nm-device.c35
-rw-r--r--src/dnsmasq/nm-dnsmasq-manager.c14
-rw-r--r--src/dnsmasq/nm-dnsmasq-manager.h1
-rw-r--r--src/nm-manager.c8
-rw-r--r--src/nm-manager.h2
5 files changed, 57 insertions, 3 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 57021e4b7..c2223a985 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -10175,6 +10175,9 @@ start_sharing (NMDevice *self, NMIP4Config *config, GError **error)
const NMPlatformIP4Address *ip4_addr = NULL;
const char *ip_iface;
GError *local = NULL;
+ NMConnection *conn;
+ NMSettingConnection *s_con;
+ gboolean announce_android_metered;
g_return_val_if_fail (config, FALSE);
@@ -10196,7 +10199,7 @@ start_sharing (NMDevice *self, NMIP4Config *config, GError **error)
return FALSE;
req = nm_device_get_act_request (self);
- g_assert (req);
+ g_return_val_if_fail (req, FALSE);
netmask = _nm_utils_ip4_prefix_to_netmask (ip4_addr->plen);
nm_utils_inet4_ntop (netmask, str_mask);
@@ -10217,7 +10220,35 @@ start_sharing (NMDevice *self, NMIP4Config *config, GError **error)
nm_act_request_set_shared (req, TRUE);
- if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &local)) {
+ conn = nm_act_request_get_applied_connection (req);
+ s_con = nm_connection_get_setting_connection (conn);
+
+ switch (nm_setting_connection_get_metered (s_con)) {
+ case NM_METERED_YES:
+ /* honor the metered flag. Note that reapply on the device does not affect
+ * the metered setting. This is different from other profiles, where the
+ * metered flag of an activated profile can be changed (reapplied). */
+ announce_android_metered = TRUE;
+ break;
+ case NM_METERED_UNKNOWN:
+ /* we pick up the current value and announce it. But again, we cannot update
+ * the announced setting without restarting dnsmasq. That means, if the default
+ * route changes w.r.t. being metered, then the shared connection does not get
+ * updated before reactivating. */
+ announce_android_metered = NM_IN_SET (nm_manager_get_metered (nm_manager_get ()),
+ NM_METERED_YES,
+ NM_METERED_GUESS_YES);
+ break;
+ default:
+ announce_android_metered = FALSE;
+ break;
+ }
+
+
+ if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager,
+ config,
+ announce_android_metered,
+ &local)) {
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
"could not start dnsmasq due to %s", local->message);
g_error_free (local);
diff --git a/src/dnsmasq/nm-dnsmasq-manager.c b/src/dnsmasq/nm-dnsmasq-manager.c
index 42917bfdd..1afc6e0d7 100644
--- a/src/dnsmasq/nm-dnsmasq-manager.c
+++ b/src/dnsmasq/nm-dnsmasq-manager.c
@@ -104,6 +104,7 @@ static GPtrArray *
create_dm_cmd_line (const char *iface,
const NMIP4Config *ip4_config,
const char *pidfile,
+ gboolean announce_android_metered,
GError **error)
{
gs_unref_ptrarray GPtrArray *cmd = NULL;
@@ -199,6 +200,12 @@ create_dm_cmd_line (const char *iface,
nm_strv_ptrarray_take_gstring (cmd, &s);
}
+ if (announce_android_metered) {
+ /* force option 43 to announce ANDROID_METERED. Do this, even if the client
+ * did not ask for this option. See https://www.lorier.net/docs/android-metered.html */
+ nm_strv_ptrarray_add_string_dup (cmd, "--dhcp-option-force=43,ANDROID_METERED");
+ }
+
nm_strv_ptrarray_add_string_dup (cmd, "--dhcp-lease-max=50");
nm_strv_ptrarray_add_string_printf (cmd,
@@ -258,6 +265,7 @@ out:
gboolean
nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
NMIP4Config *ip4_config,
+ gboolean announce_android_metered,
GError **error)
{
NMDnsMasqManagerPrivate *priv;
@@ -272,7 +280,11 @@ nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
kill_existing_by_pidfile (priv->pidfile);
- dm_cmd = create_dm_cmd_line (priv->iface, ip4_config, priv->pidfile, error);
+ dm_cmd = create_dm_cmd_line (priv->iface,
+ ip4_config,
+ priv->pidfile,
+ announce_android_metered,
+ error);
if (!dm_cmd)
return FALSE;
diff --git a/src/dnsmasq/nm-dnsmasq-manager.h b/src/dnsmasq/nm-dnsmasq-manager.h
index a0ad295cd..dd4a9069c 100644
--- a/src/dnsmasq/nm-dnsmasq-manager.h
+++ b/src/dnsmasq/nm-dnsmasq-manager.h
@@ -48,6 +48,7 @@ NMDnsMasqManager *nm_dnsmasq_manager_new (const char *iface);
gboolean nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
NMIP4Config *ip4_config,
+ gboolean announce_android_metered,
GError **error);
void nm_dnsmasq_manager_stop (NMDnsMasqManager *manager);
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 0710483d1..7914d16d1 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1445,6 +1445,14 @@ nm_manager_update_metered (NMManager *self)
}
}
+NMMetered
+nm_manager_get_metered (NMManager *self)
+{
+ g_return_val_if_fail (NM_IS_MANAGER (self), NM_METERED_UNKNOWN);
+
+ return NM_MANAGER_GET_PRIVATE (self)->metered;
+}
+
static void
nm_manager_update_state (NMManager *self)
{
diff --git a/src/nm-manager.h b/src/nm-manager.h
index 11cba1a5c..06ca633de 100644
--- a/src/nm-manager.h
+++ b/src/nm-manager.h
@@ -174,4 +174,6 @@ void nm_manager_dbus_set_property_handle (NMDBusObject *obj,
GVariant *value,
gpointer user_data);
+NMMetered nm_manager_get_metered (NMManager *self);
+
#endif /* __NETWORKMANAGER_MANAGER_H__ */