mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-27 02:20:12 +01:00
merge branch 'bg/metered-connections-bgo741725'
Expose information about whether a connection is metered and use some
heuristics to choose a reasonable default when the value is not
configured.
https://bugzilla.gnome.org/show_bug.cgi?id=741725
https://bugzilla.redhat.com/show_bug.cgi?id=1200452
(cherry picked from commit 7d09debdf0)
This commit is contained in:
commit
586bb2799f
38 changed files with 674 additions and 12 deletions
|
|
@ -521,6 +521,23 @@ nmc_device_state_to_string (NMDeviceState state)
|
|||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
nmc_device_metered_to_string (NMMetered value)
|
||||
{
|
||||
switch (value) {
|
||||
case NM_METERED_YES:
|
||||
return _("yes");
|
||||
case NM_METERED_NO:
|
||||
return _("no");
|
||||
case NM_METERED_GUESS_YES:
|
||||
return _("yes (guessed)");
|
||||
case NM_METERED_GUESS_NO:
|
||||
return _("no (guessed)");
|
||||
default:
|
||||
return _("unknown");
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
nmc_device_reason_to_string (NMDeviceStateReason reason)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ NMIPRoute *nmc_parse_and_build_route (int family, const char *first, const char
|
|||
|
||||
const char * nmc_device_state_to_string (NMDeviceState state);
|
||||
const char * nmc_device_reason_to_string (NMDeviceStateReason reason);
|
||||
const char * nmc_device_metered_to_string (NMMetered value);
|
||||
|
||||
char **
|
||||
nmc_vlan_parse_priority_maps (const char *priority_map,
|
||||
|
|
|
|||
|
|
@ -78,11 +78,12 @@ static NmcOutputField nmc_fields_dev_show_general[] = {
|
|||
{"CONNECTION", N_("CONNECTION"), 20}, /* 20 */
|
||||
{"CON-UUID", N_("CON-UUID"), 38}, /* 21 */
|
||||
{"CON-PATH", N_("CON-PATH"), 51}, /* 22 */
|
||||
{"METERED", N_("METERED"), 10}, /* 23 */
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
#define NMC_FIELDS_DEV_SHOW_GENERAL_ALL "NAME,DEVICE,TYPE,NM-TYPE,VENDOR,PRODUCT,DRIVER,DRIVER-VERSION,FIRMWARE-VERSION,HWADDR,MTU,"\
|
||||
"STATE,REASON,UDI,IP-IFACE,IS-SOFTWARE,NM-MANAGED,AUTOCONNECT,FIRMWARE-MISSING,PHYS-PORT-ID,"\
|
||||
"CONNECTION,CON-UUID,CON-PATH"
|
||||
"CONNECTION,CON-UUID,CON-PATH,METERED"
|
||||
#define NMC_FIELDS_DEV_SHOW_GENERAL_COMMON "NAME,DEVICE,TYPE,VENDOR,PRODUCT,DRIVER,HWADDR,STATE"
|
||||
|
||||
/* Available fields for 'device show' - CONNECTIONS part */
|
||||
|
|
@ -858,6 +859,8 @@ show_device_info (NMDevice *device, NmCli *nmc)
|
|||
set_val_strc (arr, 20, get_active_connection_id (device));
|
||||
set_val_strc (arr, 21, acon ? nm_active_connection_get_uuid (acon) : NULL);
|
||||
set_val_strc (arr, 22, acon ? nm_object_get_path (NM_OBJECT (acon)) : NULL);
|
||||
set_val_strc (arr, 23, nmc_device_metered_to_string (nm_device_get_metered (device)));
|
||||
|
||||
g_ptr_array_add (nmc->output_data, arr);
|
||||
|
||||
print_data (nmc); /* Print all data */
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ NmcOutputField nmc_fields_setting_connection[] = {
|
|||
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, 13), /* 13 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES, 40), /* 14 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, 30), /* 15 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_METERED, 10), /* 16 */
|
||||
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
|
||||
};
|
||||
#define NMC_FIELDS_SETTING_CONNECTION_ALL "name"","\
|
||||
|
|
@ -77,7 +78,8 @@ NmcOutputField nmc_fields_setting_connection[] = {
|
|||
NM_SETTING_CONNECTION_SLAVE_TYPE","\
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES","\
|
||||
NM_SETTING_CONNECTION_SECONDARIES","\
|
||||
NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT
|
||||
NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT","\
|
||||
NM_SETTING_CONNECTION_METERED
|
||||
#define NMC_FIELDS_SETTING_CONNECTION_COMMON NMC_FIELDS_SETTING_CONNECTION_ALL
|
||||
|
||||
/* Available fields for NM_SETTING_WIRED_SETTING_NAME */
|
||||
|
|
@ -2744,6 +2746,51 @@ nmc_property_connection_describe_secondaries (NMSetting *setting, const char *pr
|
|||
"Example: private-openvpn, fe6ba5d8-c2fc-4aae-b2e3-97efddd8d9a7\n");
|
||||
}
|
||||
|
||||
/* 'metered' */
|
||||
static char *
|
||||
nmc_property_connection_get_metered (NMSetting *setting, NmcPropertyGetType get_type)
|
||||
{
|
||||
NMSettingConnection *s_conn = NM_SETTING_CONNECTION (setting);
|
||||
|
||||
switch (nm_setting_connection_get_metered (s_conn)) {
|
||||
case NM_METERED_YES:
|
||||
return g_strdup (_("yes"));
|
||||
case NM_METERED_NO:
|
||||
return g_strdup (_("no"));
|
||||
case NM_METERED_UNKNOWN:
|
||||
default:
|
||||
return g_strdup (_("unknown"));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nmc_property_connection_set_metered (NMSetting *setting, const char *prop,
|
||||
const char *val, GError **error)
|
||||
{
|
||||
NMMetered metered;
|
||||
NMCTriStateValue ts_val;
|
||||
|
||||
if (!nmc_string_to_tristate (val, &ts_val, error))
|
||||
return FALSE;
|
||||
|
||||
switch (ts_val) {
|
||||
case NMC_TRI_STATE_YES:
|
||||
metered = NM_METERED_YES;
|
||||
break;
|
||||
case NMC_TRI_STATE_NO:
|
||||
metered = NM_METERED_NO;
|
||||
break;
|
||||
case NMC_TRI_STATE_UNKNOWN:
|
||||
metered = NM_METERED_UNKNOWN;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
g_object_set (setting, prop, metered, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* --- NM_SETTING_802_1X_SETTING_NAME property setter functions --- */
|
||||
#define DEFINE_SETTER_STR_LIST(def_func, set_func) \
|
||||
static gboolean \
|
||||
|
|
@ -5324,6 +5371,13 @@ nmc_properties_init (void)
|
|||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nmc_add_prop_funcs (GLUE (CONNECTION, METERED),
|
||||
nmc_property_connection_get_metered,
|
||||
nmc_property_connection_set_metered,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Add editable properties for NM_SETTING_DCB_SETTING_NAME */
|
||||
nmc_add_prop_funcs (GLUE (DCB, APP_FCOE_FLAGS),
|
||||
|
|
@ -6684,6 +6738,7 @@ setting_connection_details (NMSetting *setting, NmCli *nmc, const char *one_pro
|
|||
set_val_str (arr, 13, nmc_property_connection_get_autoconnect_slaves (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 14, nmc_property_connection_get_secondaries (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 15, nmc_property_connection_get_gateway_ping_timeout (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 16, nmc_property_connection_get_metered (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
g_ptr_array_add (nmc->output_data, arr);
|
||||
|
||||
print_data (nmc); /* Print all data */
|
||||
|
|
|
|||
|
|
@ -407,7 +407,10 @@ nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error)
|
|||
|
||||
if (g_strcmp0 (str, "o") == 0) {
|
||||
g_set_error (error, 1, 0,
|
||||
_("'%s' is ambiguous (on x off)"), str);
|
||||
/* Translators: the first %s is the partial value entered by
|
||||
* the user, the second %s a list of compatible values.
|
||||
*/
|
||||
_("'%s' is ambiguous (%s)"), str, "on x off");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -424,6 +427,39 @@ nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error)
|
||||
{
|
||||
const char *s_true[] = { "true", "yes", "on", NULL };
|
||||
const char *s_false[] = { "false", "no", "off", NULL };
|
||||
const char *s_unknown[] = { "unknown", NULL };
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
if (g_strcmp0 (str, "o") == 0) {
|
||||
g_set_error (error, 1, 0,
|
||||
/* Translators: the first %s is the partial value entered by
|
||||
* the user, the second %s a list of compatible values.
|
||||
*/
|
||||
_("'%s' is ambiguous (%s)"), str, "on x off");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nmc_string_is_valid (str, s_true, NULL))
|
||||
*val = NMC_TRI_STATE_YES;
|
||||
else if (nmc_string_is_valid (str, s_false, NULL))
|
||||
*val = NMC_TRI_STATE_NO;
|
||||
else if (nmc_string_is_valid (str, s_unknown, NULL))
|
||||
*val = NMC_TRI_STATE_UNKNOWN;
|
||||
else {
|
||||
g_set_error (error, 1, 0,
|
||||
_("'%s' is not valid; use [%s], [%s] or [%s]"),
|
||||
str, "true, yes, on", "false, no, off", "unknown");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ask user for input and return the string.
|
||||
* The caller is responsible for freeing the returned string.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ typedef struct {
|
|||
gboolean found;
|
||||
} nmc_arg_t;
|
||||
|
||||
typedef enum {
|
||||
NMC_TRI_STATE_NO,
|
||||
NMC_TRI_STATE_YES,
|
||||
NMC_TRI_STATE_UNKNOWN,
|
||||
} NMCTriStateValue;
|
||||
|
||||
/* === Functions === */
|
||||
int matches (const char *cmd, const char *pattern);
|
||||
int next_arg (int *argc, char ***argv);
|
||||
|
|
@ -62,6 +68,7 @@ gboolean nmc_string_to_uint (const char *str,
|
|||
unsigned long int max,
|
||||
unsigned long int *value);
|
||||
gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error);
|
||||
gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error);
|
||||
char *nmc_ip4_address_as_string (guint32 ip, GError **error);
|
||||
char *nmc_ip6_address_as_string (const struct in6_addr *ip, GError **error);
|
||||
void nmc_terminal_erase_line (void);
|
||||
|
|
|
|||
|
|
@ -139,6 +139,12 @@
|
|||
The device MTU (maximum transmission unit).
|
||||
</tp:docstring>
|
||||
</property>
|
||||
<property name="Metered" type="u" access="read" tp:type="NM_METERED">
|
||||
<tp:docstring>
|
||||
Whether the amount of traffic flowing through the device is
|
||||
subject to limitations, for example set by service providers.
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<method name="Disconnect">
|
||||
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_device_disconnect"/>
|
||||
|
|
@ -654,6 +660,34 @@
|
|||
</tp:enumvalue>
|
||||
</tp:enum>
|
||||
|
||||
<tp:enum name="NM_METERED" type="u">
|
||||
<tp:enumvalue suffix="UNKNOWN" value="0">
|
||||
<tp:docstring>
|
||||
The device metered status is unknown.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="YES" value="1">
|
||||
<tp:docstring>
|
||||
The device is metered and the value was statically set.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="NO" value="2">
|
||||
<tp:docstring>
|
||||
The device is not metered and the value was statically set.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="GUESS_YES" value="3">
|
||||
<tp:docstring>
|
||||
The device is metered and the value was guessed.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="GUESS_NO" value="4">
|
||||
<tp:docstring>
|
||||
The device is not metered and the value was guessed.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
</tp:enum>
|
||||
|
||||
<tp:struct name="NM_DEVICE_STATE_REASON_STRUCT">
|
||||
<tp:member type="u" name="state" tp:type="NM_DEVICE_STATE">
|
||||
<tp:docstring>
|
||||
|
|
|
|||
|
|
@ -335,6 +335,14 @@
|
|||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="Metered" type="u" access="read" tp:type="NM_METERED">
|
||||
<tp:docstring>
|
||||
Wheter the connectivity is metered. This is equivalent to the
|
||||
metered property of the device associated with the primary
|
||||
connection.
|
||||
</tp:docstring>
|
||||
</property>
|
||||
|
||||
<property name="ActivatingConnection" type="o" access="read">
|
||||
<tp:docstring>
|
||||
The object path of an active connection that is currently
|
||||
|
|
|
|||
|
|
@ -403,7 +403,6 @@ typedef enum {
|
|||
NM_DEVICE_STATE_FAILED = 120
|
||||
} NMDeviceState;
|
||||
|
||||
|
||||
/**
|
||||
* NMDeviceStateReason:
|
||||
* @NM_DEVICE_STATE_REASON_NONE: No reason given
|
||||
|
|
@ -540,6 +539,26 @@ typedef enum {
|
|||
NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED = 62,
|
||||
} NMDeviceStateReason;
|
||||
|
||||
/**
|
||||
* NMMetered:
|
||||
* @NM_METERED_UNKNOWN: The metered status is unknown
|
||||
* @NM_METERED_YES: Metered, the value was statically set
|
||||
* @NM_METERED_NO: Not metered, the value was statically set
|
||||
* @NM_METERED_GUESS_YES: Metered, the value was guessed
|
||||
* @NM_METERED_GUESS_NO: Not metered, the value was guessed
|
||||
*
|
||||
* (Corresponds to the NM_METERED type in nm-device.xml.)
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
NM_AVAILABLE_IN_1_0_6
|
||||
typedef enum {
|
||||
NM_METERED_UNKNOWN = 0,
|
||||
NM_METERED_YES = 1,
|
||||
NM_METERED_NO = 2,
|
||||
NM_METERED_GUESS_YES = 3,
|
||||
NM_METERED_GUESS_NO = 4,
|
||||
} NMMetered;
|
||||
|
||||
/**
|
||||
* NMActiveConnectionState:
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ typedef struct {
|
|||
char *zone;
|
||||
GSList *secondaries; /* secondary connections to activate with the base connection */
|
||||
guint gateway_ping_timeout;
|
||||
NMMetered metered;
|
||||
} NMSettingConnectionPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -95,6 +96,7 @@ enum {
|
|||
PROP_AUTOCONNECT_SLAVES,
|
||||
PROP_SECONDARIES,
|
||||
PROP_GATEWAY_PING_TIMEOUT,
|
||||
PROP_METERED,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -760,6 +762,23 @@ nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting)
|
|||
return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->gateway_ping_timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_connection_get_metered:
|
||||
* @setting: the #NMSettingConnection
|
||||
*
|
||||
* Returns: the #NMSettingConnection:metered property of the setting.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
NMMetered
|
||||
nm_setting_connection_get_metered (NMSettingConnection *setting)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting),
|
||||
NM_METERED_UNKNOWN);
|
||||
|
||||
return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->metered;
|
||||
}
|
||||
|
||||
static void
|
||||
_set_error_missing_base_setting (GError **error, const char *type)
|
||||
{
|
||||
|
|
@ -921,6 +940,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
}
|
||||
}
|
||||
|
||||
if (priv->metered != NM_METERED_UNKNOWN &&
|
||||
priv->metered != NM_METERED_YES &&
|
||||
priv->metered != NM_METERED_NO) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("metered value %d is not valid"), priv->metered);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME,
|
||||
NM_SETTING_CONNECTION_METERED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */
|
||||
|
||||
if (!priv->uuid) {
|
||||
|
|
@ -1154,6 +1185,9 @@ set_property (GObject *object, guint prop_id,
|
|||
case PROP_GATEWAY_PING_TIMEOUT:
|
||||
priv->gateway_ping_timeout = g_value_get_uint (value);
|
||||
break;
|
||||
case PROP_METERED:
|
||||
priv->metered = g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -1227,6 +1261,9 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_GATEWAY_PING_TIMEOUT:
|
||||
g_value_set_uint (value, priv->gateway_ping_timeout);
|
||||
break;
|
||||
case PROP_METERED:
|
||||
g_value_set_enum (value, priv->metered);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -1626,4 +1663,27 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
|
|||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMSettingConnection:metered:
|
||||
*
|
||||
* Whether the connection is metered.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
/* ---ifcfg-rh---
|
||||
* property: metered
|
||||
* variable: CONNECTION_METERED
|
||||
* values: yes,no,unknown
|
||||
* description: Whether the device is metered
|
||||
* example: CONNECTION_METERED=yes
|
||||
* ---end---
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_METERED,
|
||||
g_param_spec_enum (NM_SETTING_CONNECTION_METERED, "", "",
|
||||
NM_TYPE_METERED,
|
||||
NM_METERED_UNKNOWN,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ G_BEGIN_DECLS
|
|||
#define NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES "autoconnect-slaves"
|
||||
#define NM_SETTING_CONNECTION_SECONDARIES "secondaries"
|
||||
#define NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT "gateway-ping-timeout"
|
||||
#define NM_SETTING_CONNECTION_METERED "metered"
|
||||
|
||||
/* Types for property values */
|
||||
/**
|
||||
|
|
@ -142,6 +143,8 @@ void nm_setting_connection_remove_secondary (NMSettingConnection *set
|
|||
gboolean nm_setting_connection_remove_secondary_by_value (NMSettingConnection *setting, const char *sec_uuid);
|
||||
|
||||
guint32 nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting);
|
||||
NM_AVAILABLE_IN_1_0_6
|
||||
NMMetered nm_setting_connection_get_metered (NMSettingConnection *setting);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -1969,6 +1969,7 @@ test_connection_diff_a_only (void)
|
|||
{ NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_SECONDARIES, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_METERED, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
|
||||
} },
|
||||
{ NM_SETTING_WIRED_SETTING_NAME, {
|
||||
|
|
|
|||
|
|
@ -851,3 +851,10 @@ global:
|
|||
nm_setting_connection_get_autoconnect_slaves;
|
||||
} libnm_1_0_0;
|
||||
|
||||
libnm_1_0_6 {
|
||||
global:
|
||||
nm_device_get_metered;
|
||||
nm_metered_get_type;
|
||||
nm_setting_connection_get_metered;
|
||||
} libnm_1_0_4;
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ enum {
|
|||
PROP_CONNECTIONS,
|
||||
PROP_HOSTNAME,
|
||||
PROP_CAN_MODIFY,
|
||||
PROP_METERED,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -1871,6 +1872,7 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_PRIMARY_CONNECTION:
|
||||
case PROP_ACTIVATING_CONNECTION:
|
||||
case PROP_DEVICES:
|
||||
case PROP_METERED:
|
||||
g_object_get_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->manager),
|
||||
pspec->name, value);
|
||||
break;
|
||||
|
|
@ -2143,6 +2145,20 @@ nm_client_class_init (NMClientClass *client_class)
|
|||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMClient:metered:
|
||||
*
|
||||
* Whether the connectivity is metered.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_METERED,
|
||||
g_param_spec_uint (NM_CLIENT_METERED, "", "",
|
||||
0, G_MAXUINT32, NM_METERED_UNKNOWN,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* signals */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ G_BEGIN_DECLS
|
|||
#define NM_CLIENT_CONNECTIONS "connections"
|
||||
#define NM_CLIENT_HOSTNAME "hostname"
|
||||
#define NM_CLIENT_CAN_MODIFY "can-modify"
|
||||
#define NM_CLIENT_METERED "metered"
|
||||
|
||||
#define NM_CLIENT_DEVICE_ADDED "device-added"
|
||||
#define NM_CLIENT_DEVICE_REMOVED "device-removed"
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ typedef struct {
|
|||
char *driver_version;
|
||||
char *firmware_version;
|
||||
char *type_description;
|
||||
NMMetered metered;
|
||||
NMDeviceCapabilities capabilities;
|
||||
gboolean managed;
|
||||
gboolean firmware_missing;
|
||||
|
|
@ -130,6 +131,7 @@ enum {
|
|||
PROP_AVAILABLE_CONNECTIONS,
|
||||
PROP_PHYSICAL_PORT_ID,
|
||||
PROP_MTU,
|
||||
PROP_METERED,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -193,6 +195,7 @@ init_dbus (NMObject *object)
|
|||
{ NM_DEVICE_AVAILABLE_CONNECTIONS, &priv->available_connections, NULL, NM_TYPE_REMOTE_CONNECTION },
|
||||
{ NM_DEVICE_PHYSICAL_PORT_ID, &priv->physical_port_id },
|
||||
{ NM_DEVICE_MTU, &priv->mtu },
|
||||
{ NM_DEVICE_METERED, &priv->metered },
|
||||
|
||||
/* Properties that exist in D-Bus but that we don't track */
|
||||
{ "ip4-address", NULL },
|
||||
|
|
@ -449,6 +452,9 @@ get_property (GObject *object,
|
|||
case PROP_MTU:
|
||||
g_value_set_uint (value, nm_device_get_mtu (device));
|
||||
break;
|
||||
case PROP_METERED:
|
||||
g_value_set_uint (value, nm_device_get_metered (device));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -793,6 +799,20 @@ nm_device_class_init (NMDeviceClass *device_class)
|
|||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMDevice:metered:
|
||||
*
|
||||
* Whether the device is metered.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_METERED,
|
||||
g_param_spec_uint (NM_DEVICE_METERED, "", "",
|
||||
0, G_MAXUINT32, NM_METERED_UNKNOWN,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* signals */
|
||||
|
||||
/**
|
||||
|
|
@ -1883,6 +1903,24 @@ nm_device_get_mtu (NMDevice *device)
|
|||
return NM_DEVICE_GET_PRIVATE (device)->mtu;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_get_metered:
|
||||
* @device: a #NMDevice
|
||||
*
|
||||
* Gets the metered setting of a #NMDevice.
|
||||
*
|
||||
* Returns: the metered setting.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
NMMetered
|
||||
nm_device_get_metered (NMDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_DEVICE (device), NM_METERED_UNKNOWN);
|
||||
|
||||
return NM_DEVICE_GET_PRIVATE (device)->metered;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_is_software:
|
||||
* @device: a #NMDevice
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ G_BEGIN_DECLS
|
|||
#define NM_DEVICE_PRODUCT "product"
|
||||
#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id"
|
||||
#define NM_DEVICE_MTU "mtu"
|
||||
#define NM_DEVICE_METERED "metered"
|
||||
|
||||
struct _NMDevice {
|
||||
NMObject parent;
|
||||
|
|
@ -119,6 +120,8 @@ gboolean nm_device_is_software (NMDevice *device);
|
|||
const char * nm_device_get_product (NMDevice *device);
|
||||
const char * nm_device_get_vendor (NMDevice *device);
|
||||
const char * nm_device_get_description (NMDevice *device);
|
||||
NM_AVAILABLE_IN_1_0_6
|
||||
NMMetered nm_device_get_metered (NMDevice *device);
|
||||
char ** nm_device_disambiguate_names (NMDevice **devices,
|
||||
int num_devices);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ typedef struct {
|
|||
NMConnectivityState connectivity;
|
||||
NMActiveConnection *primary_connection;
|
||||
NMActiveConnection *activating_connection;
|
||||
NMMetered metered;
|
||||
|
||||
GCancellable *perm_call_cancellable;
|
||||
GHashTable *permissions;
|
||||
|
|
@ -102,6 +103,7 @@ enum {
|
|||
PROP_PRIMARY_CONNECTION,
|
||||
PROP_ACTIVATING_CONNECTION,
|
||||
PROP_DEVICES,
|
||||
PROP_METERED,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -179,6 +181,7 @@ init_dbus (NMObject *object)
|
|||
{ NM_MANAGER_PRIMARY_CONNECTION, &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
|
||||
{ NM_MANAGER_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
|
||||
{ NM_MANAGER_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE, "device" },
|
||||
{ NM_MANAGER_METERED, &priv->metered },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
@ -1537,6 +1540,9 @@ get_property (GObject *object,
|
|||
case PROP_DEVICES:
|
||||
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_devices (self)));
|
||||
break;
|
||||
case PROP_METERED:
|
||||
g_value_set_uint (value, priv->metered);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -1669,6 +1675,19 @@ nm_manager_class_init (NMManagerClass *manager_class)
|
|||
G_TYPE_PTR_ARRAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* NMManager:metered:
|
||||
*
|
||||
* Whether the connectivity is metered.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_METERED,
|
||||
g_param_spec_uint (NM_MANAGER_METERED, "", "",
|
||||
0, G_MAXUINT32, NM_METERED_UNKNOWN,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* signals */
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ G_BEGIN_DECLS
|
|||
#define NM_MANAGER_PRIMARY_CONNECTION "primary-connection"
|
||||
#define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection"
|
||||
#define NM_MANAGER_DEVICES "devices"
|
||||
#define NM_MANAGER_METERED "metered"
|
||||
|
||||
typedef struct {
|
||||
NMObject parent;
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ _LOG_DECLARE_SELF (NMDevice);
|
|||
static void impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context);
|
||||
static void impl_device_delete (NMDevice *self, DBusGMethodInvocation *context);
|
||||
static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data);
|
||||
static void nm_device_update_metered (NMDevice *self);
|
||||
|
||||
#include "nm-device-glue.h"
|
||||
|
||||
|
|
@ -128,6 +129,7 @@ enum {
|
|||
PROP_MASTER,
|
||||
PROP_HW_ADDRESS,
|
||||
PROP_HAS_PENDING_ACTION,
|
||||
PROP_METERED,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
|
|
@ -338,6 +340,8 @@ typedef struct {
|
|||
gboolean is_master;
|
||||
GSList * slaves; /* list of SlaveInfo */
|
||||
|
||||
NMMetered metered;
|
||||
|
||||
NMConnectionProvider *con_provider;
|
||||
} NMDevicePrivate;
|
||||
|
||||
|
|
@ -687,6 +691,21 @@ nm_device_get_device_type (NMDevice *self)
|
|||
return NM_DEVICE_GET_PRIVATE (self)->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_get_metered:
|
||||
* @setting: the #NMDevice
|
||||
*
|
||||
* Returns: the #NMDevice:metered property of the device.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
NMMetered
|
||||
nm_device_get_metered (NMDevice *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), NM_METERED_UNKNOWN);
|
||||
|
||||
return NM_DEVICE_GET_PRIVATE (self)->metered;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_get_priority():
|
||||
|
|
@ -3450,8 +3469,10 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||
|
||||
if (priv->ip4_state == IP_CONF)
|
||||
nm_device_activate_schedule_ip4_config_result (self, ip4_config);
|
||||
else if (priv->ip4_state == IP_DONE)
|
||||
else if (priv->ip4_state == IP_DONE) {
|
||||
dhcp4_lease_change (self, ip4_config);
|
||||
nm_device_update_metered (self);
|
||||
}
|
||||
break;
|
||||
case NM_DHCP_STATE_TIMEOUT:
|
||||
dhcp4_fail (self, TRUE);
|
||||
|
|
@ -7497,6 +7518,59 @@ nm_device_set_dhcp_anycast_address (NMDevice *self, const char *addr)
|
|||
priv->dhcp_anycast_address = g_strdup (addr);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_device_update_metered (NMDevice *self)
|
||||
{
|
||||
#define NM_METERED_INVALID ((NMMetered) -1)
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMSettingConnection *setting;
|
||||
NMMetered conn_value, value = NM_METERED_INVALID;
|
||||
NMConnection *connection = NULL;
|
||||
NMDeviceState state;
|
||||
|
||||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
state = nm_device_get_state (self);
|
||||
if ( state <= NM_DEVICE_STATE_DISCONNECTED
|
||||
|| state > NM_DEVICE_STATE_ACTIVATED)
|
||||
value = NM_METERED_UNKNOWN;
|
||||
|
||||
if (value == NM_METERED_INVALID) {
|
||||
connection = nm_device_get_connection (self);
|
||||
if (connection) {
|
||||
setting = nm_connection_get_setting_connection (connection);
|
||||
if (setting) {
|
||||
conn_value = nm_setting_connection_get_metered (setting);
|
||||
if (conn_value != NM_METERED_UNKNOWN)
|
||||
value = conn_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to guess a value using the metered flag in IP configuration */
|
||||
if (value == NM_METERED_INVALID) {
|
||||
if ( priv->ip4_config
|
||||
&& priv->ip4_state == IP_DONE
|
||||
&& nm_ip4_config_get_metered (priv->ip4_config))
|
||||
value = NM_METERED_GUESS_YES;
|
||||
}
|
||||
|
||||
/* Otherwise look at connection type */
|
||||
if (value == NM_METERED_INVALID) {
|
||||
if ( nm_connection_is_type (connection, NM_SETTING_GSM_SETTING_NAME)
|
||||
|| nm_connection_is_type (connection, NM_SETTING_CDMA_SETTING_NAME))
|
||||
value = NM_METERED_GUESS_YES;
|
||||
else
|
||||
value = NM_METERED_GUESS_NO;
|
||||
}
|
||||
|
||||
if (value != priv->metered) {
|
||||
_LOGD (LOGD_DEVICE, "set metered value %d", value);
|
||||
priv->metered = value;
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_METERED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_check_connection_available():
|
||||
* @self: the #NMDevice
|
||||
|
|
@ -7954,6 +8028,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
|
|||
nm_platform_address_flush (NM_PLATFORM_GET, ifindex);
|
||||
}
|
||||
|
||||
nm_device_update_metered (self);
|
||||
_cleanup_generic_post (self, cleanup_type);
|
||||
}
|
||||
|
||||
|
|
@ -8426,6 +8501,7 @@ _set_state_full (NMDevice *self,
|
|||
break;
|
||||
case NM_DEVICE_STATE_ACTIVATED:
|
||||
_LOGI (LOGD_DEVICE, "Activation: successful, device activated.");
|
||||
nm_device_update_metered (self);
|
||||
nm_dispatcher_call (DISPATCHER_ACTION_UP, nm_act_request_get_connection (req), self, NULL, NULL, NULL);
|
||||
break;
|
||||
case NM_DEVICE_STATE_FAILED:
|
||||
|
|
@ -9298,6 +9374,9 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_HAS_PENDING_ACTION:
|
||||
g_value_set_boolean (value, nm_device_has_pending_action (self));
|
||||
break;
|
||||
case PROP_METERED:
|
||||
g_value_set_uint (value, priv->metered);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -9561,6 +9640,20 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMDevice:metered:
|
||||
*
|
||||
* Whether the connection is metered.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_METERED,
|
||||
g_param_spec_uint (NM_DEVICE_METERED, "", "",
|
||||
0, G_MAXUINT32, NM_METERED_UNKNOWN,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* Signals */
|
||||
signals[STATE_CHANGED] =
|
||||
g_signal_new ("state-changed",
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id"
|
||||
#define NM_DEVICE_MTU "mtu"
|
||||
#define NM_DEVICE_HW_ADDRESS "hw-address"
|
||||
#define NM_DEVICE_METERED "metered"
|
||||
|
||||
#define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */
|
||||
#define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */
|
||||
|
|
@ -74,7 +75,6 @@
|
|||
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
||||
#define NM_DEVICE_RECHECK_ASSUME "recheck-assume"
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define NM_TYPE_DEVICE (nm_device_get_type ())
|
||||
|
|
@ -281,6 +281,7 @@ const char * nm_device_get_driver_version (NMDevice *dev);
|
|||
const char * nm_device_get_type_desc (NMDevice *dev);
|
||||
const char * nm_device_get_type_description (NMDevice *dev);
|
||||
NMDeviceType nm_device_get_device_type (NMDevice *dev);
|
||||
NMMetered nm_device_get_metered (NMDevice *dev);
|
||||
|
||||
int nm_device_get_priority (NMDevice *dev);
|
||||
guint32 nm_device_get_ip4_route_metric (NMDevice *dev);
|
||||
|
|
|
|||
|
|
@ -224,6 +224,8 @@ lease_to_ip4_config (sd_dhcp_lease *lease,
|
|||
guint16 mtu;
|
||||
int r, num;
|
||||
guint64 end_time;
|
||||
uint8_t *data;
|
||||
gboolean metered = FALSE;
|
||||
|
||||
g_return_val_if_fail (lease != NULL, NULL);
|
||||
|
||||
|
|
@ -355,6 +357,11 @@ lease_to_ip4_config (sd_dhcp_lease *lease,
|
|||
g_string_free (l, TRUE);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_vendor_specific (lease, &data);
|
||||
if (num > 0)
|
||||
metered = !!memmem (data, num, "ANDROID_METERED", STRLEN ("ANDROID_METERED"));
|
||||
nm_ip4_config_set_metered (ip4_config, metered);
|
||||
|
||||
return ip4_config;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -575,6 +575,9 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
|
|||
g_strfreev (nis);
|
||||
}
|
||||
|
||||
str = g_hash_table_lookup (options, "vendor_encapsulated_options");
|
||||
nm_ip4_config_set_metered (ip4_config, str && strstr (str, "ANDROID_METERED"));
|
||||
|
||||
return ip4_config;
|
||||
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ struct sd_dhcp_lease {
|
|||
char *root_path;
|
||||
uint8_t *client_id;
|
||||
size_t client_id_len;
|
||||
uint8_t *vendor_specific;
|
||||
size_t vendor_specific_size;
|
||||
};
|
||||
|
||||
int dhcp_lease_new(sd_dhcp_lease **ret);
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ enum {
|
|||
DHCP_OPTION_BROADCAST = 28,
|
||||
DHCP_OPTION_STATIC_ROUTE = 33,
|
||||
DHCP_OPTION_NTP_SERVER = 42,
|
||||
DHCP_OPTION_VENDOR_SPECIFIC = 43,
|
||||
DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
|
||||
DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
|
||||
DHCP_OPTION_OVERLOAD = 52,
|
||||
|
|
|
|||
|
|
@ -191,6 +191,19 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, uint8_t **data) {
|
||||
assert_return(lease, -EINVAL);
|
||||
assert_return(data, -EINVAL);
|
||||
|
||||
if (lease->vendor_specific) {
|
||||
*data = lease->vendor_specific;
|
||||
return lease->vendor_specific_size;
|
||||
} else
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
|
||||
if (lease)
|
||||
assert_se(REFCNT_INC(lease->n_ref) >= 2);
|
||||
|
|
@ -286,6 +299,24 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lease_parse_binary(const uint8_t *option, size_t len, uint8_t **ret) {
|
||||
assert (option);
|
||||
assert (ret);
|
||||
|
||||
if (len >= 1) {
|
||||
uint8_t *data;
|
||||
|
||||
data = memdup(option, len);
|
||||
if (!data)
|
||||
return -errno;
|
||||
|
||||
free(*ret);
|
||||
*ret = data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) {
|
||||
assert(option);
|
||||
assert(ret);
|
||||
|
|
@ -568,6 +599,14 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
|
|||
return r;
|
||||
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_VENDOR_SPECIFIC:
|
||||
r = lease_parse_binary(option, len, &lease->vendor_specific);
|
||||
if (r < 0)
|
||||
return r;
|
||||
lease->vendor_specific_size = len;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -595,6 +634,7 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
|||
const uint8_t *client_id;
|
||||
size_t client_id_len;
|
||||
const char *string;
|
||||
uint8_t *data;
|
||||
uint16_t mtu;
|
||||
struct sd_dhcp_route *routes;
|
||||
int r;
|
||||
|
|
@ -667,6 +707,18 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
|
|||
if (r >= 0)
|
||||
serialize_dhcp_routes(f, "ROUTES", routes, r);
|
||||
|
||||
r = sd_dhcp_lease_get_vendor_specific(lease, &data);
|
||||
if (r >= 0) {
|
||||
_cleanup_free_ char *option_hex = NULL;
|
||||
|
||||
option_hex = hexmem(data, r);
|
||||
if (!option_hex) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
fprintf(f, "VENDOR_SPECIFIC=%s\n", option_hex);
|
||||
}
|
||||
|
||||
r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
|
||||
if (r >= 0) {
|
||||
_cleanup_free_ char *client_id_hex = NULL;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
|
|||
int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname);
|
||||
int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
|
||||
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routesgn);
|
||||
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, uint8_t **data);
|
||||
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
|
||||
size_t *client_id_len);
|
||||
|
||||
|
|
|
|||
|
|
@ -175,6 +175,30 @@ test_wins_options (void)
|
|||
g_hash_table_destroy (options);
|
||||
}
|
||||
|
||||
static void
|
||||
test_vendor_option_metered (void)
|
||||
{
|
||||
GHashTable *options;
|
||||
NMIP4Config *ip4_config;
|
||||
static const Option data[] = {
|
||||
{ "vendor_encapsulated_options", "ANDROID_METERED" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
options = fill_table (generic_options, NULL);
|
||||
ip4_config = nm_dhcp_utils_ip4_config_from_options ("eth0", options, 0);
|
||||
g_assert (ip4_config);
|
||||
g_assert (nm_ip4_config_get_metered (ip4_config) == FALSE);
|
||||
g_hash_table_destroy (options);
|
||||
|
||||
options = fill_table (generic_options, NULL);
|
||||
options = fill_table (data, options);
|
||||
ip4_config = nm_dhcp_utils_ip4_config_from_options ("eth0", options, 0);
|
||||
g_assert (ip4_config);
|
||||
g_assert (nm_ip4_config_get_metered (ip4_config) == TRUE);
|
||||
g_hash_table_destroy (options);
|
||||
}
|
||||
|
||||
static void
|
||||
ip4_test_route (NMIP4Config *ip4_config,
|
||||
guint route_num,
|
||||
|
|
@ -716,6 +740,7 @@ int main (int argc, char **argv)
|
|||
g_test_add_func ("/dhcp/ip4-missing-prefix-8", test_ip4_missing_prefix_8);
|
||||
g_test_add_func ("/dhcp/ip4-prefix-classless", test_ip4_prefix_classless);
|
||||
g_test_add_func ("/dhcp/client-id-from-string", test_client_id_from_string);
|
||||
g_test_add_func ("/dhcp/vendor-option-metered", test_vendor_option_metered);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ enum {
|
|||
|
||||
enum {
|
||||
DEVICE_CHANGED,
|
||||
DEVICE_METERED_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
|
@ -401,6 +402,18 @@ device_master_changed (GObject *object,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_metered_changed (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMActiveConnection *self = (NMActiveConnection *) user_data;
|
||||
NMDevice *device = NM_DEVICE (object);
|
||||
|
||||
g_return_if_fail (NM_IS_ACTIVE_CONNECTION (self));
|
||||
g_signal_emit (self, signals[DEVICE_METERED_CHANGED], 0, nm_device_get_metered (device));
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device)
|
||||
{
|
||||
|
|
@ -427,6 +440,8 @@ nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device)
|
|||
G_CALLBACK (device_state_changed), self);
|
||||
g_signal_connect (device, "notify::master",
|
||||
G_CALLBACK (device_master_changed), self);
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_METERED,
|
||||
G_CALLBACK (device_metered_changed), self);
|
||||
|
||||
if (!priv->assumed) {
|
||||
priv->pending_activation_id = g_strdup_printf ("activation::%p", (void *)self);
|
||||
|
|
@ -838,6 +853,7 @@ _device_cleanup (NMActiveConnection *self)
|
|||
if (priv->device) {
|
||||
g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_state_changed), self);
|
||||
g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_master_changed), self);
|
||||
g_signal_handlers_disconnect_by_func (priv->device, G_CALLBACK (device_metered_changed), self);
|
||||
}
|
||||
|
||||
if (priv->pending_activation_id) {
|
||||
|
|
@ -1043,6 +1059,14 @@ nm_active_connection_class_init (NMActiveConnectionClass *ac_class)
|
|||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2, NM_TYPE_DEVICE, NM_TYPE_DEVICE);
|
||||
|
||||
signals[DEVICE_METERED_CHANGED] =
|
||||
g_signal_new (NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMActiveConnectionClass, device_metered_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_UINT);
|
||||
|
||||
nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
|
||||
G_TYPE_FROM_CLASS (ac_class),
|
||||
&dbus_glib_nm_active_connection_object_info);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@
|
|||
#define NM_ACTIVE_CONNECTION_INT_MASTER_READY "int-master-ready"
|
||||
|
||||
/* Internal signals*/
|
||||
#define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed"
|
||||
#define NM_ACTIVE_CONNECTION_DEVICE_CHANGED "device-changed"
|
||||
#define NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED "device-metered-changed"
|
||||
|
||||
struct _NMActiveConnection {
|
||||
GObject parent;
|
||||
|
|
@ -78,6 +79,9 @@ typedef struct {
|
|||
void (*device_changed) (NMActiveConnection *connection,
|
||||
NMDevice *new_device,
|
||||
NMDevice *old_device);
|
||||
|
||||
void (*device_metered_changed) (NMActiveConnection *connection,
|
||||
NMMetered new_value);
|
||||
} NMActiveConnectionClass;
|
||||
|
||||
GType nm_active_connection_get_type (void);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ typedef struct {
|
|||
GArray *wins;
|
||||
guint32 mtu;
|
||||
NMIPConfigSource mtu_source;
|
||||
gboolean metered;
|
||||
} NMIP4ConfigPrivate;
|
||||
|
||||
/* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
|
||||
|
|
@ -574,6 +575,10 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src)
|
|||
for (i = 0; i < nm_ip4_config_get_num_wins (src); i++)
|
||||
nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
|
||||
|
||||
/* metered flag */
|
||||
nm_ip4_config_set_metered (dst, nm_ip4_config_get_metered (dst) ||
|
||||
nm_ip4_config_get_metered (src));
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (dst));
|
||||
}
|
||||
|
||||
|
|
@ -1028,6 +1033,12 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
|
|||
has_minor_changes = TRUE;
|
||||
}
|
||||
|
||||
/* metered */
|
||||
if (src_priv->metered != dst_priv->metered) {
|
||||
dst_priv->metered = src_priv->metered;
|
||||
has_minor_changes = TRUE;
|
||||
}
|
||||
|
||||
/* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
|
||||
* regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
|
||||
g_assert (config_equal == !has_relevant_changes);
|
||||
|
|
@ -1098,6 +1109,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail)
|
|||
}
|
||||
|
||||
g_message (" n-dflt: %d", nm_ip4_config_get_never_default (config));
|
||||
g_message (" mtrd: %d", (int) nm_ip4_config_get_metered (config));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -1744,6 +1756,24 @@ nm_ip4_config_get_mtu_source (const NMIP4Config *config)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
void
|
||||
nm_ip4_config_set_metered (NMIP4Config *config, gboolean metered)
|
||||
{
|
||||
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
||||
|
||||
priv->metered = !!metered;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_ip4_config_get_metered (const NMIP4Config *config)
|
||||
{
|
||||
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
||||
|
||||
return priv->metered;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static inline void
|
||||
hash_u32 (GChecksum *sum, guint32 n)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -146,6 +146,10 @@ void nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu, NMIPConfigSource s
|
|||
guint32 nm_ip4_config_get_mtu (const NMIP4Config *config);
|
||||
NMIPConfigSource nm_ip4_config_get_mtu_source (const NMIP4Config *config);
|
||||
|
||||
/* Metered */
|
||||
void nm_ip4_config_set_metered (NMIP4Config *config, gboolean metered);
|
||||
gboolean nm_ip4_config_get_metered (const NMIP4Config *config);
|
||||
|
||||
void nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only);
|
||||
gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b);
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,7 @@ typedef struct {
|
|||
guint ac_cleanup_id;
|
||||
NMActiveConnection *primary_connection;
|
||||
NMActiveConnection *activating_connection;
|
||||
NMMetered metered;
|
||||
|
||||
GSList *devices;
|
||||
NMState state;
|
||||
|
|
@ -233,6 +234,7 @@ enum {
|
|||
PROP_PRIMARY_CONNECTION_TYPE,
|
||||
PROP_ACTIVATING_CONNECTION,
|
||||
PROP_DEVICES,
|
||||
PROP_METERED,
|
||||
|
||||
/* Not exported */
|
||||
PROP_HOSTNAME,
|
||||
|
|
@ -657,6 +659,30 @@ find_best_device_state (NMManager *manager)
|
|||
return best_state;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_manager_update_metered (NMManager *manager)
|
||||
{
|
||||
NMManagerPrivate *priv;
|
||||
NMDevice *device;
|
||||
NMMetered value = NM_METERED_UNKNOWN;
|
||||
|
||||
g_return_if_fail (NM_IS_MANAGER (manager));
|
||||
priv = NM_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
if (priv->primary_connection) {
|
||||
device = nm_active_connection_get_device (priv->primary_connection);
|
||||
if (device)
|
||||
value = nm_device_get_metered (device);
|
||||
}
|
||||
|
||||
if (value != priv->metered) {
|
||||
priv->metered = value;
|
||||
nm_log_dbg (LOGD_CORE, "New manager metered value: %d",
|
||||
(int) priv->metered);
|
||||
g_object_notify (G_OBJECT (manager), NM_MANAGER_METERED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nm_manager_update_state (NMManager *manager)
|
||||
{
|
||||
|
|
@ -4259,6 +4285,14 @@ firmware_dir_changed (GFileMonitor *monitor,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
connection_metered_changed (GObject *object,
|
||||
NMMetered metered,
|
||||
gpointer user_data)
|
||||
{
|
||||
nm_manager_update_metered (NM_MANAGER (user_data));
|
||||
}
|
||||
|
||||
static void
|
||||
policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
|
|
@ -4281,11 +4315,23 @@ policy_default_device_changed (GObject *object, GParamSpec *pspec, gpointer user
|
|||
ac = NULL;
|
||||
|
||||
if (ac != priv->primary_connection) {
|
||||
g_clear_object (&priv->primary_connection);
|
||||
if (priv->primary_connection) {
|
||||
g_signal_handlers_disconnect_by_func (priv->primary_connection,
|
||||
G_CALLBACK (connection_metered_changed),
|
||||
self);
|
||||
g_clear_object (&priv->primary_connection);
|
||||
}
|
||||
|
||||
priv->primary_connection = ac ? g_object_ref (ac) : NULL;
|
||||
|
||||
if (priv->primary_connection) {
|
||||
g_signal_connect (priv->primary_connection, NM_ACTIVE_CONNECTION_DEVICE_METERED_CHANGED,
|
||||
G_CALLBACK (connection_metered_changed), self);
|
||||
}
|
||||
nm_log_dbg (LOGD_CORE, "PrimaryConnection now %s", ac ? nm_active_connection_get_id (ac) : "(none)");
|
||||
g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION);
|
||||
g_object_notify (G_OBJECT (self), NM_MANAGER_PRIMARY_CONNECTION_TYPE);
|
||||
nm_manager_update_metered (self);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4879,6 +4925,8 @@ nm_manager_init (NMManager *manager)
|
|||
|
||||
/* Update timestamps in active connections */
|
||||
priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, manager);
|
||||
|
||||
priv->metered = NM_METERED_UNKNOWN;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -4963,6 +5011,9 @@ get_property (GObject *object, guint prop_id,
|
|||
}
|
||||
g_value_take_boxed (value, array);
|
||||
break;
|
||||
case PROP_METERED:
|
||||
g_value_set_uint (value, priv->metered);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -5238,6 +5289,20 @@ nm_manager_class_init (NMManagerClass *manager_class)
|
|||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMManager:metered:
|
||||
*
|
||||
* Whether the connectivity is metered.
|
||||
*
|
||||
* Since: 1.0.6
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_METERED,
|
||||
g_param_spec_uint (NM_MANAGER_METERED, "", "",
|
||||
0, G_MAXUINT32, NM_METERED_UNKNOWN,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* signals */
|
||||
signals[DEVICE_ADDED] =
|
||||
g_signal_new ("device-added",
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#define NM_MANAGER_PRIMARY_CONNECTION_TYPE "primary-connection-type"
|
||||
#define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection"
|
||||
#define NM_MANAGER_DEVICES "devices"
|
||||
#define NM_MANAGER_METERED "metered"
|
||||
|
||||
/* Not exported */
|
||||
#define NM_MANAGER_HOSTNAME "hostname"
|
||||
|
|
|
|||
|
|
@ -250,6 +250,15 @@ make_connection_setting (const char *file,
|
|||
g_free (value);
|
||||
}
|
||||
|
||||
switch (svTrueValue (ifcfg, "CONNECTION_METERED", -1)) {
|
||||
case TRUE:
|
||||
g_object_set (s_con, NM_SETTING_CONNECTION_METERED, NM_METERED_YES, NULL);
|
||||
break;
|
||||
case FALSE:
|
||||
g_object_set (s_con, NM_SETTING_CONNECTION_METERED, NM_METERED_NO, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
return NM_SETTING (s_con);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -303,11 +303,11 @@ svGetValueFull (shvarFile *s, const char *key, gboolean verbatim)
|
|||
* return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false")
|
||||
* return <default> otherwise
|
||||
*/
|
||||
gboolean
|
||||
svTrueValue (shvarFile *s, const char *key, gboolean def)
|
||||
gint
|
||||
svTrueValue (shvarFile *s, const char *key, gint def)
|
||||
{
|
||||
char *tmp;
|
||||
gboolean returnValue = def;
|
||||
gint returnValue = def;
|
||||
|
||||
tmp = svGetValue (s, key, FALSE);
|
||||
if (!tmp)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ char *svGetValueFull (shvarFile *s, const char *key, gboolean verbatim);
|
|||
* return FALSE if <key> resolves to any non-truth value (e.g. "no", "n", "false")
|
||||
* return <def> otherwise
|
||||
*/
|
||||
gboolean svTrueValue (shvarFile *s, const char *key, gboolean def);
|
||||
gint svTrueValue (shvarFile *s, const char *key, gint def);
|
||||
|
||||
gint64 svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 max, gint64 fallback);
|
||||
|
||||
|
|
|
|||
|
|
@ -1764,6 +1764,17 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
|
|||
svSetValue (ifcfg, "GATEWAY_PING_TIMEOUT", tmp, FALSE);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
switch (nm_setting_connection_get_metered (s_con)) {
|
||||
case NM_METERED_YES:
|
||||
svSetValue (ifcfg, "CONNECTION_METERED", "yes", FALSE);
|
||||
break;
|
||||
case NM_METERED_NO:
|
||||
svSetValue (ifcfg, "CONNECTION_METERED", "no", FALSE);
|
||||
break;
|
||||
default:
|
||||
svSetValue (ifcfg, "CONNECTION_METERED", NULL, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue