Commit 1a2e767f authored by Thomas Haller's avatar Thomas Haller

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.
parent 35d9169c
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment