summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-09-16 16:53:25 +0200
committerThomas Haller <thaller@redhat.com>2015-09-16 16:54:03 +0200
commitc05557971c09782316ee7e39ae4e7a7675d338f1 (patch)
tree25595e64bb7f900b17766270b52e7696d4e615c7 /src
parent08916936bce4c8ac36156c040999add99175b455 (diff)
parente82f430eae841032c7961d2eca694435425e4d51 (diff)
downloadNetworkManager-c05557971c09782316ee7e39ae4e7a7675d338f1.tar.gz
systemd: merge branch 'systemd-integration' into master
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am99
-rw-r--r--src/dhcp-manager/nm-dhcp-systemd.c4
-rw-r--r--src/systemd/src/basic/hostname-util.c30
-rw-r--r--src/systemd/src/basic/hostname-util.h5
-rw-r--r--src/systemd/src/basic/macro.h3
-rw-r--r--src/systemd/src/basic/refcnt.h4
-rw-r--r--src/systemd/src/basic/strv.c30
-rw-r--r--src/systemd/src/basic/strv.h3
-rw-r--r--src/systemd/src/basic/time-util.c85
-rw-r--r--src/systemd/src/basic/time-util.h6
-rw-r--r--src/systemd/src/basic/util.c364
-rw-r--r--src/systemd/src/basic/util.h55
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-identifier.c2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-internal.h4
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-lease-internal.h50
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-option.c12
-rw-r--r--src/systemd/src/libsystemd-network/dhcp-protocol.h2
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-internal.h7
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-lease-internal.h24
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-network.c6
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-option.c99
-rw-r--r--src/systemd/src/libsystemd-network/dhcp6-protocol.h8
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.c19
-rw-r--r--src/systemd/src/libsystemd-network/network-internal.h6
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-client.c78
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp-lease.c787
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-client.c141
-rw-r--r--src/systemd/src/libsystemd-network/sd-dhcp6-lease.c223
-rw-r--r--src/systemd/src/libsystemd-network/sd-ipv4ll.c45
-rw-r--r--src/systemd/src/shared/dns-domain.c40
-rw-r--r--src/systemd/src/shared/dns-domain.h10
-rw-r--r--src/systemd/src/systemd/sd-dhcp-lease.h12
-rw-r--r--src/systemd/src/systemd/sd-dhcp6-lease.h8
-rw-r--r--src/systemd/src/systemd/sd-icmp6-nd.h81
34 files changed, 1604 insertions, 748 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 9101a3af6e..220331cff5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -66,70 +66,71 @@ SYSTEMD_NM_CFLAGS = \
-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON
libsystemd_nm_la_SOURCES = \
- systemd/src/libsystemd/sd-id128/sd-id128.c \
- systemd/src/libsystemd-network/dhcp-identifier.c \
- systemd/src/libsystemd-network/dhcp-identifier.h \
- systemd/src/libsystemd-network/dhcp-network.c \
- systemd/src/libsystemd-network/dhcp-packet.c \
- systemd/src/libsystemd-network/dhcp-internal.h \
- systemd/src/libsystemd-network/dhcp6-network.c \
- systemd/src/libsystemd-network/dhcp6-lease-internal.h \
- systemd/src/libsystemd-network/dhcp6-option.c \
- systemd/src/libsystemd-network/network-internal.c \
- systemd/src/libsystemd-network/sd-dhcp-lease.c \
- systemd/src/libsystemd-network/sd-dhcp-client.c \
- systemd/src/libsystemd-network/dhcp-option.c \
- systemd/src/libsystemd-network/network-internal.h \
- systemd/src/libsystemd-network/sd-dhcp6-lease.c \
- systemd/src/libsystemd-network/dhcp-protocol.h \
- systemd/src/libsystemd-network/dhcp6-internal.h \
- systemd/src/libsystemd-network/dhcp6-protocol.h \
- systemd/src/libsystemd-network/dhcp-lease-internal.h \
- systemd/src/libsystemd-network/sd-dhcp6-client.c \
- systemd/src/libsystemd-network/ipv4ll-internal.h \
- systemd/src/libsystemd-network/sd-ipv4ll.c \
- systemd/src/libsystemd-network/ipv4ll-packet.c \
- systemd/src/libsystemd-network/ipv4ll-network.c \
+ systemd/nm-sd-adapt.c \
+ systemd/nm-sd-adapt.h \
systemd/src/basic/async.h \
- systemd/src/basic/time-util.h \
- systemd/src/basic/siphash24.h \
- systemd/src/basic/time-util.c \
- systemd/src/basic/socket-util.h \
- systemd/src/basic/sparse-endian.h \
- systemd/src/basic/macro.h \
- systemd/src/basic/refcnt.h \
- systemd/src/basic/util.c \
+ systemd/src/basic/fileio.c \
+ systemd/src/basic/fileio.h \
+ systemd/src/basic/hostname-util.c \
+ systemd/src/basic/hostname-util.h \
systemd/src/basic/in-addr-util.c \
- systemd/src/basic/siphash24.c \
- systemd/src/basic/util.h \
systemd/src/basic/in-addr-util.h \
systemd/src/basic/list.h \
systemd/src/basic/log.h \
- systemd/src/basic/fileio.h \
- systemd/src/basic/fileio.c \
+ systemd/src/basic/macro.h \
systemd/src/basic/path-util.c \
systemd/src/basic/path-util.h \
- systemd/src/basic/strv.h \
+ systemd/src/basic/random-util.c \
+ systemd/src/basic/random-util.h \
+ systemd/src/basic/refcnt.h \
+ systemd/src/basic/siphash24.c \
+ systemd/src/basic/siphash24.h \
+ systemd/src/basic/socket-util.h \
+ systemd/src/basic/sparse-endian.h \
systemd/src/basic/strv.c \
+ systemd/src/basic/strv.h \
+ systemd/src/basic/time-util.c \
+ systemd/src/basic/time-util.h \
systemd/src/basic/unaligned.h \
- systemd/src/basic/utf8.h \
systemd/src/basic/utf8.c \
- systemd/src/basic/hostname-util.h \
- systemd/src/basic/hostname-util.c \
- systemd/src/basic/random-util.h \
- systemd/src/basic/random-util.c \
+ systemd/src/basic/utf8.h \
+ systemd/src/basic/util.c \
+ systemd/src/basic/util.h \
+ systemd/src/libsystemd-network/dhcp-identifier.c \
+ systemd/src/libsystemd-network/dhcp-identifier.h \
+ systemd/src/libsystemd-network/dhcp-internal.h \
+ systemd/src/libsystemd-network/dhcp-lease-internal.h \
+ systemd/src/libsystemd-network/dhcp-network.c \
+ systemd/src/libsystemd-network/dhcp-option.c \
+ systemd/src/libsystemd-network/dhcp-packet.c \
+ systemd/src/libsystemd-network/dhcp-protocol.h \
+ systemd/src/libsystemd-network/dhcp6-internal.h \
+ systemd/src/libsystemd-network/dhcp6-lease-internal.h \
+ systemd/src/libsystemd-network/dhcp6-network.c \
+ systemd/src/libsystemd-network/dhcp6-option.c \
+ systemd/src/libsystemd-network/dhcp6-protocol.h \
+ systemd/src/libsystemd-network/ipv4ll-internal.h \
+ systemd/src/libsystemd-network/ipv4ll-network.c \
+ systemd/src/libsystemd-network/ipv4ll-packet.c \
+ systemd/src/libsystemd-network/network-internal.c \
+ systemd/src/libsystemd-network/network-internal.h \
+ systemd/src/libsystemd-network/sd-dhcp-client.c \
+ systemd/src/libsystemd-network/sd-dhcp-lease.c \
+ systemd/src/libsystemd-network/sd-dhcp6-client.c \
+ systemd/src/libsystemd-network/sd-dhcp6-lease.c \
+ systemd/src/libsystemd-network/sd-ipv4ll.c \
+ systemd/src/libsystemd/sd-id128/sd-id128.c \
systemd/src/shared/dns-domain.c \
systemd/src/shared/dns-domain.h \
- systemd/src/systemd/sd-dhcp-lease.h \
+ systemd/src/systemd/_sd-common.h \
systemd/src/systemd/sd-dhcp-client.h \
- systemd/src/systemd/sd-id128.h \
- systemd/src/systemd/sd-dhcp6-lease.h \
+ systemd/src/systemd/sd-dhcp-lease.h \
systemd/src/systemd/sd-dhcp6-client.h \
+ systemd/src/systemd/sd-dhcp6-lease.h \
systemd/src/systemd/sd-event.h \
- systemd/src/systemd/_sd-common.h \
- systemd/src/systemd/sd-ipv4ll.h \
- systemd/nm-sd-adapt.h \
- systemd/nm-sd-adapt.c
+ systemd/src/systemd/sd-icmp6-nd.h \
+ systemd/src/systemd/sd-id128.h \
+ systemd/src/systemd/sd-ipv4ll.h
libsystemd_nm_la_CPPFLAGS = \
-I$(top_srcdir)/include \
diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c
index 7f16946d8f..3786f3b279 100644
--- a/src/dhcp-manager/nm-dhcp-systemd.c
+++ b/src/dhcp-manager/nm-dhcp-systemd.c
@@ -222,7 +222,7 @@ lease_to_ip4_config (const char *iface,
guint16 mtu;
int r, num;
guint64 end_time;
- const uint8_t *data;
+ const void *data;
gsize data_len;
gboolean metered = FALSE;
@@ -607,7 +607,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
client_id + 1,
client_id_len - 1);
} else if (lease) {
- r = sd_dhcp_lease_get_client_id (lease, &client_id, &client_id_len);
+ r = sd_dhcp_lease_get_client_id (lease, (const void **) &client_id, &client_id_len);
if (r == 0 && client_id_len) {
sd_dhcp_client_set_client_id (priv->client4,
client_id[0],
diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c
index 7e2fa7c609..b8cd79e52d 100644
--- a/src/systemd/src/basic/hostname-util.c
+++ b/src/systemd/src/basic/hostname-util.c
@@ -64,16 +64,19 @@ static bool hostname_valid_char(char c) {
}
/**
- * Check if s looks like a valid host name or fqdn. This does not do
+ * Check if s looks like a valid host name or FQDN. This does not do
* full DNS validation, but only checks if the name is composed of
* allowed characters and the length is not above the maximum allowed
* by Linux (c.f. dns_name_is_valid()). Trailing dot is allowed if
- * relax is true and at least two components are present in the name.
+ * allow_trailing_dot is true and at least two components are present
+ * in the name. Note that due to the restricted charset and length
+ * this call is substantially more conservative than
+ * dns_domain_is_valid().
*/
-bool hostname_is_valid(const char *s, bool relax) {
+bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
+ unsigned n_dots = 0;
const char *p;
bool dot;
- unsigned dots = 0;
if (isempty(s))
return false;
@@ -89,7 +92,7 @@ bool hostname_is_valid(const char *s, bool relax) {
return false;
dot = true;
- dots ++;
+ n_dots ++;
} else {
if (!hostname_valid_char(*p))
return false;
@@ -98,10 +101,12 @@ bool hostname_is_valid(const char *s, bool relax) {
}
}
- if (dot && (dots < 2 || !relax))
+ if (dot && (n_dots < 2 || !allow_trailing_dot))
return false;
- if (p-s > HOST_NAME_MAX)
+ if (p-s > HOST_NAME_MAX) /* Note that HOST_NAME_MAX is 64 on
+ * Linux, but DNS allows domain names
+ * up to 255 characters */
return false;
return true;
@@ -154,6 +159,17 @@ bool is_localhost(const char *hostname) {
}
#if 0 /* NM_IGNORED */
+bool is_gateway_hostname(const char *hostname) {
+ assert(hostname);
+
+ /* This tries to identify the valid syntaxes for the our
+ * synthetic "gateway" host. */
+
+ return
+ strcaseeq(hostname, "gateway") ||
+ strcaseeq(hostname, "gateway.");
+}
+
int sethostname_idempotent(const char *s) {
char buf[HOST_NAME_MAX + 1] = {};
diff --git a/src/systemd/src/basic/hostname-util.h b/src/systemd/src/basic/hostname-util.h
index fd768ee3c0..a2e6920095 100644
--- a/src/systemd/src/basic/hostname-util.h
+++ b/src/systemd/src/basic/hostname-util.h
@@ -31,10 +31,13 @@ bool hostname_is_set(void);
char* gethostname_malloc(void);
-bool hostname_is_valid(const char *s, bool relax) _pure_;
+bool hostname_is_valid(const char *s, bool allow_trailing_dot) _pure_;
char* hostname_cleanup(char *s);
+#define machine_name_is_valid(s) hostname_is_valid(s, false)
+
bool is_localhost(const char *hostname);
+bool is_gateway_hostname(const char *hostname);
int sethostname_idempotent(const char *s);
diff --git a/src/systemd/src/basic/macro.h b/src/systemd/src/basic/macro.h
index b1cef217ab..80c64904e2 100644
--- a/src/systemd/src/basic/macro.h
+++ b/src/systemd/src/basic/macro.h
@@ -300,6 +300,9 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1))
#define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1))
+#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p))
+#define PID_TO_PTR(p) ((void*) ((uintptr_t) p))
+
#define memzero(x,l) (memset((x), 0, (l)))
#define zero(x) (memzero(&(x), sizeof(x)))
diff --git a/src/systemd/src/basic/refcnt.h b/src/systemd/src/basic/refcnt.h
index e6e9a6bd6e..f7a26192ce 100644
--- a/src/systemd/src/basic/refcnt.h
+++ b/src/systemd/src/basic/refcnt.h
@@ -23,7 +23,9 @@
#include "nm-sd-adapt.h"
-/* A type-safe atomic refcounter */
+/* A type-safe atomic refcounter.
+ *
+ * DO NOT USE THIS UNLESS YOU ACTUALLY CARE ABOUT THREAD SAFETY! */
typedef struct {
volatile unsigned _value;
diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c
index df44f61907..de0f371613 100644
--- a/src/systemd/src/basic/strv.c
+++ b/src/systemd/src/basic/strv.c
@@ -272,16 +272,14 @@ char **strv_split_newlines(const char *s) {
if (n <= 0)
return l;
- if (isempty(l[n-1])) {
- free(l[n-1]);
- l[n-1] = NULL;
- }
+ if (isempty(l[n - 1]))
+ l[n - 1] = mfree(l[n - 1]);
return l;
}
#if 0 /* NM_IGNORED */
-int strv_split_quoted(char ***t, const char *s, UnquoteFlags flags) {
+int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) {
size_t n = 0, allocated = 0;
_cleanup_strv_free_ char **l = NULL;
int r;
@@ -292,7 +290,7 @@ int strv_split_quoted(char ***t, const char *s, UnquoteFlags flags) {
for (;;) {
_cleanup_free_ char *word = NULL;
- r = unquote_first_word(&s, &word, flags);
+ r = extract_first_word(&s, &word, separators, flags);
if (r < 0)
return r;
if (r == 0)
@@ -697,6 +695,26 @@ char **strv_reverse(char **l) {
return l;
}
+char **strv_shell_escape(char **l, const char *bad) {
+ char **s;
+
+ /* Escapes every character in every string in l that is in bad,
+ * edits in-place, does not roll-back on error. */
+
+ STRV_FOREACH(s, l) {
+ char *v;
+
+ v = shell_escape(*s, bad);
+ if (!v)
+ return NULL;
+
+ free(*s);
+ *s = v;
+ }
+
+ return l;
+}
+
bool strv_fnmatch(char* const* patterns, const char *s, int flags) {
char* const* p;
diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h
index b583080739..df3855d9fa 100644
--- a/src/systemd/src/basic/strv.h
+++ b/src/systemd/src/basic/strv.h
@@ -75,7 +75,7 @@ static inline bool strv_isempty(char * const *l) {
char **strv_split(const char *s, const char *separator);
char **strv_split_newlines(const char *s);
-int strv_split_quoted(char ***t, const char *s, UnquoteFlags flags);
+int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
char *strv_join(char **l, const char *separator);
char *strv_join_quoted(char **l);
@@ -147,6 +147,7 @@ void strv_print(char **l);
}))
char **strv_reverse(char **l);
+char **strv_shell_escape(char **l, const char *bad);
bool strv_fnmatch(char* const* patterns, const char *s, int flags);
diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c
index 66f91825bc..5fb666a0c3 100644
--- a/src/systemd/src/basic/time-util.c
+++ b/src/systemd/src/basic/time-util.c
@@ -28,9 +28,8 @@
#include "util.h"
#include "time-util.h"
-#if 0 /* NM_IGNORED */
+#include "path-util.h"
#include "strv.h"
-#endif /* NM_IGNORED */
usec_t now(clockid_t clock_id) {
struct timespec ts;
@@ -40,6 +39,14 @@ usec_t now(clockid_t clock_id) {
return timespec_load(&ts);
}
+nsec_t now_nsec(clockid_t clock_id) {
+ struct timespec ts;
+
+ assert_se(clock_gettime(clock_id, &ts) == 0);
+
+ return timespec_load_nsec(&ts);
+}
+
dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
assert(ts);
@@ -92,6 +99,32 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
return ts;
}
+dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u) {
+ int64_t delta;
+
+ if (u == USEC_INFINITY) {
+ ts->realtime = ts->monotonic = USEC_INFINITY;
+ return ts;
+ }
+ ts->realtime = now(CLOCK_REALTIME);
+ ts->monotonic = now(CLOCK_MONOTONIC);
+
+ delta = (int64_t) now(clock_boottime_or_monotonic()) - (int64_t) u;
+
+ if ((int64_t) ts->realtime > delta)
+ ts->realtime -= delta;
+ else
+ ts->realtime = 0;
+
+ if ((int64_t) ts->monotonic > delta)
+ ts->monotonic -= delta;
+ else
+ ts->monotonic = 0;
+
+ return ts;
+}
+
+
usec_t timespec_load(const struct timespec *ts) {
assert(ts);
@@ -107,6 +140,18 @@ usec_t timespec_load(const struct timespec *ts) {
(usec_t) ts->tv_nsec / NSEC_PER_USEC;
}
+nsec_t timespec_load_nsec(const struct timespec *ts) {
+ assert(ts);
+
+ if (ts->tv_sec == (time_t) -1 &&
+ ts->tv_nsec == (long) -1)
+ return NSEC_INFINITY;
+
+ return
+ (nsec_t) ts->tv_sec * NSEC_PER_SEC +
+ (nsec_t) ts->tv_nsec;
+}
+
struct timespec *timespec_store(struct timespec *ts, usec_t u) {
assert(ts);
@@ -946,13 +991,17 @@ int get_timezones(char ***ret) {
return 0;
}
+#endif /* NM_IGNORED */
bool timezone_is_valid(const char *name) {
bool slash = false;
const char *p, *t;
struct stat st;
- if (!name || *name == 0 || *name == '/')
+ if (isempty(name))
+ return false;
+
+ if (name[0] == '/')
return false;
for (p = name; *p; p++) {
@@ -984,7 +1033,6 @@ bool timezone_is_valid(const char *name) {
return true;
}
-#endif /* NM_IGNORED */
clockid_t clock_boottime_or_monotonic(void) {
static clockid_t clock = -1;
@@ -1003,3 +1051,32 @@ clockid_t clock_boottime_or_monotonic(void) {
return clock;
}
+
+#if 0 /* NM_IGNORED */
+int get_timezone(char **tz) {
+ _cleanup_free_ char *t = NULL;
+ const char *e;
+ char *z;
+ int r;
+
+ r = readlink_malloc("/etc/localtime", &t);
+ if (r < 0)
+ return r; /* returns EINVAL if not a symlink */
+
+ e = path_startswith(t, "/usr/share/zoneinfo/");
+ if (!e)
+ e = path_startswith(t, "../usr/share/zoneinfo/");
+ if (!e)
+ return -EINVAL;
+
+ if (!timezone_is_valid(e))
+ return -EINVAL;
+
+ z = strdup(e);
+ if (!z)
+ return -ENOMEM;
+
+ *tz = z;
+ return 0;
+}
+#endif /* NM_IGNORED */
diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h
index 480c39d902..463d509b4a 100644
--- a/src/systemd/src/basic/time-util.h
+++ b/src/systemd/src/basic/time-util.h
@@ -72,10 +72,12 @@ typedef struct dual_timestamp {
#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL })
usec_t now(clockid_t clock);
+nsec_t now_nsec(clockid_t clock);
dual_timestamp* dual_timestamp_get(dual_timestamp *ts);
dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u);
dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
+dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u);
static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
@@ -88,6 +90,8 @@ struct timespec *timespec_store(struct timespec *ts, usec_t u);
usec_t timeval_load(const struct timeval *tv) _pure_;
struct timeval *timeval_store(struct timeval *tv, usec_t u);
+nsec_t timespec_load_nsec(const struct timespec *ts) _pure_;
+
char *format_timestamp(char *buf, size_t l, usec_t t);
char *format_timestamp_utc(char *buf, size_t l, usec_t t);
char *format_timestamp_us(char *buf, size_t l, usec_t t);
@@ -111,3 +115,5 @@ bool timezone_is_valid(const char *name);
clockid_t clock_boottime_or_monotonic(void);
#define xstrftime(buf, fmt, tm) assert_se(strftime(buf, ELEMENTSOF(buf), fmt, tm) > 0)
+
+int get_timezone(char **timezone);
diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c
index 4293268857..3b41adad8d 100644
--- a/src/systemd/src/basic/util.c
+++ b/src/systemd/src/basic/util.c
@@ -339,6 +339,33 @@ void close_many(const int fds[], unsigned n_fd) {
}
#endif /* NM_IGNORED */
+int fclose_nointr(FILE *f) {
+ assert(f);
+
+ /* Same as close_nointr(), but for fclose() */
+
+ if (fclose(f) == 0)
+ return 0;
+
+ if (errno == EINTR)
+ return 0;
+
+ return -errno;
+}
+
+FILE* safe_fclose(FILE *f) {
+
+ /* Same as safe_close(), but for fclose() */
+
+ if (f) {
+ PROTECT_ERRNO;
+
+ assert_se(fclose_nointr(f) != EBADF);
+ }
+
+ return NULL;
+}
+
int unlink_noerrno(const char *path) {
PROTECT_ERRNO;
int r;
@@ -386,6 +413,19 @@ int parse_pid(const char *s, pid_t* ret_pid) {
return 0;
}
+bool uid_is_valid(uid_t uid) {
+
+ /* Some libc APIs use UID_INVALID as special placeholder */
+ if (uid == (uid_t) 0xFFFFFFFF)
+ return false;
+
+ /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
+ if (uid == (uid_t) 0xFFFF)
+ return false;
+
+ return true;
+}
+
int parse_uid(const char *s, uid_t* ret_uid) {
unsigned long ul = 0;
uid_t uid;
@@ -402,13 +442,11 @@ int parse_uid(const char *s, uid_t* ret_uid) {
if ((unsigned long) uid != ul)
return -ERANGE;
- /* Some libc APIs use UID_INVALID as special placeholder */
- if (uid == (uid_t) 0xFFFFFFFF)
- return -ENXIO;
-
- /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */
- if (uid == (uid_t) 0xFFFF)
- return -ENXIO;
+ if (!uid_is_valid(uid))
+ return -ENXIO; /* we return ENXIO instead of EINVAL
+ * here, to make it easy to distuingish
+ * invalid numeric uids invalid
+ * strings. */
if (ret_uid)
*ret_uid = uid;
@@ -477,6 +515,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
*ret = (uint8_t) l;
return 0;
}
+#endif /* NM_IGNORED */
int safe_atou16(const char *s, uint16_t *ret) {
char *x = NULL;
@@ -498,6 +537,7 @@ int safe_atou16(const char *s, uint16_t *ret) {
return 0;
}
+#if 0 /* NM_IGNORED */
int safe_atoi16(const char *s, int16_t *ret) {
char *x = NULL;
long l;
@@ -2201,7 +2241,7 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
return 0;
}
-int parse_size(const char *t, off_t base, off_t *size) {
+int parse_size(const char *t, uint64_t base, uint64_t *size) {
/* Soo, sometimes we want to parse IEC binary suffixes, and
* sometimes SI decimal suffixes. This function can parse
@@ -2229,8 +2269,8 @@ int parse_size(const char *t, off_t base, off_t *size) {
{ "G", 1024ULL*1024ULL*1024ULL },
{ "M", 1024ULL*1024ULL },
{ "K", 1024ULL },
- { "B", 1 },
- { "", 1 },
+ { "B", 1ULL },
+ { "", 1ULL },
};
static const struct table si[] = {
@@ -2240,8 +2280,8 @@ int parse_size(const char *t, off_t base, off_t *size) {
{ "G", 1000ULL*1000ULL*1000ULL },
{ "M", 1000ULL*1000ULL },
{ "K", 1000ULL },
- { "B", 1 },
- { "", 1 },
+ { "B", 1ULL },
+ { "", 1ULL },
};
const struct table *table;
@@ -2263,33 +2303,32 @@ int parse_size(const char *t, off_t base, off_t *size) {
p = t;
do {
- long long l;
- unsigned long long l2;
+ unsigned long long l, tmp;
double frac = 0;
char *e;
unsigned i;
- errno = 0;
- l = strtoll(p, &e, 10);
+ p += strspn(p, WHITESPACE);
+ if (*p == '-')
+ return -ERANGE;
+ errno = 0;
+ l = strtoull(p, &e, 10);
if (errno > 0)
return -errno;
-
- if (l < 0)
- return -ERANGE;
-
if (e == p)
return -EINVAL;
if (*e == '.') {
e++;
+
+ /* strtoull() itself would accept space/+/- */
if (*e >= '0' && *e <= '9') {
+ unsigned long long l2;
char *e2;
- /* strotoull itself would accept space/+/- */
l2 = strtoull(e, &e2, 10);
-
- if (errno == ERANGE)
+ if (errno > 0)
return -errno;
/* Ignore failure. E.g. 10.M is valid */
@@ -2302,27 +2341,27 @@ int parse_size(const char *t, off_t base, off_t *size) {
e += strspn(e, WHITESPACE);
for (i = start_pos; i < n_entries; i++)
- if (startswith(e, table[i].suffix)) {
- unsigned long long tmp;
- if ((unsigned long long) l + (frac > 0) > ULLONG_MAX / table[i].factor)
- return -ERANGE;
- tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
- if (tmp > ULLONG_MAX - r)
- return -ERANGE;
-
- r += tmp;
- if ((unsigned long long) (off_t) r != r)
- return -ERANGE;
-
- p = e + strlen(table[i].suffix);
-
- start_pos = i + 1;
+ if (startswith(e, table[i].suffix))
break;
- }
if (i >= n_entries)
return -EINVAL;
+ if (l + (frac > 0) > ULLONG_MAX / table[i].factor)
+ return -ERANGE;
+
+ tmp = l * table[i].factor + (unsigned long long) (frac * table[i].factor);
+ if (tmp > ULLONG_MAX - r)
+ return -ERANGE;
+
+ r += tmp;
+ if ((unsigned long long) (uint64_t) r != r)
+ return -ERANGE;
+
+ p = e + strlen(table[i].suffix);
+
+ start_pos = i + 1;
+
} while (*p);
*size = r;
@@ -3033,21 +3072,6 @@ char* strshorten(char *s, size_t l) {
}
#if 0 /* NM_IGNORED */
-bool machine_name_is_valid(const char *s) {
-
- if (!hostname_is_valid(s, false))
- return false;
-
- /* Machine names should be useful hostnames, but also be
- * useful in unit names, hence we enforce a stricter length
- * limitation. */
-
- if (strlen(s) > 64)
- return false;
-
- return true;
-}
-
int pipe_eof(int fd) {
struct pollfd pollfd = {
.fd = fd,
@@ -3793,38 +3817,38 @@ int prot_from_flags(int flags) {
}
}
-char *format_bytes(char *buf, size_t l, off_t t) {
+char *format_bytes(char *buf, size_t l, uint64_t t) {
unsigned i;
static const struct {
const char *suffix;
- off_t factor;
+ uint64_t factor;
} table[] = {
- { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
- { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
- { "G", 1024ULL*1024ULL*1024ULL },
- { "M", 1024ULL*1024ULL },
- { "K", 1024ULL },
+ { "E", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "P", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "T", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "G", UINT64_C(1024)*UINT64_C(1024)*UINT64_C(1024) },
+ { "M", UINT64_C(1024)*UINT64_C(1024) },
+ { "K", UINT64_C(1024) },
};
- if (t == (off_t) -1)
+ if (t == (uint64_t) -1)
return NULL;
for (i = 0; i < ELEMENTSOF(table); i++) {
if (t >= table[i].factor) {
snprintf(buf, l,
- "%llu.%llu%s",
- (unsigned long long) (t / table[i].factor),
- (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
+ "%" PRIu64 ".%" PRIu64 "%s",
+ t / table[i].factor,
+ ((t*UINT64_C(10)) / table[i].factor) % UINT64_C(10),
table[i].suffix);
goto finish;
}
}
- snprintf(buf, l, "%lluB", (unsigned long long) t);
+ snprintf(buf, l, "%" PRIu64 "B", t);
finish:
buf[l-1] = 0;
@@ -4325,7 +4349,7 @@ bool is_locale_utf8(void) {
/* Check result, but ignore the result if C was set
* explicitly. */
cached_answer =
- streq(set, "C") &&
+ STR_IN_SET(set, "C", "POSIX") &&
!getenv("LC_ALL") &&
!getenv("LC_CTYPE") &&
!getenv("LANG");
@@ -4752,7 +4776,6 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
return q;
}
-#if 0 /* NM_IGNORED */
void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
size_t prev;
uint8_t *q;
@@ -4772,6 +4795,7 @@ void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
return q;
}
+#if 0 /* NM_IGNORED */
bool id128_is_valid(const char *s) {
size_t i, l;
@@ -4860,7 +4884,7 @@ int shall_restore_state(void) {
int proc_cmdline(char **ret) {
assert(ret);
- if (detect_container(NULL) > 0)
+ if (detect_container() > 0)
return get_process_cmdline(1, 0, false, ret);
else
return read_one_line_file("/proc/cmdline", ret);
@@ -4882,7 +4906,7 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
_cleanup_free_ char *word = NULL;
char *value = NULL;
- r = unquote_first_word(&p, &word, UNQUOTE_RELAX);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
if (r < 0)
return r;
if (r == 0)
@@ -4922,7 +4946,7 @@ int get_proc_cmdline_key(const char *key, char **value) {
_cleanup_free_ char *word = NULL;
const char *e;
- r = unquote_first_word(&p, &word, UNQUOTE_RELAX);
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_RELAX);
if (r < 0)
return r;
if (r == 0)
@@ -4967,6 +4991,9 @@ int container_get_leader(const char *machine, pid_t *pid) {
assert(machine);
assert(pid);
+ if (!machine_name_is_valid(machine))
+ return -EINVAL;
+
p = strjoina("/run/systemd/machines/", machine);
r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
if (r == -ENOENT)
@@ -4989,8 +5016,8 @@ int container_get_leader(const char *machine, pid_t *pid) {
return 0;
}
-int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd) {
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1;
+int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
+ _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
int rfd = -1;
assert(pid >= 0);
@@ -5022,6 +5049,15 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
return -errno;
}
+ if (userns_fd) {
+ const char *userns;
+
+ userns = procfs_file_alloca(pid, "ns/user");
+ usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
+ if (usernsfd < 0 && errno != ENOENT)
+ return -errno;
+ }
+
if (root_fd) {
const char *root;
@@ -5040,15 +5076,33 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
if (netns_fd)
*netns_fd = netnsfd;
+ if (userns_fd)
+ *userns_fd = usernsfd;
+
if (root_fd)
*root_fd = rfd;
- pidnsfd = mntnsfd = netnsfd = -1;
+ pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
return 0;
}
-int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
+int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
+ if (userns_fd >= 0) {
+ /* Can't setns to your own userns, since then you could
+ * escalate from non-root to root in your own namespace, so
+ * check if namespaces equal before attempting to enter. */
+ _cleanup_free_ char *userns_fd_path = NULL;
+ int r;
+ if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
+ return -ENOMEM;
+
+ r = files_same(userns_fd_path, "/proc/self/ns/user");
+ if (r < 0)
+ return r;
+ if (r)
+ userns_fd = -1;
+ }
if (pidns_fd >= 0)
if (setns(pidns_fd, CLONE_NEWPID) < 0)
@@ -5062,6 +5116,10 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd) {
if (setns(netns_fd, CLONE_NEWNET) < 0)
return -errno;
+ if (userns_fd >= 0)
+ if (setns(userns_fd, CLONE_NEWUSER) < 0)
+ return -errno;
+
if (root_fd >= 0) {
if (fchdir(root_fd) < 0)
return -errno;
@@ -5741,7 +5799,7 @@ int is_device_node(const char *path) {
return !!(S_ISBLK(info.st_mode) || S_ISCHR(info.st_mode));
}
-int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) {
+int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
_cleanup_free_ char *s = NULL;
size_t allocated = 0, sz = 0;
int r;
@@ -5754,13 +5812,19 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) {
SINGLE_QUOTE_ESCAPE,
DOUBLE_QUOTE,
DOUBLE_QUOTE_ESCAPE,
- SPACE,
+ SEPARATOR,
} state = START;
assert(p);
- assert(*p);
assert(ret);
+ if (!separators)
+ separators = WHITESPACE;
+
+ /* Bail early if called after last value or with no input */
+ if (!*p)
+ goto finish_force_terminate;
+
/* Parses the first word of a string, and returns it in
* *ret. Removes all quotes in the process. When parsing fails
* (because of an uneven number of quotes or similar), leaves
@@ -5772,32 +5836,45 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) {
switch (state) {
case START:
+ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS)
+ if (!GREEDY_REALLOC(s, allocated, sz+1))
+ return -ENOMEM;
+
if (c == 0)
- goto finish;
- else if (strchr(WHITESPACE, c))
+ goto finish_force_terminate;
+ else if (strchr(separators, c)) {
+ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
+ (*p) ++;
+ goto finish_force_next;
+ }
break;
+ }
+
+ /* We found a non-blank character, so we will always
+ * want to return a string (even if it is empty),
+ * allocate it here. */
+ if (!GREEDY_REALLOC(s, allocated, sz+1))
+ return -ENOMEM;
state = VALUE;
/* fallthrough */
case VALUE:
if (c == 0)
- goto finish;
- else if (c == '\'') {
- if (!GREEDY_REALLOC(s, allocated, sz+1))
- return -ENOMEM;
-
+ goto finish_force_terminate;
+ else if (c == '\'' && (flags & EXTRACT_QUOTES))
state = SINGLE_QUOTE;
- } else if (c == '\\')
+ else if (c == '\\')
state = VALUE_ESCAPE;
- else if (c == '\"') {
- if (!GREEDY_REALLOC(s, allocated, sz+1))
- return -ENOMEM;
-
+ else if (c == '\"' && (flags & EXTRACT_QUOTES))
state = DOUBLE_QUOTE;
- } else if (strchr(WHITESPACE, c))
- state = SPACE;
- else {
+ else if (strchr(separators, c)) {
+ if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) {
+ (*p) ++;
+ goto finish_force_next;
+ }
+ state = SEPARATOR;
+ } else {
if (!GREEDY_REALLOC(s, allocated, sz+2))
return -ENOMEM;
@@ -5808,8 +5885,8 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) {
case SINGLE_QUOTE:
if (c == 0) {
- if (flags & UNQUOTE_RELAX)
- goto finish;
+ if (flags & EXTRACT_RELAX)
+ goto finish_force_terminate;
return -EINVAL;
} else if (c == '\'')
state = VALUE;
@@ -5847,29 +5924,29 @@ int unquote_first_word(const char **p, char **ret, UnquoteFlags flags) {
return -ENOMEM;
if (c == 0) {
- if ((flags & UNQUOTE_CUNESCAPE_RELAX) &&
- (state == VALUE_ESCAPE || flags & UNQUOTE_RELAX)) {
+ if ((flags & EXTRACT_CUNESCAPE_RELAX) &&
+ (state == VALUE_ESCAPE || flags & EXTRACT_RELAX)) {
/* If we find an unquoted trailing backslash and we're in
- * UNQUOTE_CUNESCAPE_RELAX mode, keep it verbatim in the
+ * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the
* output.
*
- * Unbalanced quotes will only be allowed in UNQUOTE_RELAX
- * mode, UNQUOTE_CUNESCAP_RELAX mode does not allow them.
+ * Unbalanced quotes will only be allowed in EXTRACT_RELAX
+ * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them.
*/
s[sz++] = '\\';
- goto finish;
+ goto finish_force_terminate;
}
- if (flags & UNQUOTE_RELAX)
- goto finish;
+ if (flags & EXTRACT_RELAX)
+ goto finish_force_terminate;
return -EINVAL;
}
- if (flags & UNQUOTE_CUNESCAPE) {
+ if (flags & EXTRACT_CUNESCAPE) {
uint32_t u;
r = cunescape_one(*p, (size_t) -1, &c, &u);
if (r < 0) {
- if (flags & UNQUOTE_CUNESCAPE_RELAX) {
+ if (flags & EXTRACT_CUNESCAPE_RELAX) {
s[sz++] = '\\';
s[sz++] = c;
goto end_escape;
@@ -5892,24 +5969,27 @@ end_escape:
VALUE;
break;
- case SPACE:
+ case SEPARATOR:
if (c == 0)
+ goto finish_force_terminate;
+ if (!strchr(separators, c))
goto finish;
- if (!strchr(WHITESPACE, c))
- goto finish;
-
break;
}
(*p) ++;
}
+finish_force_terminate:
+ *p = NULL;
finish:
if (!s) {
+ *p = NULL;
*ret = NULL;
return 0;
}
+finish_force_next:
s[sz] = 0;
*ret = s;
s = NULL;
@@ -5917,26 +5997,27 @@ finish:
return 1;
}
-int unquote_first_word_and_warn(
+int extract_first_word_and_warn(
const char **p,
char **ret,
- UnquoteFlags flags,
+ const char *separators,
+ ExtractFlags flags,
const char *unit,
const char *filename,
unsigned line,
const char *rvalue) {
/* Try to unquote it, if it fails, warn about it and try again but this
- * time using UNQUOTE_CUNESCAPE_RELAX to keep the backslashes verbatim
+ * time using EXTRACT_CUNESCAPE_RELAX to keep the backslashes verbatim
* in invalid escape sequences. */
const char *save;
int r;
save = *p;
- r = unquote_first_word(p, ret, flags);
- if (r < 0 && !(flags&UNQUOTE_CUNESCAPE_RELAX)) {
- /* Retry it with UNQUOTE_CUNESCAPE_RELAX. */
+ r = extract_first_word(p, ret, separators, flags);
+ if (r < 0 && !(flags&EXTRACT_CUNESCAPE_RELAX)) {
+ /* Retry it with EXTRACT_CUNESCAPE_RELAX. */
*p = save;
- r = unquote_first_word(p, ret, flags|UNQUOTE_CUNESCAPE_RELAX);
+ r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX);
if (r < 0)
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Unbalanced quoting in command line, ignoring: \"%s\"", rvalue);
@@ -5947,7 +6028,7 @@ int unquote_first_word_and_warn(
return r;
}
-int unquote_many_words(const char **p, UnquoteFlags flags, ...) {
+int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) {
va_list ap;
char **l;
int n = 0, i, c, r;
@@ -5973,7 +6054,7 @@ int unquote_many_words(const char **p, UnquoteFlags flags, ...) {
l = newa0(char*, n);
for (c = 0; c < n; c++) {
- r = unquote_first_word(p, &l[c], flags);
+ r = extract_first_word(p, &l[c], separators, flags);
if (r < 0) {
int j;
@@ -6055,7 +6136,7 @@ int ptsname_malloc(int fd, char **ret) {
}
int openpt_in_namespace(pid_t pid, int flags) {
- _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
+ _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
union {
struct cmsghdr cmsghdr;
@@ -6072,7 +6153,7 @@ int openpt_in_namespace(pid_t pid, int flags) {
assert(pid > 0);
- r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &rootfd);
+ r = namespace_open(pid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
if (r < 0)
return r;
@@ -6088,7 +6169,7 @@ int openpt_in_namespace(pid_t pid, int flags) {
pair[0] = safe_close(pair[0]);
- r = namespace_enter(pidnsfd, mntnsfd, -1, rootfd);
+ r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
if (r < 0)
_exit(EXIT_FAILURE);
@@ -6096,6 +6177,9 @@ int openpt_in_namespace(pid_t pid, int flags) {
if (master < 0)
_exit(EXIT_FAILURE);
+ if (unlockpt(master) < 0)
+ _exit(EXIT_FAILURE);
+
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
@@ -6555,7 +6639,35 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
return 0;
}
+#endif /* NM_IGNORED */
+static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
+ assert(bad);
+
+ for (; *s; s++) {
+ if (*s == '\\' || strchr(bad, *s))
+ *(t++) = '\\';
+
+ *(t++) = *s;
+ }
+
+ return t;
+}
+
+char *shell_escape(const char *s, const char *bad) {
+ char *r, *t;
+
+ r = new(char, strlen(s)*2+1);
+ if (!r)
+ return NULL;
+
+ t = strcpy_backslash_escaped(r, s, bad);
+ *t = 0;
+
+ return r;
+}
+
+#if 0 /* NM_IGNORED */
char *shell_maybe_quote(const char *s) {
const char *p;
char *r, *t;
@@ -6582,13 +6694,7 @@ char *shell_maybe_quote(const char *s) {
*(t++) = '"';
t = mempcpy(t, s, p - s);
- for (; *p; p++) {
-
- if (strchr(SHELL_NEED_ESCAPE, *p))
- *(t++) = '\\';
-
- *(t++) = *p;
- }
+ t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
*(t++)= '"';
*t = 0;
diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h
index 9e3344ebb8..154aabadee 100644
--- a/src/systemd/src/basic/util.h
+++ b/src/systemd/src/basic/util.h
@@ -89,7 +89,7 @@ int strcmp_ptr(const char *a, const char *b) _pure_;
#define newdup(t, p, n) ((t*) memdup_multiply(p, sizeof(t), (n)))
-#define malloc0(n) (calloc((n), 1))
+#define malloc0(n) (calloc(1, (n)))
static inline void *mfree(void *memory) {
free(memory);
@@ -155,12 +155,18 @@ void safe_close_pair(int p[]);
void close_many(const int fds[], unsigned n_fd);
-int parse_size(const char *t, off_t base, off_t *size);
+int fclose_nointr(FILE *f);
+FILE* safe_fclose(FILE *f);
+
+int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_boolean(const char *v) _pure_;
int parse_pid(const char *s, pid_t* ret_pid);
int parse_uid(const char *s, uid_t* ret_uid);
-#define parse_gid(s, ret_uid) parse_uid(s, ret_uid)
+#define parse_gid(s, ret_gid) parse_uid(s, ret_gid)
+
+bool uid_is_valid(uid_t uid);
+#define gid_is_valid(gid) uid_is_valid(gid)
int safe_atou(const char *s, unsigned *ret_u);
int safe_atoi(const char *s, int *ret_i);
@@ -369,6 +375,9 @@ int fd_is_temporary_fs(int fd);
int pipe_eof(int fd);
+DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE);
+#define _cleanup_cpu_free_ _cleanup_(CPU_FREEp)
+
cpu_set_t* cpu_set_malloc(unsigned *ncpus);
#define xsprintf(buf, fmt, ...) assert_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf))
@@ -400,8 +409,6 @@ bool nulstr_contains(const char*nulstr, const char *needle);
bool plymouth_running(void);
-bool machine_name_is_valid(const char *s) _pure_;
-
char* strshorten(char *s, size_t l);
int symlink_idempotent(const char *from, const char *to);
@@ -477,7 +484,7 @@ bool kexec_loaded(void);
int prot_from_flags(int flags) _const_;
-char *format_bytes(char *buf, size_t l, off_t t);
+char *format_bytes(char *buf, size_t l, uint64_t t);
int fd_wait_for_event(int fd, int event, usec_t timeout);
@@ -516,7 +523,10 @@ static inline void close_pairp(int (*p)[2]) {
safe_close_pair(*p);
}
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, fclose);
+static inline void fclosep(FILE **f) {
+ safe_fclose(*f);
+}
+
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
@@ -568,7 +578,10 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
int (*compar) (const void *, const void *, void *),
void *arg);
+#if 0 /* NM_IGNORED */
#define _(String) gettext (String)
+#define N_(String) String
+#endif
void init_gettext(void);
bool is_locale_utf8(void);
@@ -809,8 +822,8 @@ int get_proc_cmdline_key(const char *parameter, char **value);
int container_get_leader(const char *machine, pid_t *pid);
-int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *root_fd);
-int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int root_fd);
+int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
+int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
#if 0 /* NM_IGNORED */
int getpeercred(int fd, struct ucred *ucred);
@@ -864,20 +877,17 @@ int is_symlink(const char *path);
int is_dir(const char *path, bool follow);
int is_device_node(const char *path);
-typedef enum UnquoteFlags {
- UNQUOTE_RELAX = 1,
- UNQUOTE_CUNESCAPE = 2,
- UNQUOTE_CUNESCAPE_RELAX = 4,
-} UnquoteFlags;
+typedef enum ExtractFlags {
+ EXTRACT_RELAX = 1,
+ EXTRACT_CUNESCAPE = 2,
+ EXTRACT_CUNESCAPE_RELAX = 4,
+ EXTRACT_QUOTES = 8,
+ EXTRACT_DONT_COALESCE_SEPARATORS = 16,
+} ExtractFlags;
-int unquote_first_word(const char **p, char **ret, UnquoteFlags flags);
-int unquote_first_word_and_warn(const char **p, char **ret, UnquoteFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
-int unquote_many_words(const char **p, UnquoteFlags flags, ...) _sentinel_;
-
-static inline void free_and_replace(char **s, char *v) {
- free(*s);
- *s = v;
-}
+int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
+int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue);
+int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_;
int free_and_strdup(char **p, const char *s);
@@ -927,6 +937,7 @@ void cmsg_close_all(struct msghdr *mh);
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
+char *shell_escape(const char *s, const char *bad);
char *shell_maybe_quote(const char *s);
int parse_mode(const char *s, mode_t *ret);
diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c
index 0fbfb7860e..1412b1615e 100644
--- a/src/systemd/src/libsystemd-network/dhcp-identifier.c
+++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c
@@ -76,7 +76,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
uint64_t id;
#if 0 /* NM_IGNORED */
- if (detect_container(NULL) <= 0) {
+ if (detect_container() <= 0) {
/* not in a container, udev will be around */
_cleanup_udev_unref_ struct udev *udev;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h
index b94c43f3b8..dc69329921 100644
--- a/src/systemd/src/libsystemd-network/dhcp-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-internal.h
@@ -47,10 +47,10 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_
uint8_t code, size_t optlen, const void *optval);
typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
- const uint8_t *option, void *user_data);
+ const void *option, void *userdata);
int dhcp_option_parse(DHCPMessage *message, size_t len,
- dhcp_option_cb_t cb, void *user_data);
+ dhcp_option_cb_t cb, void *userdata);
int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
uint8_t type, uint16_t arp_type, size_t optlen,
diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
index e4c5a216c0..e024c57a5f 100644
--- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h
@@ -27,7 +27,6 @@
#include <stdint.h>
#include <linux/if_packet.h>
-#include "refcnt.h"
#include "util.h"
#include "list.h"
@@ -50,54 +49,59 @@ struct sd_dhcp_raw_option {
};
struct sd_dhcp_lease {
- RefCount n_ref;
+ unsigned n_ref;
- int32_t time_offset;
+ /* each 0 if unset */
uint32_t t1;
uint32_t t2;
uint32_t lifetime;
- uint32_t mtu_aging_timeout;
+
+ /* each 0 if unset */
be32_t address;
be32_t server_address;
- be32_t subnet_mask;
be32_t router;
be32_t next_server;
+
+ bool have_subnet_mask;
+ be32_t subnet_mask;
+
+ bool have_broadcast;
be32_t broadcast;
+
struct in_addr *dns;
size_t dns_size;
+
struct in_addr *ntp;
size_t ntp_size;
- struct in_addr *policy_filter;
- size_t policy_filter_size;
+
struct sd_dhcp_route *static_route;
- size_t static_route_size;
- size_t static_route_allocated;
- uint16_t boot_file_size;
- uint16_t mdr;
- uint16_t mtu;
- uint8_t ttl;
- bool ip_forward;
- bool ip_forward_non_local;
+ size_t static_route_size, static_route_allocated;
+
+ uint16_t mtu; /* 0 if unset */
+
char *domainname;
char *hostname;
char *root_path;
- uint8_t *client_id;
+
+ void *client_id;
size_t client_id_len;
- uint8_t *vendor_specific;
+
+ void *vendor_specific;
size_t vendor_specific_len;
+
+ char *timezone;
+
LIST_HEAD(struct sd_dhcp_raw_option, private_options);
};
int dhcp_lease_new(sd_dhcp_lease **ret);
-int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
- void *user_data);
-int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag,
- const uint8_t *data, uint8_t len);
+
+int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata);
+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);
-int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id,
- size_t client_id_len);
+int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c
index 50ecf87383..b9a169a54e 100644
--- a/src/systemd/src/libsystemd-network/dhcp-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp-option.c
@@ -142,7 +142,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload,
uint8_t *message_type, dhcp_option_cb_t cb,
- void *user_data) {
+ void *userdata) {
uint8_t code, len;
size_t offset = 0;
@@ -201,7 +201,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
return -EINVAL;
if (cb)
- cb(code, len, &options[offset], user_data);
+ cb(code, len, &options[offset], userdata);
offset += len;
@@ -216,7 +216,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
}
int dhcp_option_parse(DHCPMessage *message, size_t len,
- dhcp_option_cb_t cb, void *user_data) {
+ dhcp_option_cb_t cb, void *userdata) {
uint8_t overload = 0;
uint8_t message_type = 0;
int r;
@@ -230,20 +230,20 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
len -= sizeof(DHCPMessage);
r = parse_options(message->options, len, &overload, &message_type,
- cb, user_data);
+ cb, userdata);
if (r < 0)
return r;
if (overload & DHCP_OVERLOAD_FILE) {
r = parse_options(message->file, sizeof(message->file),
- NULL, &message_type, cb, user_data);
+ NULL, &message_type, cb, userdata);
if (r < 0)
return r;
}
if (overload & DHCP_OVERLOAD_SNAME) {
r = parse_options(message->sname, sizeof(message->sname),
- NULL, &message_type, cb, user_data);
+ NULL, &message_type, cb, userdata);
if (r < 0)
return r;
}
diff --git a/src/systemd/src/libsystemd-network/dhcp-protocol.h b/src/systemd/src/libsystemd-network/dhcp-protocol.h
index dd5ff56b08..d76f15b94c 100644
--- a/src/systemd/src/libsystemd-network/dhcp-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp-protocol.h
@@ -139,6 +139,8 @@ enum {
DHCP_OPTION_REBINDING_T2_TIME = 59,
DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
+ DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
DHCP_OPTION_PRIVATE_BASE = 224,
DHCP_OPTION_PRIVATE_LAST = 254,
diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h
index ee4014faab..b3028c21a9 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h
@@ -5,7 +5,7 @@
/***
This file is part of systemd.
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -70,6 +70,11 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
DHCP6IA *ia);
+int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
+ struct in6_addr **addrs, size_t count,
+ size_t *allocated);
+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen,
+ char ***str_arr);
int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,
diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
index 9f7826c466..b21515437c 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h
@@ -6,7 +6,7 @@
This file is part of systemd.
Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -26,13 +26,11 @@
#include <stdint.h>
-#include "refcnt.h"
-
#include "sd-dhcp6-lease.h"
#include "dhcp6-internal.h"
struct sd_dhcp6_lease {
- RefCount n_ref;
+ unsigned n_ref;
uint8_t *serverid;
size_t serverid_len;
@@ -42,6 +40,17 @@ struct sd_dhcp6_lease {
DHCP6IA ia;
DHCP6Address *addr_iter;
+
+ struct in6_addr *dns;
+ size_t dns_count;
+ size_t dns_allocated;
+ char **domains;
+ size_t domains_count;
+ struct in6_addr *ntp;
+ size_t ntp_count;
+ size_t ntp_allocated;
+ char **ntp_fqdn;
+ size_t ntp_fqdn_count;
};
int dhcp6_lease_clear_timers(DHCP6IA *ia);
@@ -58,6 +67,13 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit);
int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
+int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
+int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
+ size_t optlen);
+int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
+int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval,
+ size_t optlen) ;
+
int dhcp6_lease_new(sd_dhcp6_lease **ret);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref);
diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c
index 626a4d6a7f..377511a83b 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-network.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-network.c
@@ -43,8 +43,7 @@
{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } }
-int dhcp_network_icmp6_bind_router_solicitation(int index)
-{
+int dhcp_network_icmp6_bind_router_solicitation(int index) {
struct icmp6_filter filter = { };
struct ipv6_mreq mreq = {
.ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
@@ -94,8 +93,7 @@ int dhcp_network_icmp6_bind_router_solicitation(int index)
return r;
}
-int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr)
-{
+int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
struct sockaddr_in6 dst = {
.sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c
index 10872a3159..c891fef854 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-option.c
+++ b/src/systemd/src/libsystemd-network/dhcp6-option.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -28,9 +28,11 @@
#include "sparse-endian.h"
#include "unaligned.h"
#include "util.h"
+#include "strv.h"
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
+#include "dns-domain.h"
#define DHCP6_OPTION_IA_NA_LEN 12
#define DHCP6_OPTION_IA_TA_LEN 4
@@ -319,3 +321,98 @@ error:
return r;
}
+
+int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
+ struct in6_addr **addrs, size_t count,
+ size_t *allocated) {
+
+ if (optlen == 0 || optlen % sizeof(struct in6_addr) != 0)
+ return -EINVAL;
+
+ if (!GREEDY_REALLOC(*addrs, *allocated,
+ count * sizeof(struct in6_addr) + optlen))
+ return -ENOMEM;
+
+ memcpy(*addrs + count, optval, optlen);
+
+ count += optlen / sizeof(struct in6_addr);
+
+ return count;
+}
+
+int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char ***str_arr) {
+ size_t pos = 0, idx = 0;
+ _cleanup_free_ char **names = NULL;
+ int r;
+
+ assert_return(optlen > 1, -ENODATA);
+ assert_return(optval[optlen] == '\0', -EINVAL);
+
+ while (pos < optlen) {
+ _cleanup_free_ char *ret = NULL;
+ size_t n = 0, allocated = 0;
+ bool first = true;
+
+ for (;;) {
+ uint8_t c;
+
+ c = optval[pos++];
+
+ if (c == 0)
+ /* End of name */
+ break;
+ else if (c <= 63) {
+ _cleanup_free_ char *t = NULL;
+ const char *label;
+
+ /* Literal label */
+ label = (const char *)&optval[pos];
+ pos += c;
+ if (pos > optlen)
+ return -EMSGSIZE;
+
+ r = dns_label_escape(label, c, &t);
+ if (r < 0)
+ goto fail;
+
+ if (!GREEDY_REALLOC0(ret, allocated, n + !first + strlen(t) + 1)) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ if (!first)
+ ret[n++] = '.';
+ else
+ first = false;
+
+ memcpy(ret + n, t, r);
+ n += r;
+ continue;
+ } else {
+ r = -EBADMSG;
+ goto fail;
+ }
+ }
+
+ if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
+ r = -ENOMEM;
+ goto fail;
+ }
+
+ ret[n] = 0;
+
+ r = strv_extend(&names, ret);
+ if (r < 0)
+ goto fail;
+
+ idx++;
+ }
+
+ *str_arr = names;
+ names = NULL;
+
+ return idx;
+
+fail:
+ return r;
+}
diff --git a/src/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
index 6598d86074..1318c81630 100644
--- a/src/systemd/src/libsystemd-network/dhcp6-protocol.h
+++ b/src/systemd/src/libsystemd-network/dhcp6-protocol.h
@@ -125,7 +125,7 @@ enum {
DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */
DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */
- DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075 */
+ DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */
/* option code 35 is unassigned */
@@ -136,6 +136,12 @@ enum {
};
enum {
+ DHCP6_NTP_SUBOPTION_SRV_ADDR = 1,
+ DHCP6_NTP_SUBOPTION_MC_ADDR = 2,
+ DHCP6_NTP_SUBOPTION_SRV_FQDN = 3,
+};
+
+enum {
DHCP6_STATUS_SUCCESS = 0,
DHCP6_STATUS_UNSPEC_FAIL = 1,
DHCP6_STATUS_NO_ADDRS_AVAIL = 2,
diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c
index 6f5bf11b20..99b59aea75 100644
--- a/src/systemd/src/libsystemd-network/network-internal.c
+++ b/src/systemd/src/libsystemd-network/network-internal.c
@@ -40,6 +40,7 @@
#include "condition.h"
#endif /* NM_IGNORED */
#include "network-internal.h"
+#include "sd-icmp6-nd.h"
#if 0 /* NM_IGNORED */
const char *net_get_name(struct udev_device *device) {
@@ -394,6 +395,20 @@ int deserialize_in_addrs(struct in_addr **ret, const char *string) {
return size;
}
+void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
+ size_t size) {
+ unsigned i;
+
+ assert(f);
+ assert(addresses);
+ assert(size);
+
+ for (i = 0; i < size; i++)
+ fprintf(f, SD_ICMP6_ADDRESS_FORMAT_STR"%s",
+ SD_ICMP6_ADDRESS_FORMAT_VAL(addresses[i]),
+ (i < (size - 1)) ? " ": "");
+}
+
int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
_cleanup_free_ struct in6_addr *addresses = NULL;
int size = 0;
@@ -520,7 +535,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
return 0;
}
-int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size) {
+int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) {
_cleanup_free_ char *hex_buf = NULL;
assert(f);
@@ -536,7 +551,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t
return 0;
}
-int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string) {
+int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) {
assert(data);
assert(data_len);
assert(string);
diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h
index 9e4e0de13f..fd3a0956cd 100644
--- a/src/systemd/src/libsystemd-network/network-internal.h
+++ b/src/systemd/src/libsystemd-network/network-internal.h
@@ -71,6 +71,8 @@ const char *net_get_name(struct udev_device *device);
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
int deserialize_in_addrs(struct in_addr **addresses, const char *string);
+void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
+ size_t size);
int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
@@ -79,5 +81,5 @@ struct sd_dhcp_route;
void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size);
int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string);
-int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size);
-int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string);
+int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
+int deserialize_dhcp_option(void **data, size_t *data_len, const char *string);
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
index ab7adef3c6..ca8e2f24c0 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c
@@ -29,7 +29,6 @@
#include <sys/ioctl.h>
#include "util.h"
-#include "refcnt.h"
#include "random-util.h"
#include "async.h"
@@ -43,7 +42,7 @@
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
struct sd_dhcp_client {
- RefCount n_ref;
+ unsigned n_ref;
DHCPState state;
sd_event *event;
@@ -108,7 +107,6 @@ static const uint8_t default_req_opts[] = {
DHCP_OPTION_HOST_NAME,
DHCP_OPTION_DOMAIN_NAME,
DHCP_OPTION_DOMAIN_NAME_SERVER,
- DHCP_OPTION_NTP_SERVER,
};
static int client_receive_message_raw(sd_event_source *s, int fd,
@@ -350,7 +348,7 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
client->state != DHCP_STATE_REBINDING)
return -EADDRNOTAVAIL;
- *ret = sd_dhcp_lease_ref(client->lease);
+ *ret = client->lease;
return 0;
}
@@ -379,8 +377,7 @@ static int client_initialize(sd_dhcp_client *client) {
client->state = DHCP_STATE_INIT;
client->xid = 0;
- if (client->lease)
- client->lease = sd_dhcp_lease_unref(client->lease);
+ client->lease = sd_dhcp_lease_unref(client->lease);
return 0;
}
@@ -1057,18 +1054,16 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
}
lease->next_server = offer->siaddr;
-
lease->address = offer->yiaddr;
- if (lease->address == INADDR_ANY ||
- lease->server_address == INADDR_ANY ||
+ if (lease->address == 0 ||
+ lease->server_address == 0 ||
lease->lifetime == 0) {
- log_dhcp_client(client, "received lease lacks address, server "
- "address or lease lifetime, ignoring");
+ log_dhcp_client(client, "received lease lacks address, server address or lease lifetime, ignoring");
return -ENOMSG;
}
- if (lease->subnet_mask == INADDR_ANY) {
+ if (!lease->have_subnet_mask) {
r = dhcp_lease_set_default_subnet_mask(lease);
if (r < 0) {
log_dhcp_client(client, "received lease lacks subnet "
@@ -1170,13 +1165,17 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
return r;
}
-static uint64_t client_compute_timeout(sd_dhcp_client *client,
- uint32_t lifetime, double factor) {
+static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) {
assert(client);
assert(client->request_sent);
- assert(lifetime);
+ assert(lifetime > 0);
- return client->request_sent + ((lifetime - 3) * USEC_PER_SEC * factor) +
+ if (lifetime > 3)
+ lifetime -= 3;
+ else
+ lifetime = 0;
+
+ return client->request_sent + (lifetime * USEC_PER_SEC * factor) +
+ (random_u32() & 0x1fffff);
}
@@ -1208,7 +1207,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
/* convert the various timeouts from relative (secs) to absolute (usecs) */
lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1);
- if (client->lease->t1 && client->lease->t2) {
+ if (client->lease->t1 > 0 && client->lease->t2 > 0) {
/* both T1 and T2 are given */
if (client->lease->t1 < client->lease->t2 &&
client->lease->t2 < client->lease->lifetime) {
@@ -1222,7 +1221,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
client->lease->t1 = client->lease->lifetime / 2;
}
- } else if (client->lease->t2 && client->lease->t2 < client->lease->lifetime) {
+ } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) {
/* only T2 is given, and it is valid */
t2_timeout = client_compute_timeout(client, client->lease->t2, 1);
t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5);
@@ -1232,7 +1231,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
client->lease->t2 = (client->lease->lifetime * 7) / 8;
}
- } else if (client->lease->t1 && client->lease->t1 < client->lease->lifetime) {
+ } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) {
/* only T1 is given, and it is valid */
t1_timeout = client_compute_timeout(client, client->lease->t1, 1);
t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0);
@@ -1678,30 +1677,41 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
}
sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
- if (client)
- assert_se(REFCNT_INC(client->n_ref) >= 2);
+
+ if (!client)
+ return NULL;
+
+ assert(client->n_ref >= 1);
+ client->n_ref++;
return client;
}
sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
- if (client && REFCNT_DEC(client->n_ref) == 0) {
- log_dhcp_client(client, "FREE");
- client_initialize(client);
+ if (!client)
+ return NULL;
- client->receive_message =
- sd_event_source_unref(client->receive_message);
+ assert(client->n_ref >= 1);
+ client->n_ref--;
- sd_dhcp_client_detach_event(client);
+ if (client->n_ref > 0)
+ return NULL;
- sd_dhcp_lease_unref(client->lease);
+ log_dhcp_client(client, "FREE");
- free(client->req_opts);
- free(client->hostname);
- free(client->vendor_class_identifier);
- free(client);
- }
+ client_initialize(client);
+
+ client->receive_message = sd_event_source_unref(client->receive_message);
+
+ sd_dhcp_client_detach_event(client);
+
+ sd_dhcp_lease_unref(client->lease);
+
+ free(client->req_opts);
+ free(client->hostname);
+ free(client->vendor_class_identifier);
+ free(client);
return NULL;
}
@@ -1715,7 +1725,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) {
if (!client)
return -ENOMEM;
- client->n_ref = REFCNT_INIT;
+ client->n_ref = 1;
client->state = DHCP_STATE_INIT;
client->index = -1;
client->fd = -1;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
index de7cdb3880..054226c757 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c
@@ -30,18 +30,31 @@
#include "unaligned.h"
#include "in-addr-util.h"
#include "hostname-util.h"
+#include "dns-domain.h"
+#include "network-internal.h"
#include "dhcp-protocol.h"
#include "dhcp-lease-internal.h"
#include "sd-dhcp-lease.h"
-#include "network-internal.h"
-#include "dns-domain.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
+ if (lease->address == 0)
+ return -ENODATA;
+
addr->s_addr = lease->address;
+ return 0;
+}
+int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) {
+ assert_return(lease, -EINVAL);
+ assert_return(addr, -EINVAL);
+
+ if (!lease->have_broadcast)
+ return -ENODATA;
+
+ addr->s_addr = lease->broadcast;
return 0;
}
@@ -49,8 +62,32 @@ int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
assert_return(lease, -EINVAL);
assert_return(lifetime, -EINVAL);
+ if (lease->lifetime <= 0)
+ return -ENODATA;
+
*lifetime = lease->lifetime;
+ return 0;
+}
+
+int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) {
+ assert_return(lease, -EINVAL);
+ assert_return(t1, -EINVAL);
+
+ if (lease->t1 <= 0)
+ return -ENODATA;
+ *t1 = lease->t1;
+ return 0;
+}
+
+int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) {
+ assert_return(lease, -EINVAL);
+ assert_return(t2, -EINVAL);
+
+ if (lease->t2 <= 0)
+ return -ENODATA;
+
+ *t2 = lease->t2;
return 0;
}
@@ -58,11 +95,10 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
assert_return(lease, -EINVAL);
assert_return(mtu, -EINVAL);
- if (lease->mtu)
- *mtu = lease->mtu;
- else
- return -ENOENT;
+ if (lease->mtu <= 0)
+ return -ENODATA;
+ *mtu = lease->mtu;
return 0;
}
@@ -70,37 +106,32 @@ int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- if (lease->dns_size) {
- *addr = lease->dns;
- return lease->dns_size;
- } else
- return -ENOENT;
+ if (lease->dns_size <= 0)
+ return -ENODATA;
- return 0;
+ *addr = lease->dns;
+ return (int) lease->dns_size;
}
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- if (lease->ntp_size) {
- *addr = lease->ntp;
- return lease->ntp_size;
- } else
- return -ENOENT;
+ if (lease->ntp_size <= 0)
+ return -ENODATA;
- return 0;
+ *addr = lease->ntp;
+ return (int) lease->ntp_size;
}
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
assert_return(lease, -EINVAL);
assert_return(domainname, -EINVAL);
- if (lease->domainname)
- *domainname = lease->domainname;
- else
- return -ENOENT;
+ if (!lease->domainname)
+ return -ENODATA;
+ *domainname = lease->domainname;
return 0;
}
@@ -108,11 +139,10 @@ int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
assert_return(lease, -EINVAL);
assert_return(hostname, -EINVAL);
- if (lease->hostname)
- *hostname = lease->hostname;
- else
- return -ENOENT;
+ if (!lease->hostname)
+ return -ENODATA;
+ *hostname = lease->hostname;
return 0;
}
@@ -120,11 +150,10 @@ int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
assert_return(lease, -EINVAL);
assert_return(root_path, -EINVAL);
- if (lease->root_path)
- *root_path = lease->root_path;
- else
- return -ENOENT;
+ if (!lease->root_path)
+ return -ENODATA;
+ *root_path = lease->root_path;
return 0;
}
@@ -132,11 +161,10 @@ int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- if (lease->router != INADDR_ANY)
- addr->s_addr = lease->router;
- else
- return -ENOENT;
+ if (lease->router == 0)
+ return -ENODATA;
+ addr->s_addr = lease->router;
return 0;
}
@@ -144,8 +172,10 @@ int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- addr->s_addr = lease->subnet_mask;
+ if (!lease->have_subnet_mask)
+ return -ENODATA;
+ addr->s_addr = lease->subnet_mask;
return 0;
}
@@ -153,8 +183,10 @@ int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *ad
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- addr->s_addr = lease->server_address;
+ if (lease->server_address == 0)
+ return -ENODATA;
+ addr->s_addr = lease->server_address;
return 0;
}
@@ -162,136 +194,134 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
- addr->s_addr = lease->next_server;
+ if (lease->next_server == 0)
+ return -ENODATA;
+ addr->s_addr = lease->next_server;
return 0;
}
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) {
-
assert_return(lease, -EINVAL);
assert_return(routes, -EINVAL);
- if (lease->static_route_size) {
- *routes = lease->static_route;
- return lease->static_route_size;
- } else
- return -ENOENT;
+ if (lease->static_route_size <= 0)
+ return -ENODATA;
- return 0;
+ *routes = lease->static_route;
+ return (int) lease->static_route_size;
}
-int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data,
- size_t *data_len) {
+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);
assert_return(data_len, -EINVAL);
- if (!lease->vendor_specific)
- return -ENOENT;
+ if (lease->vendor_specific_len <= 0)
+ return -ENODATA;
*data = lease->vendor_specific;
*data_len = lease->vendor_specific_len;
-
return 0;
}
sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
- if (lease)
- assert_se(REFCNT_INC(lease->n_ref) >= 2);
+
+ if (!lease)
+ return NULL;
+
+ assert(lease->n_ref >= 1);
+ lease->n_ref++;
return lease;
}
sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
- if (lease && REFCNT_DEC(lease->n_ref) == 0) {
- while (lease->private_options) {
- struct sd_dhcp_raw_option *option = lease->private_options;
- LIST_REMOVE(options, lease->private_options, option);
+ if (!lease)
+ return NULL;
- free(option->data);
- free(option);
- }
- free(lease->hostname);
- free(lease->domainname);
- free(lease->dns);
- free(lease->ntp);
- free(lease->static_route);
- free(lease->client_id);
- free(lease->vendor_specific);
- free(lease);
- }
+ assert(lease->n_ref >= 1);
+ lease->n_ref--;
- return NULL;
-}
+ if (lease->n_ref > 0)
+ return NULL;
-static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
- assert(option);
- assert(ret);
+ while (lease->private_options) {
+ struct sd_dhcp_raw_option *option = lease->private_options;
- if (len == 4) {
- *ret = unaligned_read_be32((be32_t*) option);
+ LIST_REMOVE(options, lease->private_options, option);
- if (*ret < min)
- *ret = min;
+ free(option->data);
+ free(option);
}
-}
-static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) {
- lease_parse_u32(option, len, (uint32_t *)ret, 0);
+ free(lease->hostname);
+ free(lease->domainname);
+ free(lease->dns);
+ free(lease->ntp);
+ free(lease->static_route);
+ free(lease->client_id);
+ free(lease->vendor_specific);
+ free(lease);
+
+ return NULL;
}
-static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
+static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
assert(option);
assert(ret);
- if (len == 2) {
- *ret = unaligned_read_be16((be16_t*) option);
+ if (len != 4)
+ return -EINVAL;
- if (*ret < min)
- *ret = min;
- }
+ *ret = unaligned_read_be32((be32_t*) option);
+ if (*ret < min)
+ *ret = min;
+
+ return 0;
}
-static void lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
+static int lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
assert(option);
assert(ret);
- if (len == 4)
- memcpy(ret, option, 4);
-}
+ if (len != 2)
+ return -EINVAL;
-static void lease_parse_bool(const uint8_t *option, size_t len, bool *ret) {
- assert(option);
- assert(ret);
+ *ret = unaligned_read_be16((be16_t*) option);
+ if (*ret < min)
+ *ret = min;
- if (len == 1)
- *ret = !!(*option);
+ return 0;
}
-static void lease_parse_u8(const uint8_t *option, size_t len, uint8_t *ret, uint8_t min) {
+static int lease_parse_be32(const uint8_t *option, size_t len, be32_t *ret) {
assert(option);
assert(ret);
- if (len == 1) {
- *ret = *option;
+ if (len != 4)
+ return -EINVAL;
- if (*ret < min)
- *ret = min;
- }
+ memcpy(ret, option, 4);
+ return 0;
}
static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
assert(option);
assert(ret);
- if (len >= 1) {
+ if (len <= 0)
+ *ret = mfree(*ret);
+ else {
char *string;
+ if (memchr(option, 0, len))
+ return -EINVAL;
+
string = strndup((const char *)option, len);
if (!string)
- return -errno;
+ return -ENOMEM;
free(*ret);
*ret = string;
@@ -300,48 +330,47 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
return 0;
}
-static int lease_parse_in_addrs_aux(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size, size_t mult) {
+static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
assert(option);
assert(ret);
- assert(ret_size);
+ assert(n_ret);
- if (len && !(len % (4 * mult))) {
- size_t size;
+ if (len <= 0) {
+ *ret = mfree(*ret);
+ *n_ret = 0;
+ } else {
+ size_t n_addresses;
struct in_addr *addresses;
- size = len / 4;
+ if (len % 4 != 0)
+ return -EINVAL;
+
+ n_addresses = len / 4;
- addresses = newdup(struct in_addr, option, size);
+ addresses = newdup(struct in_addr, option, n_addresses);
if (!addresses)
return -ENOMEM;
free(*ret);
*ret = addresses;
- *ret_size = size;
+ *n_ret = n_addresses;
}
return 0;
}
-static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
- return lease_parse_in_addrs_aux(option, len, ret, ret_size, 1);
-}
-
-static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *ret_size) {
- return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2);
-}
-
-static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
- size_t *routes_size, size_t *routes_allocated) {
+static int lease_parse_routes(
+ const uint8_t *option, size_t len,
+ struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) {
struct in_addr addr;
- assert(option);
+ assert(option || len <= 0);
assert(routes);
assert(routes_size);
assert(routes_allocated);
- if (!len)
+ if (len <= 0)
return 0;
if (len % 8 != 0)
@@ -356,15 +385,15 @@ static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_
r = in_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen);
if (r < 0) {
- log_error("Failed to determine destination prefix length from class based IP, ignoring");
+ log_debug("Failed to determine destination prefix length from class based IP, ignoring");
continue;
}
- lease_parse_be32(option, 4, &addr.s_addr);
+ assert_se(lease_parse_be32(option, 4, &addr.s_addr) >= 0);
route->dst_addr = inet_makeaddr(inet_netof(addr), 0);
option += 4;
- lease_parse_be32(option, 4, &route->gw_addr.s_addr);
+ assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0);
option += 4;
len -= 8;
@@ -375,14 +404,18 @@ static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_
}
/* parses RFC3442 Classless Static Route Option */
-static int lease_parse_classless_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
- size_t *routes_size, size_t *routes_allocated) {
+static int lease_parse_classless_routes(
+ const uint8_t *option, size_t len,
+ struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) {
- assert(option);
+ assert(option || len <= 0);
assert(routes);
assert(routes_size);
assert(routes_allocated);
+ if (len <= 0)
+ return 0;
+
/* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
while (len > 0) {
@@ -390,7 +423,7 @@ static int lease_parse_classless_routes(const uint8_t *option, size_t len, struc
struct sd_dhcp_route *route;
if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1))
- return -ENOMEM;
+ return -ENOMEM;
route = *routes + *routes_size;
@@ -421,223 +454,222 @@ static int lease_parse_classless_routes(const uint8_t *option, size_t len, struc
return 0;
}
-int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
- void *user_data) {
- sd_dhcp_lease *lease = user_data;
+int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
+ sd_dhcp_lease *lease = userdata;
int r;
assert(lease);
switch(code) {
- case DHCP_OPTION_TIME_OFFSET:
- lease_parse_s32(option, len, &lease->time_offset);
-
- break;
-
- case DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT:
- lease_parse_u32(option, len, &lease->mtu_aging_timeout, 0);
-
- break;
-
case DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
- lease_parse_u32(option, len, &lease->lifetime, 1);
+ r = lease_parse_u32(option, len, &lease->lifetime, 1);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse lease time, ignoring: %m");
break;
case DHCP_OPTION_SERVER_IDENTIFIER:
- lease_parse_be32(option, len, &lease->server_address);
+ r = lease_parse_be32(option, len, &lease->server_address);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse server identifier, ignoring: %m");
break;
case DHCP_OPTION_SUBNET_MASK:
- lease_parse_be32(option, len, &lease->subnet_mask);
-
+ r = lease_parse_be32(option, len, &lease->subnet_mask);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m");
+ else
+ lease->have_subnet_mask = true;
break;
case DHCP_OPTION_BROADCAST:
- lease_parse_be32(option, len, &lease->broadcast);
-
+ r = lease_parse_be32(option, len, &lease->broadcast);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m");
+ else
+ lease->have_broadcast = true;
break;
case DHCP_OPTION_ROUTER:
- if(len >= 4)
- lease_parse_be32(option, 4, &lease->router);
-
+ if (len >= 4) {
+ r = lease_parse_be32(option, 4, &lease->router);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse router address, ignoring: %m");
+ }
break;
case DHCP_OPTION_DOMAIN_NAME_SERVER:
r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
if (r < 0)
- return r;
-
+ log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");
break;
case DHCP_OPTION_NTP_SERVER:
r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
if (r < 0)
- return r;
-
- break;
-
- case DHCP_OPTION_POLICY_FILTER:
- r = lease_parse_in_addrs_pairs(option, len, &lease->policy_filter, &lease->policy_filter_size);
- if (r < 0)
- return r;
-
+ log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
break;
case DHCP_OPTION_STATIC_ROUTE:
- r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size,
- &lease->static_route_allocated);
+ r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
if (r < 0)
- return r;
-
+ log_debug_errno(r, "Failed to parse static routes, ignoring: %m");
break;
case DHCP_OPTION_INTERFACE_MTU:
- lease_parse_u16(option, len, &lease->mtu, 68);
-
- break;
-
- case DHCP_OPTION_INTERFACE_MDR:
- lease_parse_u16(option, len, &lease->mdr, 576);
-
- break;
-
- case DHCP_OPTION_INTERFACE_TTL:
- lease_parse_u8(option, len, &lease->ttl, 1);
-
- break;
-
- case DHCP_OPTION_BOOT_FILE_SIZE:
- lease_parse_u16(option, len, &lease->boot_file_size, 0);
-
+ r = lease_parse_u16(option, len, &lease->mtu, 68);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
break;
- case DHCP_OPTION_DOMAIN_NAME:
- {
- _cleanup_free_ char *domainname = NULL;
- char *e;
+ case DHCP_OPTION_DOMAIN_NAME: {
+ _cleanup_free_ char *domainname = NULL, *normalized = NULL;
r = lease_parse_string(option, len, &domainname);
- if (r < 0)
- return r;
-
- /* Chop off trailing dot of domain name that some DHCP
- * servers send us back. Internally we want to store
- * host names without trailing dots and
- * host_name_is_valid() doesn't accept them. */
- e = endswith(domainname, ".");
- if (e)
- *e = 0;
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse domain name, ignoring: %m");
+ return 0;
+ }
- if (is_localhost(domainname))
- break;
+ r = dns_name_normalize(domainname, &normalized);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to normalize domain name '%s': %m", domainname);
+ return 0;
+ }
- r = dns_name_is_valid(domainname);
- if (r <= 0) {
- if (r < 0)
- log_error_errno(r, "Failed to validate domain name: %s: %m", domainname);
- if (r == 0)
- log_warning("Domain name is not valid, ignoring: %s", domainname);
+ if (is_localhost(normalized)) {
+ log_debug_errno(r, "Detected 'localhost' as suggested domain name, ignoring.");
break;
}
free(lease->domainname);
- lease->domainname = domainname;
- domainname = NULL;
+ lease->domainname = normalized;
+ normalized = NULL;
break;
}
- case DHCP_OPTION_HOST_NAME:
- {
- _cleanup_free_ char *hostname = NULL;
- char *e;
+
+ case DHCP_OPTION_HOST_NAME: {
+ _cleanup_free_ char *hostname = NULL, *normalized = NULL;
r = lease_parse_string(option, len, &hostname);
- if (r < 0)
- return r;
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse host name, ignoring: %m");
+ return 0;
+ }
- e = endswith(hostname, ".");
- if (e)
- *e = 0;
+ r = dns_name_normalize(hostname, &normalized);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to normalize host name '%s', ignoring: %m", hostname);
+ return 0;
+ }
- if (!hostname_is_valid(hostname, false) || is_localhost(hostname))
- break;
+ if (is_localhost(normalized)) {
+ log_debug_errno(r, "Detected 'localhost' as suggested host name, ignoring.");
+ return 0;
+ }
- free_and_replace(&lease->hostname, hostname);
- hostname = NULL;
+ free(lease->hostname);
+ lease->hostname = normalized;
+ normalized = NULL;
break;
}
+
case DHCP_OPTION_ROOT_PATH:
r = lease_parse_string(option, len, &lease->root_path);
if (r < 0)
- return r;
-
+ log_debug_errno(r, "Failed to parse root path, ignoring: %m");
break;
case DHCP_OPTION_RENEWAL_T1_TIME:
- lease_parse_u32(option, len, &lease->t1, 1);
-
+ r = lease_parse_u32(option, len, &lease->t1, 1);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");
break;
case DHCP_OPTION_REBINDING_T2_TIME:
- lease_parse_u32(option, len, &lease->t2, 1);
-
+ r = lease_parse_u32(option, len, &lease->t2, 1);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");
break;
- case DHCP_OPTION_ENABLE_IP_FORWARDING:
- lease_parse_bool(option, len, &lease->ip_forward);
-
+ case DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
+ r = lease_parse_classless_routes(
+ option, len,
+ &lease->static_route,
+ &lease->static_route_size,
+ &lease->static_route_allocated);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
break;
- case DHCP_OPTION_ENABLE_IP_FORWARDING_NL:
- lease_parse_bool(option, len, &lease->ip_forward_non_local);
+ case DHCP_OPTION_NEW_TZDB_TIMEZONE: {
+ _cleanup_free_ char *tz = NULL;
- break;
+ r = lease_parse_string(option, len, &tz);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse timezone option, ignoring: %m");
+ return 0;
+ }
- case DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
- r = lease_parse_classless_routes(option, len, &lease->static_route, &lease->static_route_size,
- &lease->static_route_allocated);
- if (r < 0)
- return r;
+ if (!timezone_is_valid(tz)) {
+ log_debug_errno(r, "Timezone is not valid, ignoring: %m");
+ return 0;
+ }
+
+ free(lease->timezone);
+ lease->timezone = tz;
+ tz = NULL;
break;
+ }
case DHCP_OPTION_VENDOR_SPECIFIC:
- if (len >= 1) {
- free(lease->vendor_specific);
- lease->vendor_specific = memdup(option, len);
- if (!lease->vendor_specific)
+
+ if (len <= 0)
+ lease->vendor_specific = mfree(lease->vendor_specific);
+ else {
+ void *p;
+
+ p = memdup(option, len);
+ if (!p)
return -ENOMEM;
- lease->vendor_specific_len = len;
- }
- break;
+ free(lease->vendor_specific);
+ lease->vendor_specific = p;
+ }
- default:
- if (code < DHCP_OPTION_PRIVATE_BASE || code > DHCP_OPTION_PRIVATE_LAST)
- break;
+ lease->vendor_specific_len = len;
+ break;
+ case DHCP_OPTION_PRIVATE_BASE ... DHCP_OPTION_PRIVATE_LAST:
r = dhcp_lease_insert_private_option(lease, code, option, len);
if (r < 0)
return r;
+
+ break;
+
+ default:
+ log_debug("Ignoring option DHCP option %i while parsing.", code);
+ break;
}
return 0;
}
-int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag,
- const uint8_t *data, uint8_t len) {
+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;
+ assert(lease);
+
LIST_FOREACH(options, cur, lease->private_options) {
if (tag < cur->tag)
break;
- else if (tag == cur->tag) {
- log_error("Ignoring duplicate option, tagged %d.", tag);
+ if (tag == cur->tag) {
+ log_debug("Ignoring duplicate option, tagged %i.", tag);
return 0;
}
}
@@ -655,7 +687,6 @@ int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag,
}
LIST_INSERT_BEFORE(options, lease->private_options, cur, option);
-
return 0;
}
@@ -667,8 +698,7 @@ int dhcp_lease_new(sd_dhcp_lease **ret) {
return -ENOMEM;
lease->router = INADDR_ANY;
- lease->n_ref = REFCNT_INIT;
- LIST_HEAD_INIT(lease->private_options);
+ lease->n_ref = 1;
*ret = lease;
return 0;
@@ -680,11 +710,12 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
struct sd_dhcp_raw_option *option;
struct in_addr address;
const struct in_addr *addresses;
- const uint8_t *client_id, *data;
+ const void *client_id, *data;
size_t client_id_len, data_len;
const char *string;
uint16_t mtu;
struct sd_dhcp_route *routes;
+ uint32_t t1, t2, lifetime;
int r;
assert(lease);
@@ -696,19 +727,16 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
fchmod(fileno(f), 0644);
- r = sd_dhcp_lease_get_address(lease, &address);
- if (r < 0)
- goto fail;
-
fprintf(f,
- "# This is private data. Do not parse.\n"
- "ADDRESS=%s\n", inet_ntoa(address));
+ "# This is private data. Do not parse.\n");
- r = sd_dhcp_lease_get_netmask(lease, &address);
- if (r < 0)
- goto fail;
+ r = sd_dhcp_lease_get_address(lease, &address);
+ if (r >= 0)
+ fprintf(f, "ADDRESS=%s\n", inet_ntoa(address));
- fprintf(f, "NETMASK=%s\n", inet_ntoa(address));
+ r = sd_dhcp_lease_get_netmask(lease, &address);
+ if (r >= 0)
+ fprintf(f, "NETMASK=%s\n", inet_ntoa(address));
r = sd_dhcp_lease_get_router(lease, &address);
if (r >= 0)
@@ -716,28 +744,45 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
r = sd_dhcp_lease_get_server_identifier(lease, &address);
if (r >= 0)
- fprintf(f, "SERVER_ADDRESS=%s\n",
- inet_ntoa(address));
+ fprintf(f, "SERVER_ADDRESS=%s\n", inet_ntoa(address));
r = sd_dhcp_lease_get_next_server(lease, &address);
if (r >= 0)
fprintf(f, "NEXT_SERVER=%s\n", inet_ntoa(address));
+ r = sd_dhcp_lease_get_broadcast(lease, &address);
+ if (r >= 0)
+ fprintf(f, "BROADCAST=%s\n", inet_ntoa(address));
+
r = sd_dhcp_lease_get_mtu(lease, &mtu);
if (r >= 0)
fprintf(f, "MTU=%" PRIu16 "\n", mtu);
- fputs("DNS=", f);
- r = sd_dhcp_lease_get_dns(lease, &addresses);
+ r = sd_dhcp_lease_get_t1(lease, &t1);
+ if (r >= 0)
+ fprintf(f, "T1=%" PRIu32 "\n", t1);
+
+ r = sd_dhcp_lease_get_t2(lease, &t2);
+ if (r >= 0)
+ fprintf(f, "T2=%" PRIu32 "\n", t2);
+
+ r = sd_dhcp_lease_get_lifetime(lease, &lifetime);
if (r >= 0)
+ fprintf(f, "LIFETIME=%" PRIu32 "\n", lifetime);
+
+ r = sd_dhcp_lease_get_dns(lease, &addresses);
+ if (r > 0) {
+ fputs("DNS=", f);
serialize_in_addrs(f, addresses, r);
- fputs("\n", f);
+ fputs("\n", f);
+ }
- fputs("NTP=", f);
r = sd_dhcp_lease_get_ntp(lease, &addresses);
- if (r >= 0)
+ if (r > 0) {
+ fputs("NTP=", f);
serialize_in_addrs(f, addresses, r);
- fputs("\n", f);
+ fputs("\n", f);
+ }
r = sd_dhcp_lease_get_domainname(lease, &string);
if (r >= 0)
@@ -752,9 +797,13 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
fprintf(f, "ROOT_PATH=%s\n", string);
r = sd_dhcp_lease_get_routes(lease, &routes);
- if (r >= 0)
+ if (r > 0)
serialize_dhcp_routes(f, "ROUTES", routes, r);
+ r = sd_dhcp_lease_get_timezone(lease, &string);
+ if (r >= 0)
+ fprintf(f, "TIMEZONE=%s\n", string);
+
r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
if (r >= 0) {
_cleanup_free_ char *client_id_hex = NULL;
@@ -781,6 +830,7 @@ int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
LIST_FOREACH(options, option, lease->private_options) {
char key[strlen("OPTION_000")+1];
+
snprintf(key, sizeof(key), "OPTION_%"PRIu8, option->tag);
r = serialize_dhcp_option(f, key, option->data, option->length);
if (r < 0)
@@ -806,15 +856,26 @@ fail:
}
int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
+
_cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
- _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL,
- *server_address = NULL, *next_server = NULL,
- *dns = NULL, *ntp = NULL, *mtu = NULL,
- *routes = NULL, *client_id_hex = NULL,
- *vendor_specific_hex = NULL,
- *options[DHCP_OPTION_PRIVATE_LAST -
- DHCP_OPTION_PRIVATE_BASE + 1] = { NULL };
- struct in_addr addr;
+ _cleanup_free_ char
+ *address = NULL,
+ *router = NULL,
+ *netmask = NULL,
+ *server_address = NULL,
+ *next_server = NULL,
+ *broadcast = NULL,
+ *dns = NULL,
+ *ntp = NULL,
+ *mtu = NULL,
+ *routes = NULL,
+ *client_id_hex = NULL,
+ *vendor_specific_hex = NULL,
+ *lifetime = NULL,
+ *t1 = NULL,
+ *t2 = NULL,
+ *options[DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE + 1] = {};
+
int r, i;
assert(lease_file);
@@ -830,6 +891,7 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"NETMASK", &netmask,
"SERVER_IDENTIFIER", &server_address,
"NEXT_SERVER", &next_server,
+ "BROADCAST", &broadcast,
"DNS", &dns,
"NTP", &ntp,
"MTU", &mtu,
@@ -838,7 +900,11 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"ROOT_PATH", &lease->root_path,
"ROUTES", &routes,
"CLIENTID", &client_id_hex,
+ "TIMEZONE", &lease->timezone,
"VENDOR_SPECIFIC", &vendor_specific_hex,
+ "LIFETIME", &lifetime,
+ "T1", &t1,
+ "T2", &t2,
"OPTION_224", &options[0],
"OPTION_225", &options[1],
"OPTION_226", &options[2],
@@ -871,100 +937,123 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"OPTION_253", &options[29],
"OPTION_254", &options[30],
NULL);
- if (r < 0) {
- if (r == -ENOENT)
- return 0;
-
- return log_error_errno(r, "Failed to read %s: %m", lease_file);
- }
-
- r = inet_pton(AF_INET, address, &addr);
if (r < 0)
return r;
- lease->address = addr.s_addr;
+ if (address) {
+ r = inet_pton(AF_INET, address, &lease->address);
+ if (r <= 0)
+ log_debug_errno(errno, "Failed to parse address %s, ignoring: %m", address);
+ }
if (router) {
- r = inet_pton(AF_INET, router, &addr);
- if (r < 0)
- return r;
-
- lease->router = addr.s_addr;
+ r = inet_pton(AF_INET, router, &lease->router);
+ if (r <= 0)
+ log_debug_errno(errno, "Failed to parse router %s, ignoring: %m", router);
}
- r = inet_pton(AF_INET, netmask, &addr);
- if (r < 0)
- return r;
-
- lease->subnet_mask = addr.s_addr;
+ if (netmask) {
+ r = inet_pton(AF_INET, netmask, &lease->subnet_mask);
+ if (r <= 0)
+ log_debug_errno(errno, "Failed to parse netmask %s, ignoring: %m", netmask);
+ else
+ lease->have_subnet_mask = true;
+ }
if (server_address) {
- r = inet_pton(AF_INET, server_address, &addr);
- if (r < 0)
- return r;
-
- lease->server_address = addr.s_addr;
+ r = inet_pton(AF_INET, server_address, &lease->server_address);
+ if (r <= 0)
+ log_debug_errno(errno, "Failed to parse netmask %s, ignoring: %m", server_address);
}
if (next_server) {
- r = inet_pton(AF_INET, next_server, &addr);
- if (r < 0)
- return r;
+ r = inet_pton(AF_INET, next_server, &lease->next_server);
+ if (r <= 0)
+ log_debug_errno(errno, "Failed to parse next server %s, ignoring: %m", next_server);
+ }
- lease->next_server = addr.s_addr;
+ if (broadcast) {
+ r = inet_pton(AF_INET, broadcast, &lease->broadcast);
+ if (r <= 0)
+ log_debug_errno(errno, "Failed to parse broadcast address %s, ignoring: %m", broadcast);
+ else
+ lease->have_broadcast = true;
}
if (dns) {
r = deserialize_in_addrs(&lease->dns, dns);
if (r < 0)
- return r;
-
- lease->dns_size = r;
+ log_debug_errno(r, "Failed to deserialize DNS servers %s, ignoring: %m", dns);
+ else
+ lease->dns_size = r;
}
if (ntp) {
r = deserialize_in_addrs(&lease->ntp, ntp);
if (r < 0)
- return r;
-
- lease->ntp_size = r;
+ log_debug_errno(r, "Failed to deserialize NTP servers %s, ignoring: %m", ntp);
+ else
+ lease->ntp_size = r;
}
if (mtu) {
- uint16_t u;
- if (sscanf(mtu, "%" SCNu16, &u) > 0)
- lease->mtu = u;
+ r = safe_atou16(mtu, &lease->mtu);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse MTU %s, ignoring: %m", mtu);
}
if (routes) {
- r = deserialize_dhcp_routes(&lease->static_route, &lease->static_route_size,
- &lease->static_route_allocated, routes);
+ r = deserialize_dhcp_routes(
+ &lease->static_route,
+ &lease->static_route_size,
+ &lease->static_route_allocated,
+ routes);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse DHCP routes %s, ignoring: %m", routes);
+ }
+
+ if (lifetime) {
+ r = safe_atou32(lifetime, &lease->lifetime);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse lifetime %s, ignoring: %m", lifetime);
+ }
+
+ if (t1) {
+ r = safe_atou32(t1, &lease->t1);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse T1 %s, ignoring: %m", t1);
+ }
+
+ if (t2) {
+ r = safe_atou32(t2, &lease->t2);
if (r < 0)
- return r;
+ log_debug_errno(r, "Failed to parse T2 %s, ignoring: %m", t2);
}
if (client_id_hex) {
r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex);
if (r < 0)
- return r;
+ log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex);
}
if (vendor_specific_hex) {
r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex);
if (r < 0)
- return r;
+ log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
}
for (i = 0; i <= DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE; i++) {
- _cleanup_free_ uint8_t *data = NULL;
+ _cleanup_free_ void *data = NULL;
size_t len;
if (!options[i])
continue;
r = deserialize_dhcp_option(&data, &len, options[i]);
- if (r < 0)
- return r;
+ if (r < 0) {
+ log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]);
+ continue;
+ }
r = dhcp_lease_insert_private_option(lease, DHCP_OPTION_PRIVATE_BASE + i, data, len);
if (r < 0)
@@ -978,12 +1067,14 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
}
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
- struct in_addr address;
- struct in_addr mask;
+ struct in_addr address, mask;
int r;
assert(lease);
+ if (lease->address == 0)
+ return -ENODATA;
+
address.s_addr = lease->address;
/* fall back to the default subnet masks based on address class */
@@ -992,35 +1083,53 @@ int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
return r;
lease->subnet_mask = mask.s_addr;
+ lease->have_subnet_mask = true;
return 0;
}
-int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
- size_t *client_id_len) {
+int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) {
assert_return(lease, -EINVAL);
assert_return(client_id, -EINVAL);
assert_return(client_id_len, -EINVAL);
+ if (!lease->client_id)
+ return -ENODATA;
+
*client_id = lease->client_id;
*client_id_len = lease->client_id_len;
+
return 0;
}
-int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id,
- size_t client_id_len) {
+int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) {
assert_return(lease, -EINVAL);
- assert_return((!client_id && !client_id_len) ||
- (client_id && client_id_len), -EINVAL);
+ assert_return(client_id || client_id_len <= 0, -EINVAL);
+
+ if (client_id_len <= 0)
+ lease->client_id = mfree(lease->client_id);
+ else {
+ void *p;
- free (lease->client_id);
- lease->client_id = NULL;
- lease->client_id_len = 0;
+ p = memdup(client_id, client_id_len);
+ if (!p)
+ return -ENOMEM;
- if (client_id) {
- lease->client_id = memdup (client_id, client_id_len);
+ free(lease->client_id);
+ lease->client_id = p;
lease->client_id_len = client_id_len;
}
return 0;
}
+
+int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
+ assert_return(lease, -EINVAL);
+ assert_return(tz, -EINVAL);
+
+ if (!lease->timezone)
+ return -ENODATA;
+
+ *tz = lease->timezone;
+ return 0;
+}
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
index 5ca76045cb..5f1393c60c 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -31,7 +31,6 @@
#include "udev-util.h"
#endif /* NM_IGNORED */
#include "util.h"
-#include "refcnt.h"
#include "random-util.h"
#include "network-internal.h"
@@ -44,7 +43,7 @@
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
struct sd_dhcp6_client {
- RefCount n_ref;
+ unsigned n_ref;
enum DHCP6State state;
sd_event *event;
@@ -77,6 +76,7 @@ static const uint16_t default_req_opts[] = {
DHCP6_OPTION_DNS_SERVERS,
DHCP6_OPTION_DOMAIN_LIST,
DHCP6_OPTION_NTP_SERVER,
+ DHCP6_OPTION_SNTP_SERVERS,
};
const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
@@ -116,9 +116,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
static int client_start(sd_dhcp6_client *client, enum DHCP6State state);
-int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
- sd_dhcp6_client_cb_t cb, void *userdata)
-{
+int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
assert_return(client, -EINVAL);
client->cb = cb;
@@ -127,8 +125,7 @@ int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
return 0;
}
-int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
-{
+int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
assert_return(client, -EINVAL);
assert_return(interface_index >= -1, -EINVAL);
@@ -137,9 +134,11 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
return 0;
}
-int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
- size_t addr_len, uint16_t arp_type)
-{
+int sd_dhcp6_client_set_mac(
+ sd_dhcp6_client *client,
+ const uint8_t *addr, size_t addr_len,
+ uint16_t arp_type) {
+
assert_return(client, -EINVAL);
assert_return(addr, -EINVAL);
assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
@@ -163,16 +162,17 @@ int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
return 0;
}
-static int client_ensure_duid(sd_dhcp6_client *client)
-{
+static int client_ensure_duid(sd_dhcp6_client *client) {
if (client->duid_len != 0)
return 0;
+
return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
}
-int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
- size_t duid_len)
-{
+int sd_dhcp6_client_set_duid(
+ sd_dhcp6_client *client,
+ uint16_t type,
+ uint8_t *duid, size_t duid_len) {
assert_return(client, -EINVAL);
assert_return(duid, -EINVAL);
assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
@@ -206,8 +206,7 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
return 0;
}
-int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,
- bool enabled) {
+int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, bool enabled) {
assert_return(client, -EINVAL);
client->information_request = enabled;
@@ -215,8 +214,7 @@ int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client,
return 0;
}
-int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,
- bool *enabled) {
+int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, bool *enabled) {
assert_return(client, -EINVAL);
assert_return(enabled, -EINVAL);
@@ -225,8 +223,7 @@ int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client,
return 0;
}
-int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
- uint16_t option) {
+int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
size_t t;
assert_return(client, -EINVAL);
@@ -263,7 +260,7 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
if (!client->lease)
return -ENOMSG;
- *ret = sd_dhcp6_lease_ref(client->lease);
+ *ret = client->lease;
return 0;
}
@@ -276,6 +273,11 @@ static void client_notify(sd_dhcp6_client *client, int event) {
static int client_reset(sd_dhcp6_client *client) {
assert_return(client, -EINVAL);
+ if (client->lease) {
+ dhcp6_lease_clear_timers(&client->lease->ia);
+ client->lease = sd_dhcp6_lease_unref(client->lease);
+ }
+
client->receive_message =
sd_event_source_unref(client->receive_message);
@@ -752,7 +754,36 @@ static int client_parse_message(sd_dhcp6_client *client,
return r;
break;
+
+ case DHCP6_OPTION_DNS_SERVERS:
+ r = dhcp6_lease_set_dns(lease, optval, optlen);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case DHCP6_OPTION_DOMAIN_LIST:
+ r = dhcp6_lease_set_domains(lease, optval, optlen);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case DHCP6_OPTION_NTP_SERVER:
+ r = dhcp6_lease_set_ntp(lease, optval, optlen);
+ if (r < 0)
+ return r;
+
+ break;
+
+ case DHCP6_OPTION_SNTP_SERVERS:
+ r = dhcp6_lease_set_sntp(lease, optval, optlen);
+ if (r < 0)
+ return r;
+
+ break;
}
+
}
if (r == -ENOMSG)
@@ -774,9 +805,7 @@ static int client_parse_message(sd_dhcp6_client *client,
return r;
}
-static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
- size_t len)
-{
+static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) {
int r;
_cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
bool rapid_commit;
@@ -806,16 +835,13 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
client->lease = sd_dhcp6_lease_unref(client->lease);
}
- if (client->state != DHCP6_STATE_INFORMATION_REQUEST) {
- client->lease = lease;
- lease = NULL;
- }
+ client->lease = lease;
+ lease = NULL;
return DHCP6_STATE_BOUND;
}
-static int client_receive_advertise(sd_dhcp6_client *client,
- DHCP6Message *advertise, size_t len) {
+static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) {
int r;
_cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
uint8_t pref_advertise = 0, pref_lease = 0;
@@ -850,8 +876,7 @@ static int client_receive_advertise(sd_dhcp6_client *client,
return r;
}
-static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
- void *userdata) {
+static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
sd_dhcp6_client *client = userdata;
DHCP6_CLIENT_DONT_DESTROY(client);
_cleanup_free_ DHCP6Message *message = NULL;
@@ -962,8 +987,7 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
return 0;
}
-static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
-{
+static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
int r;
usec_t timeout, time_now;
char time_string[FORMAT_TIMESPAN_MAX];
@@ -1092,15 +1116,13 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
return 0;
}
-int sd_dhcp6_client_stop(sd_dhcp6_client *client)
-{
+int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
client_stop(client, DHCP6_EVENT_STOP);
return 0;
}
-int sd_dhcp6_client_start(sd_dhcp6_client *client)
-{
+int sd_dhcp6_client_start(sd_dhcp6_client *client) {
int r = 0;
enum DHCP6State state = DHCP6_STATE_SOLICITATION;
@@ -1156,9 +1178,7 @@ error:
return r;
}
-int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
- int priority)
-{
+int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int priority) {
int r;
assert_return(client, -EINVAL);
@@ -1193,30 +1213,39 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
}
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
- if (client)
- assert_se(REFCNT_INC(client->n_ref) >= 2);
+
+ if (!client)
+ return NULL;
+
+ assert(client->n_ref >= 1);
+ client->n_ref++;
return client;
}
sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
- if (client && REFCNT_DEC(client->n_ref) == 0) {
- client_reset(client);
- sd_dhcp6_client_detach_event(client);
- sd_dhcp6_lease_unref(client->lease);
+ if (!client)
+ return NULL;
- free(client->req_opts);
- free(client);
+ assert(client->n_ref >= 1);
+ client->n_ref--;
+ if (client->n_ref > 0)
return NULL;
- }
- return client;
+ client_reset(client);
+
+ sd_dhcp6_client_detach_event(client);
+ sd_dhcp6_lease_unref(client->lease);
+
+ free(client->req_opts);
+ free(client);
+
+ return NULL;
}
-int sd_dhcp6_client_new(sd_dhcp6_client **ret)
-{
+int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
_cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
size_t t;
@@ -1226,7 +1255,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)
if (!client)
return -ENOMEM;
- client->n_ref = REFCNT_INIT;
+ client->n_ref = 1;
client->ia_na.type = DHCP6_OPTION_IA_NA;
diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
index 8ac18a7566..a6922f78e7 100644
--- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c
@@ -1,8 +1,10 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
/***
This file is part of systemd.
Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -22,9 +24,11 @@
#include <errno.h>
+#include "strv.h"
#include "util.h"
#include "dhcp6-lease-internal.h"
+#include "dhcp6-protocol.h"
int dhcp6_lease_clear_timers(DHCP6IA *ia) {
assert_return(ia, -EINVAL);
@@ -175,20 +179,221 @@ void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease) {
lease->addr_iter = lease->ia.addresses;
}
+int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
+ int r;
+
+ assert_return(lease, -EINVAL);
+ assert_return(optval, -EINVAL);
+
+ if (!optlen)
+ return 0;
+
+ r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->dns,
+ lease->dns_count,
+ &lease->dns_allocated);
+ if (r < 0) {
+ log_dhcp6_client(client, "Invalid DNS server option: %s",
+ strerror(-r));
+
+ return r;
+ }
+
+ lease->dns_count = r;
+
+ return 0;
+}
+
+int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs) {
+ assert_return(lease, -EINVAL);
+ assert_return(addrs, -EINVAL);
+
+ if (lease->dns_count) {
+ *addrs = lease->dns;
+ return lease->dns_count;
+ }
+
+ return -ENOENT;
+}
+
+int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
+ size_t optlen) {
+ int r;
+ char **domains;
+
+ assert_return(lease, -EINVAL);
+ assert_return(optval, -EINVAL);
+
+ if (!optlen)
+ return 0;
+
+ r = dhcp6_option_parse_domainname(optval, optlen, &domains);
+ if (r < 0)
+ return 0;
+
+ free(lease->domains);
+ lease->domains = domains;
+ lease->domains_count = r;
+
+ return r;
+}
+
+int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) {
+ assert_return(lease, -EINVAL);
+ assert_return(domains, -EINVAL);
+
+ if (lease->domains_count) {
+ *domains = lease->domains;
+ return lease->domains_count;
+ }
+
+ return -ENOENT;
+}
+
+int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
+ int r;
+ uint16_t subopt;
+ size_t sublen;
+ uint8_t *subval;
+
+ assert_return(lease, -EINVAL);
+ assert_return(optval, -EINVAL);
+
+ free(lease->ntp);
+ lease->ntp_count = 0;
+ lease->ntp_allocated = 0;
+
+ while ((r = dhcp6_option_parse(&optval, &optlen, &subopt, &sublen,
+ &subval)) >= 0) {
+ int s;
+ char **servers;
+
+ switch(subopt) {
+ case DHCP6_NTP_SUBOPTION_SRV_ADDR:
+ case DHCP6_NTP_SUBOPTION_MC_ADDR:
+ if (sublen != 16)
+ return 0;
+
+ s = dhcp6_option_parse_ip6addrs(subval, sublen,
+ &lease->ntp,
+ lease->ntp_count,
+ &lease->ntp_allocated);
+ if (s < 0)
+ return s;
+
+ lease->ntp_count = s;
+
+ break;
+
+ case DHCP6_NTP_SUBOPTION_SRV_FQDN:
+ r = dhcp6_option_parse_domainname(subval, sublen,
+ &servers);
+ if (r < 0)
+ return 0;
+
+ lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
+ lease->ntp_fqdn = servers;
+ lease->ntp_fqdn_count = r;
+
+ break;
+ }
+ }
+
+ if (r != -ENOMSG)
+ return r;
+
+ return 0;
+}
+
+int dhcp6_lease_set_sntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
+ int r;
+
+ assert_return(lease, -EINVAL);
+ assert_return(optval, -EINVAL);
+
+ if (!optlen)
+ return 0;
+
+ if (lease->ntp || lease->ntp_fqdn) {
+ log_dhcp6_client(client, "NTP information already provided");
+
+ return 0;
+ }
+
+ log_dhcp6_client(client, "Using deprecated SNTP information");
+
+ r = dhcp6_option_parse_ip6addrs(optval, optlen, &lease->ntp,
+ lease->ntp_count,
+ &lease->ntp_allocated);
+ if (r < 0) {
+ log_dhcp6_client(client, "Invalid SNTP server option: %s",
+ strerror(-r));
+
+ return r;
+ }
+
+ lease->ntp_count = r;
+
+ return 0;
+}
+
+int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease,
+ struct in6_addr **addrs) {
+ assert_return(lease, -EINVAL);
+ assert_return(addrs, -EINVAL);
+
+ if (lease->ntp_count) {
+ *addrs = lease->ntp;
+ return lease->ntp_count;
+ }
+
+ return -ENOENT;
+}
+
+int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
+ assert_return(lease, -EINVAL);
+ assert_return(ntp_fqdn, -EINVAL);
+
+ if (lease->ntp_fqdn_count) {
+ *ntp_fqdn = lease->ntp_fqdn;
+ return lease->ntp_fqdn_count;
+ }
+
+ return -ENOENT;
+}
+
sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
- if (lease)
- assert_se(REFCNT_INC(lease->n_ref) >= 2);
+
+ if (!lease)
+ return NULL;
+
+ assert(lease->n_ref >= 1);
+ lease->n_ref++;
return lease;
}
sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
- if (lease && REFCNT_DEC(lease->n_ref) == 0) {
- free(lease->serverid);
- dhcp6_lease_free_ia(&lease->ia);
- free(lease);
- }
+ if (!lease)
+ return NULL;
+
+ assert(lease->n_ref >= 1);
+ lease->n_ref--;
+
+ if (lease->n_ref > 0)
+ return NULL;
+
+ free(lease->serverid);
+ dhcp6_lease_free_ia(&lease->ia);
+
+ free(lease->dns);
+
+ lease->domains = strv_free(lease->domains);
+
+ free(lease->ntp);
+
+ lease->ntp_fqdn = strv_free(lease->ntp_fqdn);
+ free(lease);
return NULL;
}
@@ -200,7 +405,7 @@ int dhcp6_lease_new(sd_dhcp6_lease **ret) {
if (!lease)
return -ENOMEM;
- lease->n_ref = REFCNT_INIT;
+ lease->n_ref = 1;
LIST_HEAD_INIT(lease->ia.addresses);
diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
index b0d15ddf8b..d652ea9a2f 100644
--- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c
@@ -28,7 +28,6 @@
#include "util.h"
#include "siphash24.h"
#include "list.h"
-#include "refcnt.h"
#include "random-util.h"
#include "ipv4ll-internal.h"
@@ -70,7 +69,7 @@ typedef enum IPv4LLState {
} IPv4LLState;
struct sd_ipv4ll {
- RefCount n_ref;
+ unsigned n_ref;
IPv4LLState state;
int index;
@@ -466,9 +465,8 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address){
assert_return(ll, -EINVAL);
assert_return(address, -EINVAL);
- if (ll->claimed_address == 0) {
+ if (ll->claimed_address == 0)
return -ENOENT;
- }
address->s_addr = ll->claimed_address;
return 0;
@@ -600,30 +598,39 @@ int sd_ipv4ll_stop(sd_ipv4ll *ll) {
}
sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) {
- if (ll)
- assert_se(REFCNT_INC(ll->n_ref) >= 2);
+
+ if (!ll)
+ return NULL;
+
+ assert(ll->n_ref >= 1);
+ ll->n_ref++;
return ll;
}
sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
- if (ll && REFCNT_DEC(ll->n_ref) == 0) {
- ll->receive_message =
- sd_event_source_unref(ll->receive_message);
- ll->fd = safe_close(ll->fd);
- ll->timer = sd_event_source_unref(ll->timer);
+ if (!ll)
+ return NULL;
- sd_ipv4ll_detach_event(ll);
+ assert(ll->n_ref >= 1);
+ ll->n_ref--;
- free(ll->random_data);
- free(ll->random_data_state);
- free(ll);
+ if (ll->n_ref > 0)
+ return ll;
- return NULL;
- }
+ ll->receive_message = sd_event_source_unref(ll->receive_message);
+ ll->fd = safe_close(ll->fd);
- return ll;
+ ll->timer = sd_event_source_unref(ll->timer);
+
+ sd_ipv4ll_detach_event(ll);
+
+ free(ll->random_data);
+ free(ll->random_data_state);
+ free(ll);
+
+ return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_ipv4ll*, sd_ipv4ll_unref);
@@ -638,7 +645,7 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) {
if (!ll)
return -ENOMEM;
- ll->n_ref = REFCNT_INIT;
+ ll->n_ref = 1;
ll->state = IPV4LL_STATE_INIT;
ll->index = -1;
ll->fd = -1;
diff --git a/src/systemd/src/shared/dns-domain.c b/src/systemd/src/shared/dns-domain.c
index 34ec45f22d..c95654f299 100644
--- a/src/systemd/src/shared/dns-domain.c
+++ b/src/systemd/src/shared/dns-domain.c
@@ -310,14 +310,14 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
#endif
}
-int dns_name_normalize(const char *s, char **_ret) {
+int dns_name_concat(const char *a, const char *b, char **_ret) {
_cleanup_free_ char *ret = NULL;
size_t n = 0, allocated = 0;
- const char *p = s;
+ const char *p = a;
bool first = true;
int r;
- assert(s);
+ assert(a);
for (;;) {
_cleanup_free_ char *t = NULL;
@@ -330,6 +330,14 @@ int dns_name_normalize(const char *s, char **_ret) {
if (r == 0) {
if (*p != 0)
return -EINVAL;
+
+ if (b) {
+ /* Now continue with the second string, if there is one */
+ p = b;
+ b = NULL;
+ continue;
+ }
+
break;
}
@@ -343,27 +351,29 @@ int dns_name_normalize(const char *s, char **_ret) {
if (r < 0)
return r;
- if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
- return -ENOMEM;
+ if (_ret) {
+ if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
+ return -ENOMEM;
- if (!first)
- ret[n++] = '.';
- else
- first = false;
+ if (!first)
+ ret[n++] = '.';
+ else
+ first = false;
+
+ memcpy(ret + n, t, r);
+ }
- memcpy(ret + n, t, r);
n += r;
}
if (n > DNS_NAME_MAX)
return -EINVAL;
- if (!GREEDY_REALLOC(ret, allocated, n + 1))
- return -ENOMEM;
-
- ret[n] = 0;
-
if (_ret) {
+ if (!GREEDY_REALLOC(ret, allocated, n + 1))
+ return -ENOMEM;
+
+ ret[n] = 0;
*_ret = ret;
ret = NULL;
}
diff --git a/src/systemd/src/shared/dns-domain.h b/src/systemd/src/shared/dns-domain.h
index ad23d99875..89e0901ad4 100644
--- a/src/systemd/src/shared/dns-domain.h
+++ b/src/systemd/src/shared/dns-domain.h
@@ -38,9 +38,17 @@ int dns_label_escape(const char *p, size_t l, char **ret);
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);
-int dns_name_normalize(const char *s, char **_ret);
+int dns_name_concat(const char *a, const char *b, char **ret);
+
+static inline int dns_name_normalize(const char *s, char **ret) {
+ /* dns_name_concat() normalizes as a side-effect */
+ return dns_name_concat(s, NULL, ret);
+}
+
static inline int dns_name_is_valid(const char *s) {
int r;
+
+ /* dns_name_normalize() verifies as a side effect */
r = dns_name_normalize(s, NULL);
if (r == -EINVAL)
return 0;
diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h
index e5678db6d7..834143b696 100644
--- a/src/systemd/src/systemd/sd-dhcp-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp-lease.h
@@ -36,6 +36,9 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease);
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime);
+int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1);
+int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2);
+int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr);
@@ -46,11 +49,10 @@ 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_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, struct sd_dhcp_route **routesgn);
-int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data,
- size_t *data_len);
-int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
- size_t *client_id_len);
+int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes);
+int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len);
+int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
+int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/systemd/src/systemd/sd-dhcp6-lease.h
index 84008cf590..1e6322c718 100644
--- a/src/systemd/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/src/systemd/sd-dhcp6-lease.h
@@ -7,7 +7,7 @@
This file is part of systemd.
Copyright (C) 2014 Tom Gundersen
- Copyright (C) 2014 Intel Corporation. All rights reserved.
+ Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -35,6 +35,12 @@ int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease,
uint32_t *lifetime_preferred,
uint32_t *lifetime_valid);
+int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs);
+int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains);
+int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease,
+ struct in6_addr **addrs);
+int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn);
+
sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease);
sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);
diff --git a/src/systemd/src/systemd/sd-icmp6-nd.h b/src/systemd/src/systemd/sd-icmp6-nd.h
new file mode 100644
index 0000000000..5f5a9217f1
--- /dev/null
+++ b/src/systemd/src/systemd/sd-icmp6-nd.h
@@ -0,0 +1,81 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#ifndef foosdicmp6ndfoo
+#define foosdicmp6ndfoo
+
+/***
+ This file is part of systemd.
+
+ Copyright (C) 2014 Intel Corporation. All rights reserved.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "nm-sd-adapt.h"
+
+#include <net/ethernet.h>
+
+#include "sd-event.h"
+
+enum {
+ ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE = 0,
+ ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT = 1,
+ ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER = 2,
+ ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED = 3,
+ ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED = 4,
+};
+
+typedef struct sd_icmp6_nd sd_icmp6_nd;
+
+typedef void(*sd_icmp6_nd_callback_t)(sd_icmp6_nd *nd, int event,
+ void *userdata);
+
+int sd_icmp6_nd_set_callback(sd_icmp6_nd *nd, sd_icmp6_nd_callback_t cb,
+ void *userdata);
+int sd_icmp6_nd_set_index(sd_icmp6_nd *nd, int interface_index);
+int sd_icmp6_nd_set_mac(sd_icmp6_nd *nd, const struct ether_addr *mac_addr);
+
+int sd_icmp6_nd_attach_event(sd_icmp6_nd *nd, sd_event *event, int priority);
+int sd_icmp6_nd_detach_event(sd_icmp6_nd *nd);
+sd_event *sd_icmp6_nd_get_event(sd_icmp6_nd *nd);
+
+sd_icmp6_nd *sd_icmp6_nd_ref(sd_icmp6_nd *nd);
+sd_icmp6_nd *sd_icmp6_nd_unref(sd_icmp6_nd *nd);
+int sd_icmp6_nd_new(sd_icmp6_nd **ret);
+
+int sd_icmp6_prefix_match(struct in6_addr *prefix, uint8_t prefixlen,
+ struct in6_addr *addr);
+
+int sd_icmp6_ra_get_mtu(sd_icmp6_nd *nd, uint32_t *mtu);
+int sd_icmp6_ra_get_prefixlen(sd_icmp6_nd *nd, const struct in6_addr *addr,
+ uint8_t *prefixlen);
+int sd_icmp6_ra_get_expired_prefix(sd_icmp6_nd *nd, struct in6_addr **addr,
+ uint8_t *prefixlen);
+
+int sd_icmp6_nd_stop(sd_icmp6_nd *nd);
+int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd);
+
+#define SD_ICMP6_ADDRESS_FORMAT_STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+
+#define SD_ICMP6_ADDRESS_FORMAT_VAL(address) \
+ be16toh((address).s6_addr16[0]), \
+ be16toh((address).s6_addr16[1]), \
+ be16toh((address).s6_addr16[2]), \
+ be16toh((address).s6_addr16[3]), \
+ be16toh((address).s6_addr16[4]), \
+ be16toh((address).s6_addr16[5]), \
+ be16toh((address).s6_addr16[6]), \
+ be16toh((address).s6_addr16[7])
+
+#endif