systemd: merge branch systemd into master

This commit is contained in:
Thomas Haller 2020-04-08 09:03:31 +02:00
commit c3969425ec
22 changed files with 359 additions and 58 deletions

View file

@ -1937,6 +1937,8 @@ shared_systemd_libnm_systemd_shared_la_SOURCES = \
shared/systemd/src/basic/util.h \
shared/systemd/src/shared/dns-domain.c \
shared/systemd/src/shared/dns-domain.h \
shared/systemd/src/shared/web-util.c \
shared/systemd/src/shared/web-util.h \
$(NULL)
shared_systemd_libnm_systemd_shared_la_LIBADD = \

View file

@ -232,6 +232,7 @@ sources = files(
'systemd/src/basic/utf8.c',
'systemd/src/basic/util.c',
'systemd/src/shared/dns-domain.c',
'systemd/src/shared/web-util.c',
)
incs = include_directories(

View file

@ -184,10 +184,13 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri
int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
int cg_get_keyed_attribute(const char *controller, const char *path, const char *attribute, char **keys, char **values);
int cg_get_attribute_as_uint64(const char *controller, const char *path, const char *attribute, uint64_t *ret);
int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
int cg_get_xattr_malloc(const char *controller, const char *path, const char *name, char **ret);
int cg_remove_xattr(const char *controller, const char *path, const char *name);
int cg_install_release_agent(const char *controller, const char *agent);

View file

@ -56,6 +56,44 @@ int fdopen_unlocked(int fd, const char *options, FILE **ret) {
return 0;
}
int take_fdopen_unlocked(int *fd, const char *options, FILE **ret) {
int r;
assert(fd);
r = fdopen_unlocked(*fd, options, ret);
if (r < 0)
return r;
*fd = -1;
return 0;
}
FILE* take_fdopen(int *fd, const char *options) {
assert(fd);
FILE *f = fdopen(*fd, options);
if (!f)
return NULL;
*fd = -1;
return f;
}
DIR* take_fdopendir(int *dfd) {
assert(dfd);
DIR *d = fdopendir(*dfd);
if (!d)
return NULL;
*dfd = -1;
return d;
}
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) {
FILE *f = open_memstream(ptr, sizeloc);
if (!f)

View file

@ -39,6 +39,9 @@ typedef enum {
int fopen_unlocked(const char *path, const char *options, FILE **ret);
int fdopen_unlocked(int fd, const char *options, FILE **ret);
int take_fdopen_unlocked(int *fd, const char *options, FILE **ret);
FILE* take_fdopen(int *fd, const char *options);
DIR* take_fdopendir(int *dfd);
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc);
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode);

View file

@ -59,9 +59,12 @@ void log_show_color(bool b);
bool log_get_show_color(void) _pure_;
void log_show_location(bool b);
bool log_get_show_location(void) _pure_;
void log_show_time(bool b);
bool log_get_show_time(void) _pure_;
int log_show_color_from_string(const char *e);
int log_show_location_from_string(const char *e);
int log_show_time_from_string(const char *e);
LogTarget log_get_target(void) _pure_;
#if 0 /* NM_IGNORED */
@ -77,7 +80,7 @@ int log_get_max_level_realm(LogRealm realm) _pure_;
#if 0 /* NM_IGNORED */
assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1);
#define PROJECT_FILE (__FILE__ + STRLEN(RELATIVE_SOURCE_PATH) + 1)
#define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1])
#endif /* NM_IGNORED */
#define PROJECT_FILE __FILE__

View file

