mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 08:20:28 +01:00
systemd: update code from upstream
This is a direct dump from systemd git on 2015-09-16, git commit
ac2896bab6.
======
SYSTEMD_DIR=../systemd
COMMIT=ac2896bab61bd8cd0b8a8b92f8347e2c11a088b5
(
cd "$SYSTEMD_DIR"
git checkout "$COMMIT"
git reset --hard
git clean -fdx
)
git ls-files :/src/systemd/src/ | xargs -d '\n' rm -f
nm_copy_sd() {
mkdir -p "./src/systemd/$(dirname "$1")"
cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/siphash24.c"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/ipv4ll-internal.h"
nm_copy_sd "src/libsystemd-network/ipv4ll-internal.h"
nm_copy_sd "src/libsystemd-network/ipv4ll-network.c"
nm_copy_sd "src/libsystemd-network/ipv4ll-packet.c"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-icmp6-nd.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
This commit is contained in:
parent
8f4e617526
commit
3383d5d0a6
32 changed files with 1565 additions and 718 deletions
|
|
@ -62,16 +62,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;
|
||||
|
|
@ -87,7 +90,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;
|
||||
|
|
@ -96,10 +99,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;
|
||||
|
|
@ -151,6 +156,17 @@ bool is_localhost(const char *hostname) {
|
|||
endswith_no_case(hostname, ".localdomain.");
|
||||
}
|
||||
|
||||
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] = {};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -298,6 +298,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)))
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@
|
|||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
/* 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;
|
||||
|
|
|
|||
|
|
@ -270,15 +270,13 @@ 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -289,7 +287,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)
|
||||
|
|
@ -693,6 +691,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,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);
|
||||
|
|
@ -145,6 +145,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "time-util.h"
|
||||
#include "path-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
usec_t now(clockid_t clock_id) {
|
||||
|
|
@ -36,6 +37,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);
|
||||
|
||||
|
|
@ -88,6 +97,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);
|
||||
|
||||
|
|
@ -103,6 +138,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);
|
||||
|
||||
|
|
@ -945,7 +992,10 @@ bool timezone_is_valid(const char *name) {
|
|||
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++) {
|
||||
|
|
@ -995,3 +1045,30 @@ clockid_t clock_boottime_or_monotonic(void) {
|
|||
|
||||
return clock;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,10 +70,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) ||
|
||||
|
|
@ -86,6 +88,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);
|
||||
|
|
@ -109,3 +113,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);
|
||||
|
|
|
|||
|
|
@ -327,6 +327,33 @@ void close_many(const int fds[], unsigned n_fd) {
|
|||
safe_close(fds[i]);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -373,6 +400,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;
|
||||
|
|
@ -389,13 +429,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;
|
||||
|
|
@ -2176,7 +2214,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
|
||||
|
|
@ -2204,8 +2242,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[] = {
|
||||
|
|
@ -2215,8 +2253,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;
|
||||
|
|
@ -2238,33 +2276,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);
|
||||
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
|
||||
if (l < 0)
|
||||
p += strspn(p, WHITESPACE);
|
||||
if (*p == '-')
|
||||
return -ERANGE;
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(p, &e, 10);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
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 */
|
||||
|
|
@ -2277,27 +2314,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;
|
||||
|
|
@ -3006,21 +3043,6 @@ char* strshorten(char *s, size_t l) {
|
|||
return s;
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
@ -3762,38 +3784,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;
|
||||
|
|
@ -4288,7 +4310,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");
|
||||
|
|
@ -4821,7 +4843,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);
|
||||
|
|
@ -4843,7 +4865,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)
|
||||
|
|
@ -4883,7 +4905,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)
|
||||
|
|
@ -4928,6 +4950,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)
|
||||
|
|
@ -4950,8 +4975,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);
|
||||
|
|
@ -4983,6 +5008,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;
|
||||
|
||||
|
|
@ -5001,15 +5035,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)
|
||||
|
|
@ -5023,6 +5075,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;
|
||||
|
|
@ -5698,7 +5754,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;
|
||||
|
|
@ -5711,13 +5767,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
|
||||
|
|
@ -5729,32 +5791,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;
|
||||
|
||||
|
|
@ -5765,8 +5840,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;
|
||||
|
|
@ -5804,29 +5879,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;
|
||||
|
|
@ -5849,24 +5924,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;
|
||||
|
|
@ -5874,26 +5952,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);
|
||||
|
|
@ -5904,7 +5983,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;
|
||||
|
|
@ -5930,7 +6009,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;
|
||||
|
||||
|
|
@ -6012,7 +6091,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;
|
||||
|
|
@ -6029,7 +6108,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;
|
||||
|
||||
|
|
@ -6045,7 +6124,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);
|
||||
|
||||
|
|
@ -6053,6 +6132,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;
|
||||
|
|
@ -6511,6 +6593,32 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char
|
|||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
char *shell_maybe_quote(const char *s) {
|
||||
const char *p;
|
||||
char *r, *t;
|
||||
|
|
@ -6537,13 +6645,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;
|
||||
|
|
|
|||
|
|
@ -83,7 +83,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);
|
||||
|
|
@ -149,12 +149,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);
|
||||
|
|
@ -363,6 +369,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))
|
||||
|
|
@ -394,8 +403,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);
|
||||
|
|
@ -471,7 +478,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);
|
||||
|
||||
|
|
@ -510,7 +517,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);
|
||||
|
|
@ -563,6 +573,7 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
|
|||
void *arg);
|
||||
|
||||
#define _(String) gettext (String)
|
||||
#define N_(String) String
|
||||
void init_gettext(void);
|
||||
bool is_locale_utf8(void);
|
||||
|
||||
|
|
@ -803,8 +814,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);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
|
|
@ -854,20 +865,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);
|
||||
|
||||
|
|
@ -917,6 +925,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);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
|
|||
const char *name = NULL;
|
||||
uint64_t id;
|
||||
|
||||
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)];
|
||||
|
|
|
|||
|
|
@ -45,10 +45,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,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include <stdint.h>
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
#include "refcnt.h"
|
||||
#include "util.h"
|
||||
#include "list.h"
|
||||
|
||||
|
|
@ -48,54 +47,62 @@ 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);
|
||||
|
||||
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
|
||||
int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
|
||||
#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
|
||||
|
|
|
|||
|
|
@ -140,7 +140,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;
|
||||
|
||||
|
|
@ -199,7 +199,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;
|
||||
|
||||
|
|
@ -214,7 +214,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;
|
||||
|
|
@ -228,20 +228,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -68,6 +68,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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -24,13 +24,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;
|
||||
|
|
@ -40,6 +38,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);
|
||||
|
|
@ -56,6 +65,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);
|
||||
|
|
|
|||
|
|
@ -41,8 +41,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,
|
||||
|
|
@ -92,8 +91,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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -26,9 +26,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
|
||||
|
|
@ -317,3 +319,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,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 */
|
||||
|
||||
|
|
@ -133,6 +133,12 @@ enum {
|
|||
/* option codes 144-65535 are unassigned */
|
||||
};
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "conf-parser.h"
|
||||
#include "condition.h"
|
||||
#include "network-internal.h"
|
||||
#include "sd-icmp6-nd.h"
|
||||
|
||||
const char *net_get_name(struct udev_device *device) {
|
||||
const char *name, *field;
|
||||
|
|
@ -384,6 +385,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;
|
||||
|
|
@ -510,7 +525,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);
|
||||
|
|
@ -526,7 +541,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);
|
||||
|
|
|
|||
|
|
@ -67,6 +67,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 */
|
||||
|
|
@ -75,5 +77,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);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#include <sys/ioctl.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "refcnt.h"
|
||||
#include "random-util.h"
|
||||
#include "async.h"
|
||||
|
||||
|
|
@ -41,7 +40,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;
|
||||
|
|
@ -106,7 +105,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,
|
||||
|
|
@ -348,7 +346,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;
|
||||
}
|
||||
|
|
@ -377,8 +375,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;
|
||||
}
|
||||
|
|
@ -1055,18 +1052,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 "
|
||||
|
|
@ -1168,13 +1163,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);
|
||||
}
|
||||
|
||||
|
|
@ -1206,7 +1205,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) {
|
||||
|
|
@ -1220,7 +1219,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);
|
||||
|
|
@ -1230,7 +1229,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);
|
||||
|
|
@ -1676,30 +1675,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;
|
||||
}
|
||||
|
|
@ -1713,7 +1723,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;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
#include "udev.h"
|
||||
#include "udev-util.h"
|
||||
#include "util.h"
|
||||
#include "refcnt.h"
|
||||
#include "random-util.h"
|
||||
|
||||
#include "network-internal.h"
|
||||
|
|
@ -40,7 +39,7 @@
|
|||
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
|
||||
|
||||
struct sd_dhcp6_client {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
enum DHCP6State state;
|
||||
sd_event *event;
|
||||
|
|
@ -73,6 +72,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] = {
|
||||
|
|
@ -112,9 +112,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;
|
||||
|
|
@ -123,8 +121,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);
|
||||
|
||||
|
|
@ -133,9 +130,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);
|
||||
|
|
@ -159,16 +158,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);
|
||||
|
|
@ -202,8 +202,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;
|
||||
|
|
@ -211,8 +210,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);
|
||||
|
||||
|
|
@ -221,8 +219,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);
|
||||
|
|
@ -259,7 +256,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;
|
||||
}
|
||||
|
|
@ -272,6 +269,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);
|
||||
|
||||
|
|
@ -748,7 +750,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)
|
||||
|
|
@ -770,9 +801,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;
|
||||
|
|
@ -802,16 +831,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;
|
||||
|
|
@ -846,8 +872,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;
|
||||
|
|
@ -958,8 +983,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];
|
||||
|
|
@ -1088,15 +1112,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;
|
||||
|
||||
|
|
@ -1152,9 +1174,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);
|
||||
|
|
@ -1189,30 +1209,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);
|
||||
|
||||
free(client->req_opts);
|
||||
free(client);
|
||||
|
||||
if (!client)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return client;
|
||||
assert(client->n_ref >= 1);
|
||||
client->n_ref--;
|
||||
|
||||
if (client->n_ref > 0)
|
||||
return NULL;
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -1222,7 +1251,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -20,9 +22,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);
|
||||
|
|
@ -173,20 +177,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;
|
||||
}
|
||||
|
|
@ -198,7 +403,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#include "util.h"
|
||||
#include "siphash24.h"
|
||||
#include "list.h"
|
||||
#include "refcnt.h"
|
||||
#include "random-util.h"
|
||||
|
||||
#include "ipv4ll-internal.h"
|
||||
|
|
@ -68,7 +67,7 @@ typedef enum IPv4LLState {
|
|||
} IPv4LLState;
|
||||
|
||||
struct sd_ipv4ll {
|
||||
RefCount n_ref;
|
||||
unsigned n_ref;
|
||||
|
||||
IPv4LLState state;
|
||||
int index;
|
||||
|
|
@ -464,9 +463,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;
|
||||
|
|
@ -598,30 +596,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);
|
||||
|
||||
sd_ipv4ll_detach_event(ll);
|
||||
|
||||
free(ll->random_data);
|
||||
free(ll->random_data_state);
|
||||
free(ll);
|
||||
|
||||
if (!ll)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ll;
|
||||
assert(ll->n_ref >= 1);
|
||||
ll->n_ref--;
|
||||
|
||||
if (ll->n_ref > 0)
|
||||
return ll;
|
||||
|
||||
ll->receive_message = sd_event_source_unref(ll->receive_message);
|
||||
ll->fd = safe_close(ll->fd);
|
||||
|
||||
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);
|
||||
|
|
@ -636,7 +643,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;
|
||||
|
|
|
|||
|
|
@ -308,14 +308,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;
|
||||
|
|
@ -328,6 +328,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;
|
||||
}
|
||||
|
||||
|
|
@ -341,27 +349,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,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;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,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);
|
||||
|
|
@ -44,13 +47,9 @@ 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_save(sd_dhcp_lease *lease, const char *lease_file);
|
||||
int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -33,6 +33,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);
|
||||
|
||||
|
|
|
|||
79
src/systemd/src/systemd/sd-icmp6-nd.h
Normal file
79
src/systemd/src/systemd/sd-icmp6-nd.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*-*- 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 <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
|
||||
Loading…
Add table
Reference in a new issue