diff options
Diffstat (limited to 'src/dhcp-manager')
| -rw-r--r-- | src/dhcp-manager/nm-dhcp-client.c | 21 | ||||
| -rw-r--r-- | src/dhcp-manager/nm-dhcp-manager.c | 2 | ||||
| -rw-r--r-- | src/dhcp-manager/nm-dhcp-systemd.c | 7 | ||||
| -rw-r--r-- | src/dhcp-manager/nm-dhcp-utils.c | 3 | ||||
| -rw-r--r-- | src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h | 2 | ||||
| -rw-r--r-- | src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h | 1 | ||||
| -rw-r--r-- | src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c | 52 | ||||
| -rw-r--r-- | src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h | 1 | ||||
| -rw-r--r-- | src/dhcp-manager/tests/test-dhcp-utils.c | 60 |
9 files changed, 128 insertions, 21 deletions
diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index eb317330..7f5d5a28 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -36,6 +36,7 @@ #include "nm-dhcp-client.h" #include "nm-dhcp-utils.h" #include "nm-platform.h" +#include "gsystem-local-alloc.h" typedef struct { char * iface; @@ -284,6 +285,7 @@ nm_dhcp_client_set_state (NMDhcpClient *self, GHashTable *options) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + gs_free char *event_id = NULL; if (new_state >= NM_DHCP_STATE_BOUND) timeout_cleanup (self); @@ -308,19 +310,30 @@ nm_dhcp_client_set_state (NMDhcpClient *self, if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND)) return; + if (priv->ipv6 && new_state == NM_DHCP_STATE_BOUND) { + char *start, *iaid; + + iaid = g_hash_table_lookup (options, "iaid"); + start = g_hash_table_lookup (options, "life_starts"); + if (iaid && start) + event_id = g_strdup_printf ("%s|%s", iaid, start); + } + nm_log_info (priv->ipv6 ? LOGD_DHCP6 : LOGD_DHCP4, - "(%s): DHCPv%c state changed %s -> %s", + "(%s): DHCPv%c state changed %s -> %s%s%s%s", priv->iface, priv->ipv6 ? '6' : '4', state_to_string (priv->state), - state_to_string (new_state)); + state_to_string (new_state), + NM_PRINT_FMT_QUOTED (event_id, ", event ID=\"", event_id, "\"", "")); priv->state = new_state; g_signal_emit (G_OBJECT (self), signals[SIGNAL_STATE_CHANGED], 0, new_state, ip_config, - options); + options, + event_id); } static gboolean @@ -977,6 +990,6 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDhcpClientClass, state_changed), NULL, NULL, NULL, - G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE); + G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE, G_TYPE_STRING); } diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index f936f45c..20ddefc3 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -184,6 +184,7 @@ static void client_state_changed (NMDhcpClient *client, NMDhcpState state, GObject *ip_config, GHashTable *options, + const char *event_id, NMDhcpManager *self); static void @@ -204,6 +205,7 @@ client_state_changed (NMDhcpClient *client, NMDhcpState state, GObject *ip_config, GHashTable *options, + const char *event_id, NMDhcpManager *self) { if (state >= NM_DHCP_STATE_TIMEOUT) diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c index 12dc03cc..2bd0d72f 100644 --- a/src/dhcp-manager/nm-dhcp-systemd.c +++ b/src/dhcp-manager/nm-dhcp-systemd.c @@ -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; } diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c index 8cd4359a..ab7f26d5 100644 --- a/src/dhcp-manager/nm-dhcp-utils.c +++ b/src/dhcp-manager/nm-dhcp-utils.c @@ -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: diff --git a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h index 9e184ac4..71f7f143 100644 --- a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h @@ -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); diff --git a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h index abca9422..aa37e9b0 100644 --- a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h +++ b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h @@ -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, diff --git a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c index 2d13d503..0b5048a6 100644 --- a/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c @@ -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; diff --git a/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h b/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h index 4296b91d..079a1bb3 100644 --- a/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h +++ b/src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h @@ -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); diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c index 53688a5b..618188df 100644 --- a/src/dhcp-manager/tests/test-dhcp-utils.c +++ b/src/dhcp-manager/tests/test-dhcp-utils.c @@ -72,7 +72,7 @@ static void test_generic_options (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; const NMPlatformIP4Route *route; guint32 tmp; @@ -147,7 +147,7 @@ static void test_wins_options (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; guint32 tmp; const char *expected_wins1 = "63.12.199.5"; @@ -176,6 +176,31 @@ test_wins_options (void) } static void +test_vendor_option_metered (void) +{ + GHashTable *options; + gs_unref_object NMIP4Config *ip4_config = NULL; + 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); + g_clear_object (&ip4_config); + + 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, const char *expected_dest, @@ -208,7 +233,7 @@ static void test_classless_static_routes_1 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_route2_dest = "10.0.0.0"; @@ -236,7 +261,7 @@ static void test_classless_static_routes_2 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_route2_dest = "10.0.0.0"; @@ -264,7 +289,7 @@ static void test_fedora_dhclient_classless_static_routes (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "129.210.177.128"; const char *expected_route1_gw = "192.168.0.113"; const char *expected_route2_dest = "2.0.0.0"; @@ -296,7 +321,7 @@ static void test_dhclient_invalid_classless_routes_1 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; static const Option data[] = { @@ -325,7 +350,7 @@ static void test_dhcpcd_invalid_classless_routes_1 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "10.1.1.5"; const char *expected_route1_gw = "10.1.1.1"; const char *expected_route2_dest = "100.99.88.56"; @@ -359,7 +384,7 @@ static void test_dhclient_invalid_classless_routes_2 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "10.1.1.5"; const char *expected_route1_gw = "10.1.1.1"; const char *expected_route2_dest = "100.99.88.56"; @@ -392,7 +417,7 @@ static void test_dhcpcd_invalid_classless_routes_2 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "10.1.1.5"; const char *expected_route1_gw = "10.1.1.1"; const char *expected_route2_dest = "100.99.88.56"; @@ -427,7 +452,7 @@ static void test_dhclient_invalid_classless_routes_3 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; static const Option data[] = { @@ -455,7 +480,7 @@ static void test_dhcpcd_invalid_classless_routes_3 (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; static Option data[] = { @@ -483,7 +508,7 @@ static void test_dhclient_gw_in_classless_routes (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_gateway = "192.2.3.4"; @@ -511,7 +536,7 @@ static void test_dhcpcd_gw_in_classless_routes (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_route1_dest = "192.168.10.0"; const char *expected_route1_gw = "192.168.1.1"; const char *expected_gateway = "192.2.3.4"; @@ -539,7 +564,7 @@ static void test_escaped_domain_searches (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const char *expected_search0 = "host1"; const char *expected_search1 = "host2"; const char *expected_search2 = "host3"; @@ -566,7 +591,7 @@ static void test_invalid_escaped_domain_searches (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; static const Option data[] = { { "domain_search", "host1\\aahost2\\032host3" }, { NULL, NULL } @@ -591,7 +616,7 @@ static void test_ip4_missing_prefix (const char *ip, guint32 expected_prefix) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; options = fill_table (generic_options, NULL); @@ -631,7 +656,7 @@ static void test_ip4_prefix_classless (void) { GHashTable *options; - NMIP4Config *ip4_config; + gs_unref_object NMIP4Config *ip4_config = NULL; const NMPlatformIP4Address *address; /* Ensure that the missing-subnet-mask handler doesn't mangle classless @@ -716,6 +741,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 (); } |