summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-network/sd-dhcp-client.c')
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 137537253a..5ec0e661f7 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -34,6 +34,8 @@
#include "dhcp-internal.h"
#include "dhcp-lease-internal.h"
#include "dhcp-protocol.h"
+#include "dns-domain.h"
+#include "hostname-util.h"
#include "random-util.h"
#include "string-util.h"
#include "util.h"
@@ -298,6 +300,9 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
assert_return(client, -EINVAL);
+ if (!hostname_is_valid(hostname, false) && !dns_name_is_valid(hostname))
+ return -EINVAL;
+
if (streq_ptr(client->hostname, hostname))
return 0;
@@ -539,6 +544,24 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
return 0;
}
+static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset,
+ const char *fqdn) {
+ uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
+ int r;
+
+ buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */
+ DHCP_FQDN_FLAG_E; /* Canonical wire format */
+ buffer[1] = 0; /* RCODE1 (deprecated) */
+ buffer[2] = 0; /* RCODE2 (deprecated) */
+
+ r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3);
+ if (r > 0)
+ r = dhcp_option_append(message, optlen, optoffset, 0,
+ DHCP_OPTION_FQDN, 3 + r, buffer);
+
+ return r;
+}
+
static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
size_t len) {
dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
@@ -576,13 +599,21 @@ 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);
+ /* According to RFC 4702 "clients that send the Client FQDN option in
+ their messages MUST NOT also send the Host Name option". Just send
+ one of the two depending on the hostname type.
+ */
+ if (dns_name_single_label(client->hostname)) {
+ /* it is unclear from RFC 2131 if client should send hostname in
+ DHCPDISCOVER but dhclient does and so we do as well
+ */
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ DHCP_OPTION_HOST_NAME,
+ strlen(client->hostname), client->hostname);
+ } else
+ r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
+ client->hostname);
if (r < 0)
return r;
}
@@ -688,9 +719,13 @@ static int client_send_request(sd_dhcp_client *client) {
}
if (client->hostname) {
- r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_HOST_NAME,
- strlen(client->hostname), client->hostname);
+ if (dns_name_single_label(client->hostname))
+ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
+ DHCP_OPTION_HOST_NAME,
+ strlen(client->hostname), client->hostname);
+ else
+ r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
+ client->hostname);
if (r < 0)
return r;
}