diff options
| author | Michael Biebl <biebl@debian.org> | 2016-03-01 16:55:22 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2016-03-01 16:55:22 +0100 |
| commit | c2de0d98ba39e0a1a970d066fd19be786092f376 (patch) | |
| tree | 3838363c06a6019db6cf1f882ea34ebded63c38b /src/dhcp-manager/nm-dhcp-systemd.c | |
| parent | 494f296a3baab08522617b24b1f126d8f9a17502 (diff) | |
Imported Upstream version 1.1.91 upstream/1.1.91
Diffstat (limited to 'src/dhcp-manager/nm-dhcp-systemd.c')
| -rw-r--r-- | src/dhcp-manager/nm-dhcp-systemd.c | 203 |
1 files changed, 121 insertions, 82 deletions
diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c index 4f68a0b6..b5a3d67c 100644 --- a/src/dhcp-manager/nm-dhcp-systemd.c +++ b/src/dhcp-manager/nm-dhcp-systemd.c @@ -16,7 +16,7 @@ * Copyright (C) 2014 Red Hat, Inc. */ -#include "config.h" +#include "nm-default.h" #include <string.h> #include <stdlib.h> @@ -28,7 +28,6 @@ #include <ctype.h> #include <net/if_arp.h> -#include "nm-default.h" #include "nm-dhcp-systemd.h" #include "nm-utils.h" #include "nm-dhcp-utils.h" @@ -37,21 +36,20 @@ #include "sd-dhcp-client.h" #include "sd-dhcp6-client.h" -#include "dhcp-protocol.h" + +/* we use a private systemd header, thus need to include nm-sd-adapt.h. */ +#include "nm-sd-adapt.h" #include "dhcp-lease-internal.h" -#include "dhcp6-protocol.h" -#include "dhcp6-lease-internal.h" G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT) #define NM_DHCP_SYSTEMD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdPrivate)) typedef struct { - struct sd_dhcp_client *client4; - struct sd_dhcp6_client *client6; + sd_dhcp_client *client4; + sd_dhcp6_client *client6; char *lease_file; - guint timeout_id; guint request_count; gboolean privacy; @@ -62,7 +60,6 @@ typedef struct { #define DHCP_OPTION_NIS_DOMAIN 40 #define DHCP_OPTION_NIS_SERVERS 41 #define DHCP_OPTION_DOMAIN_SEARCH 119 -#define DHCP_OPTION_RFC3442_ROUTES 121 #define DHCP_OPTION_MS_ROUTES 249 #define DHCP_OPTION_WPAD 252 @@ -88,53 +85,53 @@ typedef struct { #define REQPREFIX "requested_" static const ReqOption dhcp4_requests[] = { - { DHCP_OPTION_SUBNET_MASK, REQPREFIX "subnet_mask", TRUE }, - { DHCP_OPTION_TIME_OFFSET, REQPREFIX "time_offset", TRUE }, - { DHCP_OPTION_ROUTER, REQPREFIX "routers", TRUE }, - { DHCP_OPTION_DOMAIN_NAME_SERVER, REQPREFIX "domain_name_servers", TRUE }, - { DHCP_OPTION_HOST_NAME, REQPREFIX "host_name", TRUE }, - { DHCP_OPTION_DOMAIN_NAME, REQPREFIX "domain_name", TRUE }, - { DHCP_OPTION_INTERFACE_MTU, REQPREFIX "interface_mtu", TRUE }, - { DHCP_OPTION_BROADCAST, REQPREFIX "broadcast_address", TRUE }, - { DHCP_OPTION_STATIC_ROUTE, REQPREFIX "static_routes", TRUE }, - { DHCP_OPTION_NIS_DOMAIN, REQPREFIX "nis_domain", TRUE }, - { DHCP_OPTION_NIS_SERVERS, REQPREFIX "nis_servers", TRUE }, - { DHCP_OPTION_NTP_SERVER, REQPREFIX "ntp_servers", TRUE }, - { DHCP_OPTION_SERVER_IDENTIFIER, REQPREFIX "dhcp_server_identifier", TRUE }, - { DHCP_OPTION_DOMAIN_SEARCH, REQPREFIX "domain_search", TRUE }, - { DHCP_OPTION_CLASSLESS_STATIC_ROUTE, REQPREFIX "rfc3442_classless_static_routes", TRUE }, - { DHCP_OPTION_MS_ROUTES, REQPREFIX "ms_classless_static_routes", TRUE }, - { DHCP_OPTION_WPAD, REQPREFIX "wpad", TRUE }, + { SD_DHCP_OPTION_SUBNET_MASK, REQPREFIX "subnet_mask", TRUE }, + { SD_DHCP_OPTION_TIME_OFFSET, REQPREFIX "time_offset", TRUE }, + { SD_DHCP_OPTION_ROUTER, REQPREFIX "routers", TRUE }, + { SD_DHCP_OPTION_DOMAIN_NAME_SERVER, REQPREFIX "domain_name_servers", TRUE }, + { SD_DHCP_OPTION_HOST_NAME, REQPREFIX "host_name", TRUE }, + { SD_DHCP_OPTION_DOMAIN_NAME, REQPREFIX "domain_name", TRUE }, + { SD_DHCP_OPTION_INTERFACE_MTU, REQPREFIX "interface_mtu", TRUE }, + { SD_DHCP_OPTION_BROADCAST, REQPREFIX "broadcast_address", TRUE }, + { SD_DHCP_OPTION_STATIC_ROUTE, REQPREFIX "static_routes", TRUE }, + { DHCP_OPTION_NIS_DOMAIN, REQPREFIX "nis_domain", TRUE }, + { DHCP_OPTION_NIS_SERVERS, REQPREFIX "nis_servers", TRUE }, + { SD_DHCP_OPTION_NTP_SERVER, REQPREFIX "ntp_servers", TRUE }, + { SD_DHCP_OPTION_SERVER_IDENTIFIER, REQPREFIX "dhcp_server_identifier", TRUE }, + { DHCP_OPTION_DOMAIN_SEARCH, REQPREFIX "domain_search", TRUE }, + { SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, REQPREFIX "rfc3442_classless_static_routes", TRUE }, + { DHCP_OPTION_MS_ROUTES, REQPREFIX "ms_classless_static_routes", TRUE }, + { DHCP_OPTION_WPAD, REQPREFIX "wpad", TRUE }, /* Internal values */ - { DHCP_OPTION_IP_ADDRESS_LEASE_TIME, REQPREFIX "expiry", FALSE }, - { DHCP_OPTION_CLIENT_IDENTIFIER, REQPREFIX "dhcp_client_identifier", FALSE }, - { DHCP_OPTION_IP_ADDRESS, REQPREFIX "ip_address", FALSE }, + { SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, REQPREFIX "expiry", FALSE }, + { SD_DHCP_OPTION_CLIENT_IDENTIFIER, REQPREFIX "dhcp_client_identifier", FALSE }, + { DHCP_OPTION_IP_ADDRESS, REQPREFIX "ip_address", FALSE }, { 0, NULL, FALSE } }; static const ReqOption dhcp6_requests[] = { - { DHCP6_OPTION_CLIENTID, REQPREFIX "dhcp6_client_id", TRUE }, + { SD_DHCP6_OPTION_CLIENTID, REQPREFIX "dhcp6_client_id", TRUE }, /* Don't request server ID by default; some servers don't reply to * Information Requests that request the Server ID. */ - { DHCP6_OPTION_SERVERID, REQPREFIX "dhcp6_server_id", FALSE }, + { SD_DHCP6_OPTION_SERVERID, REQPREFIX "dhcp6_server_id", FALSE }, - { DHCP6_OPTION_DNS_SERVERS, REQPREFIX "dhcp6_name_servers", TRUE }, - { DHCP6_OPTION_DOMAIN_LIST, REQPREFIX "dhcp6_domain_search", TRUE }, - { DHCP6_OPTION_SNTP_SERVERS, REQPREFIX "dhcp6_sntp_servers", TRUE }, + { SD_DHCP6_OPTION_DNS_SERVERS, REQPREFIX "dhcp6_name_servers", TRUE }, + { SD_DHCP6_OPTION_DOMAIN_LIST, REQPREFIX "dhcp6_domain_search", TRUE }, + { SD_DHCP6_OPTION_SNTP_SERVERS, REQPREFIX "dhcp6_sntp_servers", TRUE }, /* Internal values */ - { DHCP6_OPTION_IP_ADDRESS, REQPREFIX "ip6_address", FALSE }, - { DHCP6_OPTION_PREFIXLEN, REQPREFIX "ip6_prefixlen", FALSE }, - { DHCP6_OPTION_PREFERRED_LIFE, REQPREFIX "preferred_life", FALSE }, - { DHCP6_OPTION_MAX_LIFE, REQPREFIX "max_life", FALSE }, - { DHCP6_OPTION_STARTS, REQPREFIX "starts", FALSE }, - { DHCP6_OPTION_LIFE_STARTS, REQPREFIX "life_starts", FALSE }, - { DHCP6_OPTION_RENEW, REQPREFIX "renew", FALSE }, - { DHCP6_OPTION_REBIND, REQPREFIX "rebind", FALSE }, - { DHCP6_OPTION_IAID, REQPREFIX "iaid", FALSE }, + { DHCP6_OPTION_IP_ADDRESS, REQPREFIX "ip6_address", FALSE }, + { DHCP6_OPTION_PREFIXLEN, REQPREFIX "ip6_prefixlen", FALSE }, + { DHCP6_OPTION_PREFERRED_LIFE, REQPREFIX "preferred_life", FALSE }, + { DHCP6_OPTION_MAX_LIFE, REQPREFIX "max_life", FALSE }, + { DHCP6_OPTION_STARTS, REQPREFIX "starts", FALSE }, + { DHCP6_OPTION_LIFE_STARTS, REQPREFIX "life_starts", FALSE }, + { DHCP6_OPTION_RENEW, REQPREFIX "renew", FALSE }, + { DHCP6_OPTION_REBIND, REQPREFIX "rebind", FALSE }, + { DHCP6_OPTION_IAID, REQPREFIX "iaid", FALSE }, { 0, NULL, FALSE } }; @@ -151,7 +148,7 @@ take_option (GHashTable *options, for (i = 0; requests[i].name; i++) { if (requests[i].num == option) { g_hash_table_insert (options, - (gpointer) (requests[i].name + STRLEN (REQPREFIX)), + (gpointer) (requests[i].name + NM_STRLEN (REQPREFIX)), value); break; } @@ -216,13 +213,14 @@ lease_to_ip4_config (const char *iface, guint32 lifetime = 0, i; NMPlatformIP4Address address; GString *l; - struct sd_dhcp_route *routes; + gs_free sd_dhcp_route **routes = NULL; guint16 mtu; int r, num; guint64 end_time; const void *data; gsize data_len; gboolean metered = FALSE; + gboolean static_default_gateway = FALSE; g_return_val_if_fail (lease != NULL, NULL); @@ -243,7 +241,7 @@ lease_to_ip4_config (const char *iface, LOG_LEASE (LOGD_DHCP4, " plen %d", address.plen); add_option (options, dhcp4_requests, - DHCP_OPTION_SUBNET_MASK, + SD_DHCP_OPTION_SUBNET_MASK, nm_utils_inet4_ntop (tmp_addr.s_addr, NULL)); /* Lease time */ @@ -254,21 +252,12 @@ lease_to_ip4_config (const char *iface, LOG_LEASE (LOGD_DHCP4, " expires in %" G_GUINT32_FORMAT " seconds", lifetime); add_option_u64 (options, dhcp4_requests, - DHCP_OPTION_IP_ADDRESS_LEASE_TIME, + SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, end_time); address.source = NM_IP_CONFIG_SOURCE_DHCP; nm_ip4_config_add_address (ip4_config, &address); - /* Gateway */ - r = sd_dhcp_lease_get_router (lease, &tmp_addr); - if (r == 0) { - nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr); - str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL); - LOG_LEASE (LOGD_DHCP4, " gateway %s", str); - add_option (options, dhcp4_requests, DHCP_OPTION_ROUTER, str); - } - /* DNS Servers */ num = sd_dhcp_lease_get_dns (lease, &addr_list); if (num > 0) { @@ -282,7 +271,7 @@ lease_to_ip4_config (const char *iface, } } if (l->len) - add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME_SERVER, l->str); + add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, l->str); g_string_free (l, TRUE); } @@ -298,14 +287,14 @@ lease_to_ip4_config (const char *iface, nm_ip4_config_add_domain (ip4_config, *s); } g_strfreev (domains); - add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME, str); + add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME, str); } /* Hostname */ r = sd_dhcp_lease_get_hostname (lease, &str); if (r == 0) { LOG_LEASE (LOGD_DHCP4, " hostname '%s'", str); - add_option (options, dhcp4_requests, DHCP_OPTION_HOST_NAME, str); + add_option (options, dhcp4_requests, SD_DHCP_OPTION_HOST_NAME, str); } /* Routes */ @@ -313,32 +302,70 @@ lease_to_ip4_config (const char *iface, if (num > 0) { l = g_string_sized_new (30); for (i = 0; i < num; i++) { - NMPlatformIP4Route route; + NMPlatformIP4Route route = { 0 }; const char *gw_str; - - memset (&route, 0, sizeof (route)); - route.network = routes[i].dst_addr.s_addr; - route.plen = routes[i].dst_prefixlen; - route.gateway = routes[i].gw_addr.s_addr; - route.source = NM_IP_CONFIG_SOURCE_DHCP; - route.metric = default_priority; - nm_ip4_config_add_route (ip4_config, &route); - - str = nm_utils_inet4_ntop (route.network, buf); - gw_str = nm_utils_inet4_ntop (route.gateway, NULL); - LOG_LEASE (LOGD_DHCP4, " static route %s/%d gw %s", str, route.plen, gw_str); - - g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str); + guint8 plen; + struct in_addr a; + + if (sd_dhcp_route_get_destination (routes[i], &a) < 0) + continue; + route.network = a.s_addr; + + if (sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0) + continue; + route.plen = plen; + + if (sd_dhcp_route_get_gateway (routes[i], &a) < 0) + continue; + route.gateway = a.s_addr; + + if (route.plen) { + route.source = NM_IP_CONFIG_SOURCE_DHCP; + route.metric = default_priority; + nm_ip4_config_add_route (ip4_config, &route); + + str = nm_utils_inet4_ntop (route.network, buf); + gw_str = nm_utils_inet4_ntop (route.gateway, NULL); + LOG_LEASE (LOGD_DHCP4, " static route %s/%d gw %s", str, route.plen, gw_str); + + g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str); + } else { + if (!static_default_gateway) { + static_default_gateway = TRUE; + nm_ip4_config_set_gateway (ip4_config, route.gateway); + + str = nm_utils_inet4_ntop (route.gateway, NULL); + LOG_LEASE (LOGD_DHCP4, " gateway %s", str); + add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str); + } + } } - add_option (options, dhcp4_requests, DHCP_OPTION_RFC3442_ROUTES, l->str); + if (l->len) + add_option (options, dhcp4_requests, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, l->str); g_string_free (l, TRUE); } + /* If the DHCP server returns both a Classless Static Routes option and a + * Router option, the DHCP client MUST ignore the Router option [RFC 3442]. + * Be more lenient and ignore the Router option only if Classless Static + * Routes contain a default gateway (as other DHCP backends do). + */ + /* Gateway */ + if (!static_default_gateway) { + r = sd_dhcp_lease_get_router (lease, &tmp_addr); + if (r == 0) { + nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr); + str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL); + LOG_LEASE (LOGD_DHCP4, " gateway %s", str); + add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str); + } + } + /* MTU */ r = sd_dhcp_lease_get_mtu (lease, &mtu); if (r == 0 && mtu) { nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); - add_option_u32 (options, dhcp4_requests, DHCP_OPTION_INTERFACE_MTU, mtu); + add_option_u32 (options, dhcp4_requests, SD_DHCP_OPTION_INTERFACE_MTU, mtu); LOG_LEASE (LOGD_DHCP4, " mtu %u", mtu); } @@ -351,13 +378,13 @@ lease_to_ip4_config (const char *iface, LOG_LEASE (LOGD_DHCP4, " ntp server '%s'", str); g_string_append_printf (l, "%s%s", l->len ? " " : "", str); } - add_option (options, dhcp4_requests, DHCP_OPTION_NTP_SERVER, l->str); + add_option (options, dhcp4_requests, SD_DHCP_OPTION_NTP_SERVER, l->str); g_string_free (l, TRUE); } r = sd_dhcp_lease_get_vendor_specific (lease, &data, &data_len); if (r >= 0) - metered = !!memmem (data, data_len, "ANDROID_METERED", STRLEN ("ANDROID_METERED")); + metered = !!memmem (data, data_len, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED")); nm_ip4_config_set_metered (ip4_config, metered); return ip4_config; @@ -517,7 +544,7 @@ get_arp_type (const GByteArray *hwaddr) else if (hwaddr->len == INFINIBAND_ALEN) return ARPHRD_INFINIBAND; else - g_assert_not_reached (); + return ARPHRD_NONE; } static gboolean @@ -534,6 +561,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last const char *hostname, *fqdn; int r, i; gboolean success = FALSE; + guint16 arp_type; g_assert (priv->client4 == NULL); g_assert (priv->client6 == NULL); @@ -555,10 +583,16 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last hwaddr = nm_dhcp_client_get_hw_addr (client); if (hwaddr) { + arp_type= get_arp_type (hwaddr); + if (arp_type == ARPHRD_NONE) { + nm_log_warn (LOGD_DHCP4, "(%s): failed to determine ARP type", iface); + goto error; + } + r = sd_dhcp_client_set_mac (priv->client4, hwaddr->data, hwaddr->len, - get_arp_type (hwaddr)); + arp_type); if (r < 0) { nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP MAC address (%d)", iface, r); goto error; @@ -661,6 +695,8 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last goto error; } + nm_dhcp_client_start_timeout (client); + success = TRUE; error: @@ -807,10 +843,13 @@ stop (NMDhcpClient *client, gboolean release, const GByteArray *duid) NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (client); int r = 0; - if (priv->client4) + if (priv->client4) { + sd_dhcp_client_set_callback (priv->client4, NULL, NULL); r = sd_dhcp_client_stop (priv->client4); - else if (priv->client6) + } else if (priv->client6) { + sd_dhcp6_client_set_callback (priv->client6, NULL, NULL); r = sd_dhcp6_client_stop (priv->client6); + } if (r) { nm_log_warn (priv->client6 ? LOGD_DHCP6 : LOGD_DHCP4, |