@ -1188,6 +1188,11 @@ int must_be_root(void) {
return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Need to be root.");
}
static void restore_sigsetp(sigset_t **ssp) {
if (*ssp)
(void) sigprocmask(SIG_SETMASK, *ssp, NULL);
}
int safe_fork_full(
const char *name,
const int except_fds[],
@ -1197,7 +1202,8 @@ int safe_fork_full(
pid_t original_pid, pid;
sigset_t saved_ss, ss;
bool block_signals = false;
_cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
bool block_signals = false, block_all = false;
int prio, r;
/* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
@ -1212,7 +1218,7 @@ int safe_fork_full(
* be sure that SIGTERMs are not lost we might send to the child. */
assert_se(sigfillset(&ss) >= 0);
block_signals = true;
block_signals = block_all = true;
} else if (flags & FORK_WAIT) {
/* Let's block SIGCHLD at least, so that we can safely watch for the child process */
@ -1222,28 +1228,31 @@ int safe_fork_full(
block_signals = true;
}
if (block_signals)
if (block_signals) {
if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
return log_full_errno(prio, errno, "Failed to set signal mask: %m");
saved_ssp = &saved_ss;
}
if (flags & FORK_NEW_MOUNTNS)
pid = raw_clone(SIGCHLD|CLONE_NEWNS);
else
pid = fork();
if (pid < 0) {
r = -errno;
if (block_signals) /* undo what we did above */
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
return log_full_errno(prio, r, "Failed to fork: %m");
}
if (pid < 0)
return log_full_errno(prio, errno, "Failed to fork: %m");
if (pid > 0) {
/* We are in the parent process */
log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
if (flags & FORK_WAIT) {
if (block_all) {
/* undo everything except SIGCHLD */
ss = saved_ss;
assert_se(sigaddset(&ss, SIGCHLD) >= 0);
(void) sigprocmask(SIG_SETMASK, &ss, NULL);
}
r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
if (r < 0)
return r;
@ -1251,9 +1260,6 @@ int safe_fork_full(
return -EPROTO;
}
if (block_signals) /* undo what we did above */
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
if (ret_pid)
*ret_pid = pid;
@ -1262,6 +1268,9 @@ int safe_fork_full(
/* We are in the child process */
/* Restore signal mask manually */
saved_ssp = NULL;
if (flags & FORK_REOPEN_LOG) {
/* Close the logs if requested, before we log anything. And make sure we reopen it if needed. */
log_close();

View file

@ -12,6 +12,7 @@
#include "alloc-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "macro.h"
#include "missing_fs.h"
@ -82,10 +83,9 @@ int dir_is_empty_at(int dir_fd, const char *path) {
if (fd < 0)
return -errno;
d = fdopendir(fd);
d = take_fdopendir(&fd);
if (!d)
return -errno;
fd = -1;
FOREACH_DIRENT(de, d, return -errno)
return 0;

View file

@ -115,7 +115,7 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
bool escaped = false;
int n;
for (n=0; s[n]; n++) {
for (n = 0; s[n] != '\0'; n++) {
if (escaped)
escaped = false;
else if (s[n] == '\\')
@ -124,50 +124,62 @@ static size_t strcspn_escaped(const char *s, const char *reject) {
break;
}
/* if s ends in \, return index of previous char */
return n - escaped;
return n;
}
/* Split a string into words. */
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags) {
const char* split(
const char **state,
size_t *l,
const char *separator,
SplitFlags flags) {
const char *current;
assert(state);
assert(l);
if (!separator)
separator = WHITESPACE;
current = *state;
if (!*current) {
assert(**state == '\0');
if (*current == '\0') /* already at the end? */
return NULL;
}
current += strspn(current, separator);
if (!*current) {
current += strspn(current, separator); /* skip leading separators */
if (*current == '\0') { /* at the end now? */
*state = current;
return NULL;
}
if (flags & SPLIT_QUOTES && strchr("\'\"", *current)) {
char quotechars[2] = {*current, '\0'};
if (FLAGS_SET(flags, SPLIT_QUOTES)) {
*l = strcspn_escaped(current + 1, quotechars);
if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
(current[*l + 2] && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end */
if (flags & SPLIT_RELAX) {
*state = current + *l + 1 + (current[*l + 1] != '\0');
return current + 1;
if (strchr(QUOTES, *current)) {
/* We are looking at a quote */
*l = strcspn_escaped(current + 1, CHAR_TO_STR(*current));
if (current[*l + 1] != *current ||
(current[*l + 2] != 0 && !strchr(separator, current[*l + 2]))) {
/* right quote missing or garbage at the end */
if (FLAGS_SET(flags, SPLIT_RELAX)) {
*state = current + *l + 1 + (current[*l + 1] != '\0');
return current + 1;
}
*state = current;
return NULL;
}
*state = current;
return NULL;
*state = current++ + *l + 2;
} else {
/* We are looking at a something that is not a quote */
*l = strcspn_escaped(current, separator);
if (current[*l] && !strchr(separator, current[*l]) && !FLAGS_SET(flags, SPLIT_RELAX)) {
/* unfinished escape */
*state = current;
return NULL;
}
*state = current + *l;
}
*state = current++ + *l + 2;
} else if (flags & SPLIT_QUOTES) {
*l = strcspn_escaped(current, separator);
if (current[*l] && !strchr(separator, current[*l]) && !(flags & SPLIT_RELAX)) {
/* unfinished escape */
*state = current;
return NULL;
}
*state = current + *l;
} else {
*l = strcspn(current, separator);
*state = current + *l;

View file

@ -112,8 +112,10 @@ typedef enum SplitFlags {
SPLIT_RELAX = 0x01 << 1,
} SplitFlags;
/* Smelly. Do not use this anymore. Use extract_first_word() instead! */
const char* split(const char **state, size_t *l, const char *separator, SplitFlags flags);
/* Similar, don't use this anymore */
#define FOREACH_WORD(word, length, s, state) \
_FOREACH_WORD(word, length, s, WHITESPACE, 0, state)

View file

@ -87,6 +87,16 @@ char **strv_parse_nulstr(const char *s, size_t l);
char **strv_split_nulstr(const char *s);
int strv_make_nulstr(char * const *l, char **p, size_t *n);
static inline int strv_from_nulstr(char ***a, const char *nulstr) {
char **t;
t = strv_split_nulstr(nulstr);
if (!t)
return -ENOMEM;
*a = t;
return 0;
}
bool strv_overlap(char * const *a, char * const *b) _pure_;
#define STRV_FOREACH(s, l) \

View file

@ -50,14 +50,12 @@ int fopen_temporary(const char *path, FILE **ret_f, char **ret_temp_path) {
/* This assumes that returned FILE object is short-lived and used within the same single-threaded
* context and never shared externally, hence locking is not necessary. */
r = fdopen_unlocked(fd, "w", &f);
r = take_fdopen_unlocked(&fd, "w", &f);
if (r < 0) {
(void) unlink(t);
return r;
}
TAKE_FD(fd);
if (ret_f)
*ret_f = TAKE_PTR(f);
@ -83,18 +81,16 @@ int mkostemp_safe(char *pattern) {
#if 0 /* NM_IGNORED */
int fmkostemp_safe(char *pattern, const char *mode, FILE **ret_f) {
int fd;
_cleanup_close_ int fd = -1;
FILE *f;
fd = mkostemp_safe(pattern);
if (fd < 0)
return fd;
f = fdopen(fd, mode);
if (!f) {
safe_close(fd);
f = take_fdopen(&fd, mode);
if (!f)
return -errno;
}
*ret_f = f;
return 0;

View file

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "nm-sd-adapt-shared.h"
#include <stdbool.h>
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
#include "web-util.h"
#if 0 /* NM_IGNORED */
bool http_etag_is_valid(const char *etag) {
if (isempty(etag))
return false;
if (!endswith(etag, "\""))
return false;
if (!STARTSWITH_SET(etag, "\"", "W/\""))
return false;
return true;
}
#endif /* NM_IGNORED */
bool http_url_is_valid(const char *url) {
const char *p;
if (isempty(url))
return false;
p = STARTSWITH_SET(url, "http://", "https://");
if (!p)
return false;
if (isempty(p))
return false;
return ascii_is_valid(p);
}
#if 0 /* NM_IGNORED */
bool documentation_url_is_valid(const char *url) {
const char *p;
if (isempty(url))
return false;
if (http_url_is_valid(url))
return true;
p = STARTSWITH_SET(url, "file:/", "info:", "man:");
if (isempty(p))
return false;
return ascii_is_valid(p);
}
#endif /* NM_IGNORED */

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
#include "macro.h"
bool http_url_is_valid(const char *url) _pure_;
bool documentation_url_is_valid(const char *url) _pure_;
bool http_etag_is_valid(const char *etag);

View file

@ -61,6 +61,12 @@ struct sd_dhcp_lease {
struct in_addr *sip;
size_t sip_size;
struct in_addr *pop3_server;
size_t pop3_server_size;
struct in_addr *smtp_server;
size_t smtp_server_size;
struct sd_dhcp_route *static_route;
size_t static_route_size, static_route_allocated;

View file

@ -8,7 +8,6 @@
#include "sd-dhcp-lease.h"
#include "conf-parser.h"
#include "def.h"
#include "set.h"
#include "strv.h"
@ -67,5 +66,3 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
#define NETWORK_DIRS ((const char* const*) CONF_PATHS_STRV("systemd/network"))

View file

@ -29,6 +29,7 @@
#include "random-util.h"
#include "string-util.h"
#include "strv.h"
#include "web-util.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
@ -85,6 +86,7 @@ struct sd_dhcp_client {
size_t client_id_len;
char *hostname;
char *vendor_class_identifier;
char *mudurl;
char **user_class;
uint32_t mtu;
uint32_t xid;
@ -498,6 +500,18 @@ int sd_dhcp_client_set_vendor_class_identifier(
return free_and_strdup(&client->vendor_class_identifier, vci);
}
int sd_dhcp_client_set_mud_url(
sd_dhcp_client *client,
const char *mudurl) {
assert_return(client, -EINVAL);
assert_return(mudurl, -EINVAL);
assert_return(strlen(mudurl) <= 255, -EINVAL);
assert_return(http_url_is_valid(mudurl), -EINVAL);
return free_and_strdup(&client->mudurl, mudurl);
}
int sd_dhcp_client_set_user_class(
sd_dhcp_client *client,
const char* const* user_class) {
@ -900,6 +914,15 @@ static int client_send_discover(sd_dhcp_client *client) {
return r;
}
if (client->mudurl) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_MUD_URL,
strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
if (client->user_class) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_USER_CLASS,
@ -1037,6 +1060,16 @@ static int client_send_request(sd_dhcp_client *client) {
return r;
}
if (client->mudurl) {
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_MUD_URL,
strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
@ -2106,6 +2139,7 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);
free(client->mudurl);
client->user_class = strv_free(client->user_class);
ordered_hashmap_free(client->extra_options);
ordered_hashmap_free(client->vendor_options);

View file

@ -131,6 +131,28 @@ int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) {
return (int) lease->sip_size;
}
int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
if (lease->pop3_server_size <= 0)
return -ENODATA;
*addr = lease->pop3_server;
return (int) lease->pop3_server_size;
}
int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL);
if (lease->smtp_server_size <= 0)
return -ENODATA;
*addr = lease->smtp_server;
return (int) lease->smtp_server_size;
}
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) {
assert_return(lease, -EINVAL);
assert_return(domainname, -EINVAL);
@ -281,6 +303,8 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
free(lease->dns);
free(lease->ntp);
free(lease->sip);
free(lease->pop3_server);
free(lease->smtp_server);
free(lease->static_route);
free(lease->client_id);
free(lease->vendor_specific);
@ -603,6 +627,18 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
log_debug_errno(r, "Failed to parse SIP server, ignoring: %m");
break;
case SD_DHCP_OPTION_POP3_SERVER:
r = lease_parse_in_addrs(option, len, &lease->pop3_server, &lease->pop3_server_size);
if (r < 0)
log_debug_errno(r, "Failed to parse POP3 server, ignoring: %m");
break;
case SD_DHCP_OPTION_SMTP_SERVER:
r = lease_parse_in_addrs(option, len, &lease->smtp_server, &lease->smtp_server_size);
if (r < 0)
log_debug_errno(r, "Failed to parse SMTP server, ignoring: %m");
break;
case SD_DHCP_OPTION_STATIC_ROUTE:
r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
if (r < 0)
@ -1039,6 +1075,8 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
*dns = NULL,
*ntp = NULL,
*sip = NULL,
*pop3_server = NULL,
*smtp_server = NULL,
*mtu = NULL,
*routes = NULL,
*domains = NULL,
@ -1068,6 +1106,8 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"DNS", &dns,
"NTP", &ntp,
"SIP", &sip,
"POP3_SERVERS", &pop3_server,
"SMTP_SERVERS", &smtp_server,
"MTU", &mtu,
"DOMAINNAME", &lease->domainname,
"HOSTNAME", &lease->hostname,
@ -1177,7 +1217,23 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
if (r < 0)
log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip);
else
lease->ntp_size = r;
lease->sip_size = r;
}
if (pop3_server) {
r = deserialize_in_addrs(&lease->pop3_server, pop3_server);
if (r < 0)
log_debug_errno(r, "Failed to deserialize POP3 server %s, ignoring: %m", pop3_server);
else
lease->pop3_server_size = r;
}
if (smtp_server) {
r = deserialize_in_addrs(&lease->smtp_server, smtp_server);
if (r < 0)
log_debug_errno(r, "Failed to deserialize SMTP server %s, ignoring: %m", smtp_server);
else
lease->smtp_server_size = r;
}
if (mtu) {

View file

@ -27,6 +27,7 @@
#include "socket-util.h"
#include "string-table.h"
#include "util.h"
#include "web-util.h"
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
@ -67,6 +68,7 @@ struct sd_dhcp6_client {
size_t req_opts_allocated;
size_t req_opts_len;
char *fqdn;
char *mudurl;
sd_event_source *receive_message;
usec_t retransmit_time;
uint8_t retransmit_count;
@ -369,6 +371,17 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
return 0;
}
int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, char *mudurl) {
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(mudurl, -EINVAL);
assert_return(strlen(mudurl) <= 255, -EINVAL);
assert_return(http_url_is_valid(mudurl), -EINVAL);
return free_and_strdup(&client->mudurl, mudurl);
}
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
assert_return(client, -EINVAL);
assert_return(delegation, -EINVAL);
@ -490,6 +503,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
case DHCP6_STATE_INFORMATION_REQUEST:
message->type = DHCP6_INFORMATION_REQUEST;
if (client->mudurl) {
r = dhcp6_option_append(&opt, &optlen,
SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
break;
case DHCP6_STATE_SOLICITATION:
@ -513,6 +534,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->mudurl) {
r = dhcp6_option_append(&opt, &optlen,
SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
if (r < 0)
@ -551,6 +580,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->mudurl) {
r = dhcp6_option_append(&opt, &optlen,
SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
@ -577,6 +614,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->mudurl) {
r = dhcp6_option_append(&opt, &optlen,
SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl),
client->mudurl);
if (r < 0)
return r;
}
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
if (r < 0)
@ -1527,6 +1572,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
free(client->req_opts);
free(client->fqdn);
free(client->mudurl);
return mfree(client);
}

View file

@ -83,6 +83,8 @@ enum {
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
SD_DHCP_OPTION_SMTP_SERVER = 69,
SD_DHCP_OPTION_POP3_SERVER = 70,
SD_DHCP_OPTION_USER_CLASS = 77,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
@ -90,6 +92,7 @@ enum {
SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119,
SD_DHCP_OPTION_SIP_SERVER = 120,
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
SD_DHCP_OPTION_MUD_URL = 161,
SD_DHCP_OPTION_PRIVATE_BASE = 224,
/* Windows 10 option to send when Anonymize=true */
SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249,
@ -169,6 +172,9 @@ int sd_dhcp_client_set_hostname(
int sd_dhcp_client_set_vendor_class_identifier(
sd_dhcp_client *client,
const char *vci);
int sd_dhcp_client_set_mud_url(
sd_dhcp_client *client,
const char *mudurl);
int sd_dhcp_client_set_user_class(
sd_dhcp_client *client,
const char* const *user_class);

View file

@ -45,6 +45,8 @@ int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *ad
int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu);
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains);

View file

@ -73,6 +73,7 @@ enum {
SD_DHCP6_OPTION_FQDN = 39, /* RFC 4704 */
SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */
SD_DHCP6_OPTION_MUD_URL = 112, /* RFC 8250 */
/* option codes 89-142 are unassigned */
/* option codes 144-65535 are unassigned */
@ -120,6 +121,9 @@ int sd_dhcp6_client_get_information_request(
int sd_dhcp6_client_set_request_option(
sd_dhcp6_client *client,
uint16_t option);
int sd_dhcp6_client_set_request_mud_url(
sd_dhcp6_client *client,
char *mudurl);
int sd_dhcp6_client_set_prefix_delegation_hint(
sd_dhcp6_client *client,
uint8_t prefixlen,