summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-06-14 12:07:26 +0200
committerThomas Haller <thaller@redhat.com>2017-06-14 13:10:05 +0200
commitbe3d897758086f86d5380bc518db92dab8dd8ce0 (patch)
treebb693eeef57863e0fee97d8c3a13ee349d62442b
parent49f8fc90bd2458174397c9c712c03fd35d96d5da (diff)
parentcd5ef1ed7dbbd235f9cfe75c44fabe74e5b0300e (diff)
downloadNetworkManager-be3d897758086f86d5380bc518db92dab8dd8ce0.tar.gz
systemd: merge branch systemd into master
- adjust nm-sd-adapt.h to new LogRealm - add support for DHCP search domain list
-rw-r--r--src/systemd/sd-adapt/nm-sd-adapt.h11
-rw-r--r--src/systemd/sd-adapt/udev.h1
-rw-r--r--src/systemd/src/basic/fileio.c16
-rw-r--r--src/systemd/src/basic/fileio.h10
-rw-r--r--src/systemd/src/basic/log.h89
-rw-r--r--src/systemd/src/basic/macro.h1
-rw-r--r--src/systemd/src/basic/time-util.c18
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-lease-internal.h2
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c8
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c139
-rw-r--r--src/systemd/src/shared/dns-domain.c42
-rw-r--r--src/systemd/src/shared/dns-domain.h2
-rw-r--r--src/systemd/src/systemd/sd-dhcp-client.h1
-rw-r--r--src/systemd/src/systemd/sd-dhcp-lease.h1
14 files changed, 291 insertions, 50 deletions
diff --git a/src/systemd/sd-adapt/nm-sd-adapt.h b/src/systemd/sd-adapt/nm-sd-adapt.h
index a8ff18bc95..3a9a744da7 100644
--- a/src/systemd/sd-adapt/nm-sd-adapt.h
+++ b/src/systemd/sd-adapt/nm-sd-adapt.h
@@ -37,7 +37,7 @@
static inline NMLogLevel
_slog_level_to_nm (int slevel)
{
- switch (slevel) {
+ switch (LOG_PRI (slevel)) {
case LOG_DEBUG: return LOGL_DEBUG;
case LOG_WARNING: return LOGL_WARN;
case LOG_CRIT:
@@ -48,7 +48,9 @@ _slog_level_to_nm (int slevel)
}
}
-#define log_internal(level, error, file, line, func, format, ...) \
+#define log_get_max_level_realm(realm) (LOG_DEBUG)
+
+#define log_internal_realm(level, error, file, line, func, format, ...) \
({ \
const int _nm_e = (error); \
const NMLogLevel _nm_l = _slog_level_to_nm ((level)); \
@@ -61,11 +63,6 @@ _slog_level_to_nm (int slevel)
(_nm_e > 0 ? -_nm_e : _nm_e); \
})
-#define log_full_errno(level, error, ...) \
-({ \
- log_internal(level, error, __FILE__, __LINE__, __func__, __VA_ARGS__); \
-})
-
#define log_assert_failed(text, file, line, func) \
G_STMT_START { \
log_internal (LOG_CRIT, 0, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting.", text, file, line, func); \
diff --git a/src/systemd/sd-adapt/udev.h b/src/systemd/sd-adapt/udev.h
index 00f60f92e4..419abcbfc2 100644
--- a/src/systemd/sd-adapt/udev.h
+++ b/src/systemd/sd-adapt/udev.h
@@ -3,3 +3,4 @@
/* dummy header */
#include "libudev.h"
+#include "strv.h"
diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c
index 711580a4de..6bcb7c1503 100644
--- a/src/systemd/src/basic/fileio.c
+++ b/src/systemd/src/basic/fileio.c
@@ -53,7 +53,7 @@
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
-int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
+int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts) {
assert(f);
assert(line);
@@ -62,6 +62,13 @@ int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
if (enforce_newline && !endswith(line, "\n"))
fputc('\n', f);
+ if (ts) {
+ struct timespec twice[2] = {*ts, *ts};
+
+ if (futimens(fileno(f), twice) < 0)
+ return -errno;
+ }
+
return fflush_and_check(f);
}
@@ -91,7 +98,7 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
return r;
}
-int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
+int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts) {
_cleanup_fclose_ FILE *f = NULL;
int q, r;
@@ -106,7 +113,8 @@ int write_string_file(const char *fn, const char *line, WriteStringFileFlags fla
goto fail;
return r;
- }
+ } else
+ assert(ts == NULL);
if (flags & WRITE_STRING_FILE_CREATE) {
f = fopen(fn, "we");
@@ -133,7 +141,7 @@ int write_string_file(const char *fn, const char *line, WriteStringFileFlags fla
}
}
- r = write_string_stream(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE));
+ r = write_string_stream_ts(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE), ts);
if (r < 0)
goto fail;
diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h
index e547614cc4..6098562265 100644
--- a/src/systemd/src/basic/fileio.h
+++ b/src/systemd/src/basic/fileio.h
@@ -35,8 +35,14 @@ typedef enum {
WRITE_STRING_FILE_VERIFY_ON_FAILURE = 8,
} WriteStringFileFlags;
-int write_string_stream(FILE *f, const char *line, bool enforce_newline);
-int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags);
+int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts);
+static inline int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
+ return write_string_stream_ts(f, line, enforce_newline, NULL);
+}
+int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts);
+static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
+ return write_string_file_ts(fn, line, flags, NULL);
+}
int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
diff --git a/src/systemd/src/basic/log.h b/src/systemd/src/basic/log.h
index af67998b51..63052862b9 100644
--- a/src/systemd/src/basic/log.h
+++ b/src/systemd/src/basic/log.h
@@ -31,6 +31,16 @@
#include "macro.h"
+typedef enum LogRealm {
+ LOG_REALM_SYSTEMD,
+ LOG_REALM_UDEV,
+ _LOG_REALM_MAX,
+} LogRealm;
+
+#ifndef LOG_REALM
+# define LOG_REALM LOG_REALM_SYSTEMD
+#endif
+
typedef enum LogTarget{
LOG_TARGET_CONSOLE,
LOG_TARGET_CONSOLE_PREFIXED,
@@ -44,14 +54,24 @@ typedef enum LogTarget{
LOG_TARGET_NULL,
_LOG_TARGET_MAX,
_LOG_TARGET_INVALID = -1
-} LogTarget;
+} LogTarget;
+
+#define LOG_REALM_PLUS_LEVEL(realm, level) \
+ ((realm) << 10 | (level))
+#define LOG_REALM_REMOVE_LEVEL(realm_level) \
+ ((realm_level >> 10))
void log_set_target(LogTarget target);
-void log_set_max_level(int level);
+void log_set_max_level_realm(LogRealm realm, int level);
+#define log_set_max_level(level) \
+ log_set_max_level_realm(LOG_REALM, (level))
+
void log_set_facility(int facility);
int log_set_target_from_string(const char *e);
-int log_set_max_level_from_string(const char *e);
+int log_set_max_level_from_string_realm(LogRealm realm, const char *e);
+#define log_set_max_level_from_string(e) \
+ log_set_max_level_from_string_realm(LOG_REALM, (e))
void log_show_color(bool b);
bool log_get_show_color(void) _pure_;
@@ -62,7 +82,11 @@ int log_show_color_from_string(const char *e);
int log_show_location_from_string(const char *e);
LogTarget log_get_target(void) _pure_;
-int log_get_max_level(void) _pure_;
+#if 0 /* NM_IGNORED */
+int log_get_max_level_realm(LogRealm realm) _pure_;
+#endif /* NM_IGNORED */
+#define log_get_max_level() \
+ log_get_max_level_realm(LOG_REALM)
int log_open(void);
void log_close(void);
@@ -73,7 +97,9 @@ void log_close_journal(void);
void log_close_kmsg(void);
void log_close_console(void);
-void log_parse_environment(void);
+void log_parse_environment_realm(LogRealm realm);
+#define log_parse_environment() \
+ log_parse_environment_realm(LOG_REALM)
#if 0 /* NM_IGNORED */
int log_dispatch_internal(
@@ -88,15 +114,19 @@ int log_dispatch_internal(
const char *extra_field,
char *buffer);
-int log_internal(
+int log_internal_realm(
int level,
int error,
const char *file,
int line,
const char *func,
const char *format, ...) _printf_(6,7);
+#endif /* NM_IGNORED */
+#define log_internal(level, ...) \
+ log_internal_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__)
-int log_internalv(
+#if 0 /* NM_IGNORED */
+int log_internalv_realm(
int level,
int error,
const char *file,
@@ -104,7 +134,10 @@ int log_internalv(
const char *func,
const char *format,
va_list ap) _printf_(6,0);
+#define log_internalv(level, ...) \
+ log_internalv_realm(LOG_REALM_PLUS_LEVEL(LOG_REALM, (level)), __VA_ARGS__)
+/* Realm is fixed to LOG_REALM_SYSTEMD for those */
int log_object_internal(
int level,
int error,
@@ -139,6 +172,7 @@ int log_struct_internal(
const char *format, ...) _printf_(6,0) _sentinel_;
int log_oom_internal(
+ LogRealm realm,
const char *file,
int line,
const char *func);
@@ -162,38 +196,51 @@ int log_dump_internal(
char *buffer);
/* Logging for various assertions */
-noreturn void log_assert_failed(
+noreturn void log_assert_failed_realm(
+ LogRealm realm,
const char *text,
const char *file,
int line,
const char *func);
+#define log_assert_failed(text, ...) \
+ log_assert_failed_realm(LOG_REALM, (text), __VA_ARGS__)
-noreturn void log_assert_failed_unreachable(
+noreturn void log_assert_failed_unreachable_realm(
+ LogRealm realm,
const char *text,
const char *file,
int line,
const char *func);
+#define log_assert_failed_unreachable(text, ...) \
+ log_assert_failed_unreachable_realm(LOG_REALM, (text), __VA_ARGS__)
-void log_assert_failed_return(
+void log_assert_failed_return_realm(
+ LogRealm realm,
const char *text,
const char *file,
int line,
const char *func);
+#define log_assert_failed_return(text, ...) \
+ log_assert_failed_return_realm(LOG_REALM, (text), __VA_ARGS__)
#define log_dispatch(level, error, buffer) \
log_dispatch_internal(level, error, __FILE__, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer)
+#endif /* NM_IGNORED */
/* Logging with level */
-#define log_full_errno(level, error, ...) \
+#define log_full_errno_realm(realm, level, error, ...) \
({ \
int _level = (level), _e = (error); \
- (log_get_max_level() >= LOG_PRI(_level)) \
- ? log_internal(_level, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \
+ (log_get_max_level_realm((realm)) >= LOG_PRI(_level)) \
+ ? log_internal_realm(LOG_REALM_PLUS_LEVEL((realm), _level), _e, \
+ __FILE__, __LINE__, __func__, __VA_ARGS__) \
: -abs(_e); \
})
-#endif /* NM_IGNORED */
-#define log_full(level, ...) log_full_errno(level, 0, __VA_ARGS__)
+#define log_full_errno(level, error, ...) \
+ log_full_errno_realm(LOG_REALM, (level), (error), __VA_ARGS__)
+
+#define log_full(level, ...) log_full_errno((level), 0, __VA_ARGS__)
/* Normal logging */
#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__)
@@ -218,13 +265,17 @@ void log_assert_failed_return(
#endif
/* Structured logging */
-#define log_struct(level, ...) log_struct_internal(level, 0, __FILE__, __LINE__, __func__, __VA_ARGS__)
-#define log_struct_errno(level, error, ...) log_struct_internal(level, error, __FILE__, __LINE__, __func__, __VA_ARGS__)
+#define log_struct_errno(level, error, ...) \
+ log_struct_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
+ error, __FILE__, __LINE__, __func__, __VA_ARGS__)
+#define log_struct(level, ...) log_struct_errno(level, 0, __VA_ARGS__)
/* This modifies the buffer passed! */
-#define log_dump(level, buffer) log_dump_internal(level, 0, __FILE__, __LINE__, __func__, buffer)
+#define log_dump(level, buffer) \
+ log_dump_internal(LOG_REALM_PLUS_LEVEL(LOG_REALM, level), \
+ 0, __FILE__, __LINE__, __func__, buffer)
-#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
+#define log_oom() log_oom_internal(LOG_REALM, __FILE__, __LINE__, __func__)
bool log_on_console(void) _pure_;
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index 7db87b493a..afcde4597a 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -19,7 +19,6 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <sys/param.h>
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index e8158d5584..d803df8b98 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -560,15 +560,29 @@ void dual_timestamp_serialize(FILE *f, const char *name, dual_timestamp *t) {
int dual_timestamp_deserialize(const char *value, dual_timestamp *t) {
uint64_t a, b;
+ int r, pos;
assert(value);
assert(t);
- if (sscanf(value, "%" PRIu64 "%" PRIu64, &a, &b) != 2) {
- log_debug("Failed to parse dual timestamp value \"%s\": %m", value);
+ pos = strspn(value, WHITESPACE);
+ if (value[pos] == '-')
+ return -EINVAL;
+ pos += strspn(value + pos, DIGITS);
+ pos += strspn(value + pos, WHITESPACE);
+ if (value[pos] == '-')
+ return -EINVAL;
+
+ r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
+ if (r != 2) {
+ log_debug("Failed to parse dual timestamp value \"%s\".", value);
return -EINVAL;
}
+ if (value[pos] != '\0')
+ /* trailing garbage */
+ return -EINVAL;
+
t->realtime = a;
t->monotonic = b;
diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
index 82cae2300a..7847ce0709 100644
--- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
@@ -75,6 +75,7 @@ struct sd_dhcp_lease {
uint16_t mtu; /* 0 if unset */
char *domainname;
+ char **search_domains;
char *hostname;
char *root_path;
@@ -92,6 +93,7 @@ struct sd_dhcp_lease {
int dhcp_lease_new(sd_dhcp_lease **ret);
int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata);
+int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains);
int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len);
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index 17393e2062..955c9ddabf 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -1659,7 +1659,8 @@ static int client_receive_message_udp(
if (errno == EAGAIN || errno == EINTR)
return 0;
- return log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket: %m");
+ return log_dhcp_client_errno(client, errno,
+ "Could not receive message from UDP socket: %m");
}
if ((size_t) len < sizeof(DHCPMessage)) {
log_dhcp_client(client, "Too small to be a DHCP message: ignoring");
@@ -1752,9 +1753,8 @@ static int client_receive_message_raw(
if (errno == EAGAIN || errno == EINTR)
return 0;
- log_dhcp_client(client, "Could not receive message from raw socket: %m");
-
- return -errno;
+ return log_dhcp_client_errno(client, errno,
+ "Could not receive message from raw socket: %m");
} else if ((size_t)len < sizeof(DHCPPacket))
return 0;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index 5a3bff2f76..f0ddf2dae1 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -233,6 +233,21 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
return (int) lease->static_route_size;
}
+int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
+ unsigned r;
+
+ assert_return(lease, -EINVAL);
+ assert_return(domains, -EINVAL);
+
+ r = strv_length(lease->search_domains);
+ if (r > 0) {
+ *domains = lease->search_domains;
+ return (int) r;
+ }
+
+ return -ENODATA;
+}
+
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) {
assert_return(lease, -EINVAL);
assert_return(data, -EINVAL);
@@ -284,6 +299,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
free(lease->static_route);
free(lease->client_id);
free(lease->vendor_specific);
+ strv_free(lease->search_domains);
return mfree(lease);
}
@@ -596,6 +612,11 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
r = lease_parse_u16(option, len, &lease->mtu, 68);
if (r < 0)
log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
+ if (lease->mtu < DHCP_DEFAULT_MIN_SIZE) {
+ log_debug("MTU value of %" PRIu16 " too small. Using default MTU value of %d instead.", lease->mtu, DHCP_DEFAULT_MIN_SIZE);
+ lease->mtu = DHCP_DEFAULT_MIN_SIZE;
+ }
+
break;
case SD_DHCP_OPTION_DOMAIN_NAME:
@@ -607,6 +628,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
break;
+ case SD_DHCP_OPTION_DOMAIN_SEARCH_LIST:
+ r = dhcp_lease_parse_search_domains(option, len, &lease->search_domains);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse Domain Search List, ignoring: %m");
+ break;
+
case SD_DHCP_OPTION_HOST_NAME:
r = lease_parse_domain(option, len, &lease->hostname);
if (r < 0) {
@@ -698,6 +725,96 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
return 0;
}
+/* Parses compressed domain names. */
+int dhcp_lease_parse_search_domains(const uint8_t *option, size_t len, char ***domains) {
+ _cleanup_strv_free_ char **names = NULL;
+ size_t pos = 0, cnt = 0;
+ int r;
+
+ assert(domains);
+ assert_return(option && len > 0, -ENODATA);
+
+ while (pos < len) {
+ _cleanup_free_ char *name = NULL;
+ size_t n = 0, allocated = 0;
+ size_t jump_barrier = pos, next_chunk = 0;
+ bool first = true;
+
+ for (;;) {
+ uint8_t c;
+ c = option[pos++];
+
+ if (c == 0) {
+ /* End of name */
+ break;
+ } else if (c <= 63) {
+ const char *label;
+
+ /* Literal label */
+ label = (const char*) (option + pos);
+ pos += c;
+ if (pos >= len)
+ return -EBADMSG;
+
+ if (!GREEDY_REALLOC(name, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+ return -ENOMEM;
+
+ if (first)
+ first = false;
+ else
+ name[n++] = '.';
+
+ r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX);
+ if (r < 0)
+ return r;
+
+ n += r;
+ } else if ((c & 0xc0) == 0xc0) {
+ /* Pointer */
+
+ uint8_t d;
+ uint16_t ptr;
+
+ if (pos >= len)
+ return -EBADMSG;
+
+ d = option[pos++];
+ ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
+
+ /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
+ if (ptr >= jump_barrier)
+ return -EBADMSG;
+ jump_barrier = ptr;
+
+ /* Save current location so we don't end up re-parsing what's parsed so far. */
+ if (next_chunk == 0)
+ next_chunk = pos;
+
+ pos = ptr;
+ } else
+ return -EBADMSG;
+ }
+
+ if (!GREEDY_REALLOC(name, allocated, n + 1))
+ return -ENOMEM;
+ name[n] = 0;
+
+ r = strv_extend(&names, name);
+ if (r < 0)
+ return r;
+
+ cnt++;
+
+ if (next_chunk != 0)
+ pos = next_chunk;
+ }
+
+ *domains = names;
+ names = NULL;
+
+ return cnt;
+}
+
int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const void *data, uint8_t len) {
struct sd_dhcp_raw_option *cur, *option;
@@ -753,6 +870,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
const char *string;
uint16_t mtu;
_cleanup_free_ sd_dhcp_route **routes = NULL;
+ char **search_domains = NULL;
uint32_t t1, t2, lifetime;
int r;
@@ -826,6 +944,13 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
if (r >= 0)
fprintf(f, "DOMAINNAME=%s\n", string);
+ r = sd_dhcp_lease_get_search_domains(lease, &search_domains);
+ if (r > 0) {
+ fputs("DOMAIN_SEARCH_LIST=", f);
+ fputstrv(f, search_domains, NULL, NULL);
+ fputs("\n", f);
+ }
+
r = sd_dhcp_lease_get_hostname(lease, &string);
if (r >= 0)
fprintf(f, "HOSTNAME=%s\n", string);
@@ -907,6 +1032,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
*ntp = NULL,
*mtu = NULL,
*routes = NULL,
+ *domains = NULL,
*client_id_hex = NULL,
*vendor_specific_hex = NULL,
*lifetime = NULL,
@@ -935,6 +1061,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"MTU", &mtu,
"DOMAINNAME", &lease->domainname,
"HOSTNAME", &lease->hostname,
+ "DOMAIN_SEARCH_LIST", &domains,
"ROOT_PATH", &lease->root_path,
"ROUTES", &routes,
"CLIENTID", &client_id_hex,
@@ -1040,6 +1167,18 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu);
}
+ if (domains) {
+ _cleanup_strv_free_ char **a = NULL;
+ a = strv_split(domains, " ");
+ if (!a)
+ return -ENOMEM;
+
+ if (!strv_isempty(a)) {
+ lease->search_domains = a;
+ a = NULL;
+ }
+ }
+
if (routes) {
r = deserialize_dhcp_routes(
&lease->static_route,
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
index 5ed2719136..8b341461f0 100644
--- a/src/systemd/src/shared/dns-domain.c
+++ b/src/systemd/src/shared/dns-domain.c
@@ -19,9 +19,11 @@
#include "nm-sd-adapt.h"
-#ifdef HAVE_LIBIDN
-#include <idna.h>
-#include <stringprep.h>
+#if defined(HAVE_LIBIDN2)
+# include <idn2.h>
+#elif defined(HAVE_LIBIDN)
+# include <idna.h>
+# include <stringprep.h>
#endif
#include <endian.h>
@@ -144,6 +146,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz) {
return r;
}
+#if 0 /* NM_IGNORED */
/* @label_terminal: terminal character of a label, updated to point to the terminal character of
* the previous label (always skipping one dot) or to NULL if there are no more
* labels. */
@@ -209,6 +212,7 @@ int dns_label_unescape_suffix(const char *name, const char **label_terminal, cha
return r;
}
+#endif /* NM_IGNORED */
int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
char *q;
@@ -277,6 +281,7 @@ int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
return (int) (q - dest);
}
+#if 0 /* NM_IGNORED */
int dns_label_escape_new(const char *p, size_t l, char **ret) {
_cleanup_free_ char *s = NULL;
int r;
@@ -301,8 +306,8 @@ int dns_label_escape_new(const char *p, size_t l, char **ret) {
return r;
}
-int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
#ifdef HAVE_LIBIDN
+int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
_cleanup_free_ uint32_t *input = NULL;
size_t input_size, l;
const char *p;
@@ -350,13 +355,9 @@ int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded
decoded[l] = 0;
return (int) l;
-#else
- return 0;
-#endif
}
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
-#ifdef HAVE_LIBIDN
size_t input_size, output_size;
_cleanup_free_ uint32_t *input = NULL;
_cleanup_free_ char *result = NULL;
@@ -401,10 +402,9 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
decoded[w] = 0;
return w;
-#else
- return 0;
-#endif
}
+#endif
+#endif /* NM_IGNORED */
int dns_name_concat(const char *a, const char *b, char **_ret) {
_cleanup_free_ char *ret = NULL;
@@ -1279,6 +1279,23 @@ int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
}
int dns_name_apply_idna(const char *name, char **ret) {
+ /* Return negative on error, 0 if not implemented, positive on success. */
+
+#if defined(HAVE_LIBIDN2)
+ int r;
+
+ assert(name);
+ assert(ret);
+
+ r = idn2_lookup_u8((uint8_t*) name, (uint8_t**) ret,
+ IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL);
+ if (r == IDN2_OK)
+ return 1; /* *ret has been written */
+ else if (IN_SET(r, IDN2_TOO_BIG_DOMAIN, IDN2_TOO_BIG_LABEL))
+ return -ENOSPC;
+ else
+ return -EINVAL;
+#elif defined(HAVE_LIBIDN)
_cleanup_free_ char *buf = NULL;
size_t n = 0, allocated = 0;
bool first = true;
@@ -1328,6 +1345,9 @@ int dns_name_apply_idna(const char *name, char **ret) {
buf = NULL;
return (int) n;
+#else
+ return 0;
+#endif
}
int dns_name_is_valid_or_address(const char *name) {
diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h
index 03f160369c..fca025def0 100644
--- a/src/systemd/src/shared/dns-domain.h
+++ b/src/systemd/src/shared/dns-domain.h
@@ -51,8 +51,10 @@ static inline int dns_name_parent(const char **name) {
return dns_label_unescape(name, NULL, DNS_LABEL_MAX);
}
+#if defined(HAVE_LIBIDN)
int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
+#endif
int dns_name_concat(const char *a, const char *b, char **ret);
diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h
index ffe7f836de..f731fdcbd4 100644
--- a/src/systemd/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/src/systemd/sd-dhcp-client.h
@@ -76,6 +76,7 @@ enum {
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
+ SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119,
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
SD_DHCP_OPTION_PRIVATE_BASE = 224,
SD_DHCP_OPTION_PRIVATE_LAST = 254,
diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h
index 2f565ca825..7ab99cccd1 100644
--- a/src/systemd/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp-lease.h
@@ -49,6 +49,7 @@ int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
+int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);
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, sd_dhcp_route ***routes);