summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Yakubovich <eugene.yakubovich@coreos.com>2014-07-01 11:58:49 -0700
committerTom Gundersen <teg@jklm.no>2014-07-01 22:02:25 +0200
commit4cc7a82c9490a3c5ae03b1d6d168ce40ba499e23 (patch)
tree0b806eddc7563072cb1398ae602ced46ee840b4c
parent0a8a0fad010018be0f46d1c2e077ade0eb27c7db (diff)
networkd: send hostname to dhcp server
Send hostname (option 12) in DISCOVER and REQUEST messages so the DHCP server could use it to register with dynamic DNS and such. To opt-out of this behaviour set SendHostname to false in [DHCP] section of .network file [tomegun: rebased, made sure a failing set_hostname is a noop and moved config from DHCPv4 to DHCP]
-rw-r--r--man/systemd.network.xml7
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c42
-rw-r--r--src/network/networkd-link.c26
-rw-r--r--src/network/networkd-network-gperf.gperf5
-rw-r--r--src/network/networkd-network.c1
-rw-r--r--src/network/networkd.h1
-rw-r--r--src/systemd/sd-dhcp-client.h1
7 files changed, 81 insertions, 2 deletions
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 707ced13d2..2b0eb567be 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -405,6 +405,13 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>SendHostname=</varname></term>
+ <listitem>
+ <para>When true (the default), the machine's hostname will be sent to the DHCP
+ server</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>UseHostname=</varname></term>
<listitem>
<para>When true (the default), the hostname received from the DHCP server
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 8e9f5bd827..d8a9d20e4c 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -56,6 +56,7 @@ struct sd_dhcp_client {
uint8_t type;
struct ether_addr mac_addr;
} _packed_ client_id;
+ char *hostname;
uint32_t xid;
usec_t start_time;
uint16_t secs;
@@ -178,6 +179,27 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client,
return 0;
}
+int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
+ const char *hostname) {
+ char *new_hostname = NULL;
+
+ assert_return(client, -EINVAL);
+
+ if (streq_ptr(client->hostname, hostname))
+ return 0;
+
+ if (hostname) {
+ new_hostname = strdup(hostname);
+ if (!new_hostname)
+ return -ENOMEM;
+ }
+
+ free(client->hostname);
+ client->hostname = new_hostname;
+
+ return 0;
+}
+
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
assert_return(client, -EINVAL);
assert_return(ret, -EINVAL);
@@ -386,6 +408,17 @@ static int client_send_discover(sd_dhcp_client *client) {
return r;
}
+ /* it is unclear from RFC 2131 if client should send hostname in
+ DHCPDISCOVER but dhclient does and so we do as well
+ */
+ if (client->hostname) {
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ DHCP_OPTION_HOST_NAME,
+ strlen(client->hostname), client->hostname);
+ if (r < 0)
+ return r;
+ }
+
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_END, 0, NULL);
if (r < 0)
@@ -477,6 +510,14 @@ static int client_send_request(sd_dhcp_client *client) {
return -EINVAL;
}
+ if (client->hostname) {
+ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
+ DHCP_OPTION_HOST_NAME,
+ strlen(client->hostname), client->hostname);
+ if (r < 0)
+ return r;
+ }
+
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_END, 0, NULL);
if (r < 0)
@@ -1364,6 +1405,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
sd_dhcp_lease_unref(client->lease);
free(client->req_opts);
+ free(client->hostname);
free(client);
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index a523a3e9b2..3324276bcc 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -21,6 +21,7 @@
#include <netinet/ether.h>
#include <linux/if.h>
+#include <unistd.h>
#include "networkd.h"
#include "libudev-private.h"
@@ -1927,6 +1928,18 @@ static int link_enter_enslave(Link *link) {
return 0;
}
+/* make sure the hostname is not "localhost" */
+static bool is_localhost(const char *hostname) {
+ assert(hostname);
+
+ return streq(hostname, "localhost") ||
+ streq(hostname, "localhost.") ||
+ endswith(hostname, ".localhost") ||
+ endswith(hostname, ".localhost.") ||
+ endswith(hostname, ".localdomain") ||
+ endswith(hostname, ".localdomain.");
+}
+
static int link_configure(Link *link) {
int r;
@@ -1992,6 +2005,7 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
}
+
if (link->network->dhcp_routes) {
r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_STATIC_ROUTE);
if (r < 0)
@@ -2000,6 +2014,18 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
}
+
+ if (link->network->dhcp_sendhost) {
+ _cleanup_free_ char *hostname = gethostname_malloc();
+ if (!hostname)
+ return -ENOMEM;
+
+ if (!is_localhost(hostname)) {
+ r = sd_dhcp_client_set_hostname(link->dhcp_client, hostname);
+ if (r < 0)
+ return r;
+ }
+ }
}
if (link->network->dhcp_server) {
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index b6d52e7335..3aaae4c94b 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -47,11 +47,12 @@ DHCP.UseDNS, config_parse_bool, 0,
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domainname)
+DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
+DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
-/* backwards compatibility */
+/* backwards compatibility: do not add new entries to this section */
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domainname)
-DHCPv4.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index f60f7c812c..9ab4f23068 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -90,6 +90,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->dhcp_hostname = true;
network->dhcp_domainname = true;
network->dhcp_routes = true;
+ network->dhcp_sendhost = true;
r = config_parse(NULL, filename, file, "Match\0Network\0Address\0Route\0DHCPv4\0", config_item_perf_lookup,
(void*) network_network_gperf_lookup, false, false, network);
diff --git a/src/network/networkd.h b/src/network/networkd.h
index d1b0bb72ae..c2b88acd61 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -169,6 +169,7 @@ struct Network {
bool dhcp_mtu;
bool dhcp_hostname;
bool dhcp_domainname;
+ bool dhcp_sendhost;
bool dhcp_critical;
bool dhcp_routes;
bool ipv4ll;
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index 0ed7d0f135..c3ea0592f6 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -51,6 +51,7 @@ int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
int sd_dhcp_client_set_mac(sd_dhcp_client *client,
const struct ether_addr *addr);
+int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname);
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret);
int sd_dhcp_client_stop(sd_dhcp_client *client);