summaryrefslogtreecommitdiffstats
path: root/src/libsystemd-network
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp-option.c55
-rw-r--r--src/libsystemd-network/dhcp-option.h1
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c10
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c14
4 files changed, 59 insertions, 21 deletions
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 5e216c5..5679091 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -10,6 +10,8 @@
#include "alloc-util.h"
#include "dhcp-option.h"
#include "dhcp-server-internal.h"
+#include "dns-domain.h"
+#include "hostname-util.h"
#include "memory-util.h"
#include "ordered-set.h"
#include "strv.h"
@@ -396,27 +398,56 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c
}
int dhcp_option_parse_string(const uint8_t *option, size_t len, char **ret) {
+ _cleanup_free_ char *string = NULL;
int r;
assert(option);
assert(ret);
- if (len <= 0)
- *ret = mfree(*ret);
- else {
- char *string;
+ if (len <= 0) {
+ *ret = NULL;
+ return 0;
+ }
- /*
- * One trailing NUL byte is OK, we don't mind. See:
- * https://github.com/systemd/systemd/issues/1337
- */
- r = make_cstring((const char *) option, len, MAKE_CSTRING_ALLOW_TRAILING_NUL, &string);
- if (r < 0)
- return r;
+ /* One trailing NUL byte is OK, we don't mind. See:
+ * https://github.com/systemd/systemd/issues/1337 */
+ r = make_cstring((const char *) option, len, MAKE_CSTRING_ALLOW_TRAILING_NUL, &string);
+ if (r < 0)
+ return r;
+
+ if (!string_is_safe(string) || !utf8_is_valid(string))
+ return -EINVAL;
+
+ *ret = TAKE_PTR(string);
+ return 0;
+}
+
+int dhcp_option_parse_hostname(const uint8_t *option, size_t len, char **ret) {
+ _cleanup_free_ char *hostname = NULL;
+ int r;
- free_and_replace(*ret, string);
+ assert(option);
+ assert(ret);
+
+ r = dhcp_option_parse_string(option, len, &hostname);
+ if (r < 0)
+ return r;
+
+ if (!hostname) {
+ *ret = NULL;
+ return 0;
}
+ if (!hostname_is_valid(hostname, 0))
+ return -EINVAL;
+
+ r = dns_name_is_valid(hostname);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -EINVAL;
+
+ *ret = TAKE_PTR(hostname);
return 0;
}
diff --git a/src/libsystemd-network/dhcp-option.h b/src/libsystemd-network/dhcp-option.h
index 425f5b5..aaa8f84 100644
--- a/src/libsystemd-network/dhcp-option.h
+++ b/src/libsystemd-network/dhcp-option.h
@@ -44,3 +44,4 @@ int dhcp_option_parse(
char **ret_error_message);
int dhcp_option_parse_string(const uint8_t *option, size_t len, char **ret);
+int dhcp_option_parse_hostname(const uint8_t *option, size_t len, char **ret);
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index 4e3be98..202d75f 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -833,12 +833,16 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
break;
- case SD_DHCP_OPTION_ROOT_PATH:
- r = dhcp_option_parse_string(option, len, &lease->root_path);
+ case SD_DHCP_OPTION_ROOT_PATH: {
+ _cleanup_free_ char *p = NULL;
+
+ r = dhcp_option_parse_string(option, len, &p);
if (r < 0)
log_debug_errno(r, "Failed to parse root path, ignoring: %m");
- break;
+ free_and_replace(lease->root_path, p);
+ break;
+ }
case SD_DHCP_OPTION_RENEWAL_TIME:
r = lease_parse_be32_seconds(option, len, /* max_as_infinity = */ true, &lease->t1);
if (r < 0)
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index fcc5b74..b87e4d6 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -808,14 +808,16 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
req->agent_info_option = (uint8_t*)option - 2;
break;
- case SD_DHCP_OPTION_HOST_NAME:
- r = dhcp_option_parse_string(option, len, &req->hostname);
- if (r < 0) {
- log_debug_errno(r, "Failed to parse hostname, ignoring: %m");
- return 0;
- }
+ case SD_DHCP_OPTION_HOST_NAME: {
+ _cleanup_free_ char *p = NULL;
+ r = dhcp_option_parse_hostname(option, len, &p);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse hostname, ignoring: %m");
+ else
+ free_and_replace(req->hostname, p);
break;
+ }
case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
req->parameter_request_list = option;
req->parameter_request_list_len = len;