systemd: merge branch 'systemd' into master

This commit is contained in:
Thomas Haller
2016-01-26 17:22:54 +01:00
40 changed files with 909 additions and 536 deletions

View File

@@ -77,6 +77,8 @@ libsystemd_nm_la_SOURCES = \
systemd/src/basic/fileio.h \ systemd/src/basic/fileio.h \
systemd/src/basic/fs-util.c \ systemd/src/basic/fs-util.c \
systemd/src/basic/fs-util.h \ systemd/src/basic/fs-util.h \
systemd/src/basic/hash-funcs.c \
systemd/src/basic/hash-funcs.h \
systemd/src/basic/hashmap.c \ systemd/src/basic/hashmap.c \
systemd/src/basic/hashmap.h \ systemd/src/basic/hashmap.h \
systemd/src/basic/hexdecoct.c \ systemd/src/basic/hexdecoct.c \
@@ -106,6 +108,7 @@ libsystemd_nm_la_SOURCES = \
systemd/src/basic/set.h \ systemd/src/basic/set.h \
systemd/src/basic/socket-util.h \ systemd/src/basic/socket-util.h \
systemd/src/basic/sparse-endian.h \ systemd/src/basic/sparse-endian.h \
systemd/src/basic/stdio-util.h \
systemd/src/basic/string-table.c \ systemd/src/basic/string-table.c \
systemd/src/basic/string-table.h \ systemd/src/basic/string-table.h \
systemd/src/basic/string-util.c \ systemd/src/basic/string-util.c \

View File

@@ -37,18 +37,15 @@
#include "sd-dhcp-client.h" #include "sd-dhcp-client.h"
#include "sd-dhcp6-client.h" #include "sd-dhcp6-client.h"
#include "dhcp-protocol.h"
#include "dhcp-lease-internal.h" #include "dhcp-lease-internal.h"
#include "dhcp6-protocol.h"
#include "dhcp6-lease-internal.h"
G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT) G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
#define NM_DHCP_SYSTEMD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdPrivate)) #define NM_DHCP_SYSTEMD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdPrivate))
typedef struct { typedef struct {
struct sd_dhcp_client *client4; sd_dhcp_client *client4;
struct sd_dhcp6_client *client6; sd_dhcp6_client *client6;
char *lease_file; char *lease_file;
guint request_count; guint request_count;
@@ -61,7 +58,6 @@ typedef struct {
#define DHCP_OPTION_NIS_DOMAIN 40 #define DHCP_OPTION_NIS_DOMAIN 40
#define DHCP_OPTION_NIS_SERVERS 41 #define DHCP_OPTION_NIS_SERVERS 41
#define DHCP_OPTION_DOMAIN_SEARCH 119 #define DHCP_OPTION_DOMAIN_SEARCH 119
#define DHCP_OPTION_RFC3442_ROUTES 121
#define DHCP_OPTION_MS_ROUTES 249 #define DHCP_OPTION_MS_ROUTES 249
#define DHCP_OPTION_WPAD 252 #define DHCP_OPTION_WPAD 252
@@ -87,53 +83,53 @@ typedef struct {
#define REQPREFIX "requested_" #define REQPREFIX "requested_"
static const ReqOption dhcp4_requests[] = { static const ReqOption dhcp4_requests[] = {
{ DHCP_OPTION_SUBNET_MASK, REQPREFIX "subnet_mask", TRUE }, { SD_DHCP_OPTION_SUBNET_MASK, REQPREFIX "subnet_mask", TRUE },
{ DHCP_OPTION_TIME_OFFSET, REQPREFIX "time_offset", TRUE }, { SD_DHCP_OPTION_TIME_OFFSET, REQPREFIX "time_offset", TRUE },
{ DHCP_OPTION_ROUTER, REQPREFIX "routers", TRUE }, { SD_DHCP_OPTION_ROUTER, REQPREFIX "routers", TRUE },
{ DHCP_OPTION_DOMAIN_NAME_SERVER, REQPREFIX "domain_name_servers", TRUE }, { SD_DHCP_OPTION_DOMAIN_NAME_SERVER, REQPREFIX "domain_name_servers", TRUE },
{ DHCP_OPTION_HOST_NAME, REQPREFIX "host_name", TRUE }, { SD_DHCP_OPTION_HOST_NAME, REQPREFIX "host_name", TRUE },
{ DHCP_OPTION_DOMAIN_NAME, REQPREFIX "domain_name", TRUE }, { SD_DHCP_OPTION_DOMAIN_NAME, REQPREFIX "domain_name", TRUE },
{ DHCP_OPTION_INTERFACE_MTU, REQPREFIX "interface_mtu", TRUE }, { SD_DHCP_OPTION_INTERFACE_MTU, REQPREFIX "interface_mtu", TRUE },
{ DHCP_OPTION_BROADCAST, REQPREFIX "broadcast_address", TRUE }, { SD_DHCP_OPTION_BROADCAST, REQPREFIX "broadcast_address", TRUE },
{ DHCP_OPTION_STATIC_ROUTE, REQPREFIX "static_routes", TRUE }, { SD_DHCP_OPTION_STATIC_ROUTE, REQPREFIX "static_routes", TRUE },
{ DHCP_OPTION_NIS_DOMAIN, REQPREFIX "nis_domain", TRUE }, { DHCP_OPTION_NIS_DOMAIN, REQPREFIX "nis_domain", TRUE },
{ DHCP_OPTION_NIS_SERVERS, REQPREFIX "nis_servers", TRUE }, { DHCP_OPTION_NIS_SERVERS, REQPREFIX "nis_servers", TRUE },
{ DHCP_OPTION_NTP_SERVER, REQPREFIX "ntp_servers", TRUE }, { SD_DHCP_OPTION_NTP_SERVER, REQPREFIX "ntp_servers", TRUE },
{ DHCP_OPTION_SERVER_IDENTIFIER, REQPREFIX "dhcp_server_identifier", TRUE }, { SD_DHCP_OPTION_SERVER_IDENTIFIER, REQPREFIX "dhcp_server_identifier", TRUE },
{ DHCP_OPTION_DOMAIN_SEARCH, REQPREFIX "domain_search", TRUE }, { DHCP_OPTION_DOMAIN_SEARCH, REQPREFIX "domain_search", TRUE },
{ DHCP_OPTION_CLASSLESS_STATIC_ROUTE, REQPREFIX "rfc3442_classless_static_routes", TRUE }, { SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, REQPREFIX "rfc3442_classless_static_routes", TRUE },
{ DHCP_OPTION_MS_ROUTES, REQPREFIX "ms_classless_static_routes", TRUE }, { DHCP_OPTION_MS_ROUTES, REQPREFIX "ms_classless_static_routes", TRUE },
{ DHCP_OPTION_WPAD, REQPREFIX "wpad", TRUE }, { DHCP_OPTION_WPAD, REQPREFIX "wpad", TRUE },
/* Internal values */ /* Internal values */
{ DHCP_OPTION_IP_ADDRESS_LEASE_TIME, REQPREFIX "expiry", FALSE }, { SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, REQPREFIX "expiry", FALSE },
{ DHCP_OPTION_CLIENT_IDENTIFIER, REQPREFIX "dhcp_client_identifier", FALSE }, { SD_DHCP_OPTION_CLIENT_IDENTIFIER, REQPREFIX "dhcp_client_identifier", FALSE },
{ DHCP_OPTION_IP_ADDRESS, REQPREFIX "ip_address", FALSE }, { DHCP_OPTION_IP_ADDRESS, REQPREFIX "ip_address", FALSE },
{ 0, NULL, FALSE } { 0, NULL, FALSE }
}; };
static const ReqOption dhcp6_requests[] = { static const ReqOption dhcp6_requests[] = {
{ DHCP6_OPTION_CLIENTID, REQPREFIX "dhcp6_client_id", TRUE }, { SD_DHCP6_OPTION_CLIENTID, REQPREFIX "dhcp6_client_id", TRUE },
/* Don't request server ID by default; some servers don't reply to /* Don't request server ID by default; some servers don't reply to
* Information Requests that request the Server ID. * Information Requests that request the Server ID.
*/ */
{ DHCP6_OPTION_SERVERID, REQPREFIX "dhcp6_server_id", FALSE }, { SD_DHCP6_OPTION_SERVERID, REQPREFIX "dhcp6_server_id", FALSE },
{ DHCP6_OPTION_DNS_SERVERS, REQPREFIX "dhcp6_name_servers", TRUE }, { SD_DHCP6_OPTION_DNS_SERVERS, REQPREFIX "dhcp6_name_servers", TRUE },
{ DHCP6_OPTION_DOMAIN_LIST, REQPREFIX "dhcp6_domain_search", TRUE }, { SD_DHCP6_OPTION_DOMAIN_LIST, REQPREFIX "dhcp6_domain_search", TRUE },
{ DHCP6_OPTION_SNTP_SERVERS, REQPREFIX "dhcp6_sntp_servers", TRUE }, { SD_DHCP6_OPTION_SNTP_SERVERS, REQPREFIX "dhcp6_sntp_servers", TRUE },
/* Internal values */ /* Internal values */
{ DHCP6_OPTION_IP_ADDRESS, REQPREFIX "ip6_address", FALSE }, { DHCP6_OPTION_IP_ADDRESS, REQPREFIX "ip6_address", FALSE },
{ DHCP6_OPTION_PREFIXLEN, REQPREFIX "ip6_prefixlen", FALSE }, { DHCP6_OPTION_PREFIXLEN, REQPREFIX "ip6_prefixlen", FALSE },
{ DHCP6_OPTION_PREFERRED_LIFE, REQPREFIX "preferred_life", FALSE }, { DHCP6_OPTION_PREFERRED_LIFE, REQPREFIX "preferred_life", FALSE },
{ DHCP6_OPTION_MAX_LIFE, REQPREFIX "max_life", FALSE }, { DHCP6_OPTION_MAX_LIFE, REQPREFIX "max_life", FALSE },
{ DHCP6_OPTION_STARTS, REQPREFIX "starts", FALSE }, { DHCP6_OPTION_STARTS, REQPREFIX "starts", FALSE },
{ DHCP6_OPTION_LIFE_STARTS, REQPREFIX "life_starts", FALSE }, { DHCP6_OPTION_LIFE_STARTS, REQPREFIX "life_starts", FALSE },
{ DHCP6_OPTION_RENEW, REQPREFIX "renew", FALSE }, { DHCP6_OPTION_RENEW, REQPREFIX "renew", FALSE },
{ DHCP6_OPTION_REBIND, REQPREFIX "rebind", FALSE }, { DHCP6_OPTION_REBIND, REQPREFIX "rebind", FALSE },
{ DHCP6_OPTION_IAID, REQPREFIX "iaid", FALSE }, { DHCP6_OPTION_IAID, REQPREFIX "iaid", FALSE },
{ 0, NULL, FALSE } { 0, NULL, FALSE }
}; };
@@ -215,7 +211,7 @@ lease_to_ip4_config (const char *iface,
guint32 lifetime = 0, i; guint32 lifetime = 0, i;
NMPlatformIP4Address address; NMPlatformIP4Address address;
GString *l; GString *l;
struct sd_dhcp_route *routes; gs_free sd_dhcp_route **routes = NULL;
guint16 mtu; guint16 mtu;
int r, num; int r, num;
guint64 end_time; guint64 end_time;
@@ -242,7 +238,7 @@ lease_to_ip4_config (const char *iface,
LOG_LEASE (LOGD_DHCP4, " plen %d", address.plen); LOG_LEASE (LOGD_DHCP4, " plen %d", address.plen);
add_option (options, add_option (options,
dhcp4_requests, dhcp4_requests,
DHCP_OPTION_SUBNET_MASK, SD_DHCP_OPTION_SUBNET_MASK,
nm_utils_inet4_ntop (tmp_addr.s_addr, NULL)); nm_utils_inet4_ntop (tmp_addr.s_addr, NULL));
/* Lease time */ /* Lease time */
@@ -253,7 +249,7 @@ lease_to_ip4_config (const char *iface,
LOG_LEASE (LOGD_DHCP4, " expires in %" G_GUINT32_FORMAT " seconds", lifetime); LOG_LEASE (LOGD_DHCP4, " expires in %" G_GUINT32_FORMAT " seconds", lifetime);
add_option_u64 (options, add_option_u64 (options,
dhcp4_requests, dhcp4_requests,
DHCP_OPTION_IP_ADDRESS_LEASE_TIME, SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME,
end_time); end_time);
address.source = NM_IP_CONFIG_SOURCE_DHCP; address.source = NM_IP_CONFIG_SOURCE_DHCP;
@@ -265,7 +261,7 @@ lease_to_ip4_config (const char *iface,
nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr); nm_ip4_config_set_gateway (ip4_config, tmp_addr.s_addr);
str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL); str = nm_utils_inet4_ntop (tmp_addr.s_addr, NULL);
LOG_LEASE (LOGD_DHCP4, " gateway %s", str); LOG_LEASE (LOGD_DHCP4, " gateway %s", str);
add_option (options, dhcp4_requests, DHCP_OPTION_ROUTER, str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str);
} }
/* DNS Servers */ /* DNS Servers */
@@ -281,7 +277,7 @@ lease_to_ip4_config (const char *iface,
} }
} }
if (l->len) if (l->len)
add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME_SERVER, l->str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, l->str);
g_string_free (l, TRUE); g_string_free (l, TRUE);
} }
@@ -297,14 +293,14 @@ lease_to_ip4_config (const char *iface,
nm_ip4_config_add_domain (ip4_config, *s); nm_ip4_config_add_domain (ip4_config, *s);
} }
g_strfreev (domains); g_strfreev (domains);
add_option (options, dhcp4_requests, DHCP_OPTION_DOMAIN_NAME, str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME, str);
} }
/* Hostname */ /* Hostname */
r = sd_dhcp_lease_get_hostname (lease, &str); r = sd_dhcp_lease_get_hostname (lease, &str);
if (r == 0) { if (r == 0) {
LOG_LEASE (LOGD_DHCP4, " hostname '%s'", str); LOG_LEASE (LOGD_DHCP4, " hostname '%s'", str);
add_option (options, dhcp4_requests, DHCP_OPTION_HOST_NAME, str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_HOST_NAME, str);
} }
/* Routes */ /* Routes */
@@ -312,13 +308,23 @@ lease_to_ip4_config (const char *iface,
if (num > 0) { if (num > 0) {
l = g_string_sized_new (30); l = g_string_sized_new (30);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
NMPlatformIP4Route route; NMPlatformIP4Route route = { 0 };
const char *gw_str; const char *gw_str;
guint8 plen;
struct in_addr a;
if (sd_dhcp_route_get_destination (routes[i], &a) < 0)
continue;
route.network = a.s_addr;
if (sd_dhcp_route_get_destination_prefix_length (routes[i], &plen) < 0)
continue;
route.plen = plen;
if (sd_dhcp_route_get_gateway (routes[i], &a) < 0)
continue;
route.gateway = a.s_addr;
memset (&route, 0, sizeof (route));
route.network = routes[i].dst_addr.s_addr;
route.plen = routes[i].dst_prefixlen;
route.gateway = routes[i].gw_addr.s_addr;
route.source = NM_IP_CONFIG_SOURCE_DHCP; route.source = NM_IP_CONFIG_SOURCE_DHCP;
route.metric = default_priority; route.metric = default_priority;
nm_ip4_config_add_route (ip4_config, &route); nm_ip4_config_add_route (ip4_config, &route);
@@ -329,7 +335,7 @@ lease_to_ip4_config (const char *iface,
g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str); g_string_append_printf (l, "%s%s/%d %s", l->len ? " " : "", str, route.plen, gw_str);
} }
add_option (options, dhcp4_requests, DHCP_OPTION_RFC3442_ROUTES, l->str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, l->str);
g_string_free (l, TRUE); g_string_free (l, TRUE);
} }
@@ -337,7 +343,7 @@ lease_to_ip4_config (const char *iface,
r = sd_dhcp_lease_get_mtu (lease, &mtu); r = sd_dhcp_lease_get_mtu (lease, &mtu);
if (r == 0 && mtu) { if (r == 0 && mtu) {
nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
add_option_u32 (options, dhcp4_requests, DHCP_OPTION_INTERFACE_MTU, mtu); add_option_u32 (options, dhcp4_requests, SD_DHCP_OPTION_INTERFACE_MTU, mtu);
LOG_LEASE (LOGD_DHCP4, " mtu %u", mtu); LOG_LEASE (LOGD_DHCP4, " mtu %u", mtu);
} }
@@ -350,7 +356,7 @@ lease_to_ip4_config (const char *iface,
LOG_LEASE (LOGD_DHCP4, " ntp server '%s'", str); LOG_LEASE (LOGD_DHCP4, " ntp server '%s'", str);
g_string_append_printf (l, "%s%s", l->len ? " " : "", str); g_string_append_printf (l, "%s%s", l->len ? " " : "", str);
} }
add_option (options, dhcp4_requests, DHCP_OPTION_NTP_SERVER, l->str); add_option (options, dhcp4_requests, SD_DHCP_OPTION_NTP_SERVER, l->str);
g_string_free (l, TRUE); g_string_free (l, TRUE);
} }

View File

@@ -121,16 +121,18 @@ char *cescape(const char *s) {
return cescape_length(s, strlen(s)); return cescape_length(s, strlen(s));
} }
int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) { int cunescape_one(const char *p, size_t length, uint32_t *ret, bool *eight_bit) {
int r = 1; int r = 1;
assert(p); assert(p);
assert(*p); assert(*p);
assert(ret); assert(ret);
/* Unescapes C style. Returns the unescaped character in ret, /* Unescapes C style. Returns the unescaped character in ret.
* unless we encountered a \u sequence in which case the full * Sets *eight_bit to true if the escaped sequence either fits in
* unicode character is returned in ret_unicode, instead. */ * one byte in UTF-8 or is a non-unicode literal byte and should
* instead be copied directly.
*/
if (length != (size_t) -1 && length < 1) if (length != (size_t) -1 && length < 1)
return -EINVAL; return -EINVAL;
@@ -192,7 +194,8 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
if (a == 0 && b == 0) if (a == 0 && b == 0)
return -EINVAL; return -EINVAL;
*ret = (char) ((a << 4U) | b); *ret = (a << 4U) | b;
*eight_bit = true;
r = 3; r = 3;
break; break;
} }
@@ -219,16 +222,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
if (c == 0) if (c == 0)
return -EINVAL; return -EINVAL;
if (c < 128) *ret = c;
*ret = c;
else {
if (!ret_unicode)
return -EINVAL;
*ret = 0;
*ret_unicode = c;
}
r = 5; r = 5;
break; break;
} }
@@ -260,16 +254,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
if (!unichar_is_valid(c)) if (!unichar_is_valid(c))
return -EINVAL; return -EINVAL;
if (c < 128) *ret = c;
*ret = c;
else {
if (!ret_unicode)
return -EINVAL;
*ret = 0;
*ret_unicode = c;
}
r = 9; r = 9;
break; break;
} }
@@ -311,6 +296,7 @@ int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode
return -EINVAL; return -EINVAL;
*ret = m; *ret = m;
*eight_bit = true;
r = 3; r = 3;
break; break;
} }
@@ -344,7 +330,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
for (f = s, t = r + pl; f < s + length; f++) { for (f = s, t = r + pl; f < s + length; f++) {
size_t remaining; size_t remaining;
uint32_t u; uint32_t u;
char c; bool eight_bit = false;
int k; int k;
remaining = s + length - f; remaining = s + length - f;
@@ -367,7 +353,7 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
return -EINVAL; return -EINVAL;
} }
k = cunescape_one(f + 1, remaining - 1, &c, &u); k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
if (k < 0) { if (k < 0) {
if (flags & UNESCAPE_RELAX) { if (flags & UNESCAPE_RELAX) {
/* Invalid escape code, let's take it literal then */ /* Invalid escape code, let's take it literal then */
@@ -379,14 +365,13 @@ int cunescape_length_with_prefix(const char *s, size_t length, const char *prefi
return k; return k;
} }
if (c != 0)
/* Non-Unicode? Let's encode this directly */
*(t++) = c;
else
/* Unicode? Then let's encode this in UTF-8 */
t += utf8_encode_unichar(t, u);
f += k; f += k;
if (eight_bit)
/* One byte? Set directly as specified */
*(t++) = u;
else
/* Otherwise encode as multi-byte UTF-8 */
t += utf8_encode_unichar(t, u);
} }
*t = 0; *t = 0;

View File

@@ -47,7 +47,7 @@ size_t cescape_char(char c, char *buf);
int cunescape(const char *s, UnescapeFlags flags, char **ret); int cunescape(const char *s, UnescapeFlags flags, char **ret);
int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret); int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret);
int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret); int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret);
int cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode); int cunescape_one(const char *p, size_t length, uint32_t *ret, bool *eight_bit);
char *xescape(const char *s, const char *bad); char *xescape(const char *s, const char *bad);

View File

@@ -75,3 +75,7 @@ int same_fd(int a, int b);
void cmsg_close_all(struct msghdr *mh); void cmsg_close_all(struct msghdr *mh);
bool fdname_is_valid(const char *s); bool fdname_is_valid(const char *s);
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
#define ERRNO_IS_DISCONNECT(r) \
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)

View File

@@ -169,7 +169,7 @@ int read_one_line_file(const char *fn, char **line) {
if (!fgets(t, sizeof(t), f)) { if (!fgets(t, sizeof(t), f)) {
if (ferror(f)) if (ferror(f))
return errno ? -errno : -EIO; return errno > 0 ? -errno : -EIO;
t[0] = 0; t[0] = 0;
} }
@@ -1070,7 +1070,7 @@ int fflush_and_check(FILE *f) {
fflush(f); fflush(f);
if (ferror(f)) if (ferror(f))
return errno ? -errno : -EIO; return errno > 0 ? -errno : -EIO;
return 0; return 0;
} }

View File

@@ -492,7 +492,7 @@ int get_files_in_directory(const char *path, char ***list) {
errno = 0; errno = 0;
de = readdir(d); de = readdir(d);
if (!de && errno != 0) if (!de && errno > 0)
return -errno; return -errno;
if (!de) if (!de)
break; break;

View File

@@ -0,0 +1,85 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2014 Michal Schmidt
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "nm-sd-adapt.h"
#include "hash-funcs.h"
void string_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, strlen(p) + 1, state);
}
int string_compare_func(const void *a, const void *b) {
return strcmp(a, b);
}
const struct hash_ops string_hash_ops = {
.hash = string_hash_func,
.compare = string_compare_func
};
void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state);
}
int trivial_compare_func(const void *a, const void *b) {
return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops trivial_hash_ops = {
.hash = trivial_hash_func,
.compare = trivial_compare_func
};
void uint64_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, sizeof(uint64_t), state);
}
int uint64_compare_func(const void *_a, const void *_b) {
uint64_t a, b;
a = *(const uint64_t*) _a;
b = *(const uint64_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops uint64_hash_ops = {
.hash = uint64_hash_func,
.compare = uint64_compare_func
};
#if SIZEOF_DEV_T != 8
void devt_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, sizeof(dev_t), state);
}
int devt_compare_func(const void *_a, const void *_b) {
dev_t a, b;
a = *(const dev_t*) _a;
b = *(const dev_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops devt_hash_ops = {
.hash = devt_hash_func,
.compare = devt_compare_func
};
#endif

View File

@@ -0,0 +1,69 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
Copyright 2014 Michal Schmidt
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "nm-sd-adapt.h"
#include "macro.h"
#include "siphash24.h"
typedef void (*hash_func_t)(const void *p, struct siphash *state);
typedef int (*compare_func_t)(const void *a, const void *b);
struct hash_ops {
hash_func_t hash;
compare_func_t compare;
};
void string_hash_func(const void *p, struct siphash *state);
int string_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops string_hash_ops;
/* This will compare the passed pointers directly, and will not
* dereference them. This is hence not useful for strings or
* suchlike. */
void trivial_hash_func(const void *p, struct siphash *state);
int trivial_compare_func(const void *a, const void *b) _const_;
extern const struct hash_ops trivial_hash_ops;
/* 32bit values we can always just embed in the pointer itself, but
* in order to support 32bit archs we need store 64bit values
* indirectly, since they don't fit in a pointer. */
void uint64_hash_func(const void *p, struct siphash *state);
int uint64_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops uint64_hash_ops;
/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
* it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
#if SIZEOF_DEV_T != 8
void devt_hash_func(const void *p, struct siphash *state) _pure_;
int devt_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops devt_hash_ops = {
.hash = devt_hash_func,
.compare = devt_compare_func
};
#else
#define devt_hash_func uint64_hash_func
#define devt_compare_func uint64_compare_func
#define devt_hash_ops uint64_hash_ops
#endif

View File

@@ -284,66 +284,6 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = {
}, },
}; };
void string_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, strlen(p) + 1, state);
}
int string_compare_func(const void *a, const void *b) {
return strcmp(a, b);
}
const struct hash_ops string_hash_ops = {
.hash = string_hash_func,
.compare = string_compare_func
};
void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state);
}
int trivial_compare_func(const void *a, const void *b) {
return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops trivial_hash_ops = {
.hash = trivial_hash_func,
.compare = trivial_compare_func
};
void uint64_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, sizeof(uint64_t), state);
}
int uint64_compare_func(const void *_a, const void *_b) {
uint64_t a, b;
a = *(const uint64_t*) _a;
b = *(const uint64_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops uint64_hash_ops = {
.hash = uint64_hash_func,
.compare = uint64_compare_func
};
#if SIZEOF_DEV_T != 8
void devt_hash_func(const void *p, struct siphash *state) {
siphash24_compress(p, sizeof(dev_t), state);
}
int devt_compare_func(const void *_a, const void *_b) {
dev_t a, b;
a = *(const dev_t*) _a;
b = *(const dev_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0);
}
const struct hash_ops devt_hash_ops = {
.hash = devt_hash_func,
.compare = devt_compare_func
};
#endif
static unsigned n_buckets(HashmapBase *h) { static unsigned n_buckets(HashmapBase *h) {
return h->has_indirect ? h->indirect.n_buckets return h->has_indirect ? h->indirect.n_buckets
: hashmap_type_info[h->type].n_direct_buckets; : hashmap_type_info[h->type].n_direct_buckets;

View File

@@ -28,8 +28,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include "hash-funcs.h"
#include "macro.h" #include "macro.h"
#include "siphash24.h"
#include "util.h" #include "util.h"
/* /*
@@ -72,47 +72,6 @@ typedef struct {
#define _IDX_ITERATOR_FIRST (UINT_MAX - 1) #define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
#define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
typedef void (*hash_func_t)(const void *p, struct siphash *state);
typedef int (*compare_func_t)(const void *a, const void *b);
struct hash_ops {
hash_func_t hash;
compare_func_t compare;
};
void string_hash_func(const void *p, struct siphash *state);
int string_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops string_hash_ops;
/* This will compare the passed pointers directly, and will not
* dereference them. This is hence not useful for strings or
* suchlike. */
void trivial_hash_func(const void *p, struct siphash *state);
int trivial_compare_func(const void *a, const void *b) _const_;
extern const struct hash_ops trivial_hash_ops;
/* 32bit values we can always just embedd in the pointer itself, but
* in order to support 32bit archs we need store 64bit values
* indirectly, since they don't fit in a pointer. */
void uint64_hash_func(const void *p, struct siphash *state);
int uint64_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops uint64_hash_ops;
/* On some archs dev_t is 32bit, and on others 64bit. And sometimes
* it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */
#if SIZEOF_DEV_T != 8
void devt_hash_func(const void *p, struct siphash *state) _pure_;
int devt_compare_func(const void *a, const void *b) _pure_;
extern const struct hash_ops devt_hash_ops = {
.hash = devt_hash_func,
.compare = devt_compare_func
};
#else
#define devt_hash_func uint64_hash_func
#define devt_compare_func uint64_compare_func
#define devt_hash_ops uint64_hash_ops
#endif
/* Macros for type checking */ /* Macros for type checking */
#define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \ #define PTR_COMPATIBLE_WITH_HASHMAP_BASE(h) \
(__builtin_types_compatible_p(typeof(h), HashmapBase*) || \ (__builtin_types_compatible_p(typeof(h), HashmapBase*) || \

View File

@@ -221,7 +221,7 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
errno = 0; errno = 0;
if (!inet_ntop(family, u, x, l)) { if (!inet_ntop(family, u, x, l)) {
free(x); free(x);
return errno ? -errno : -EINVAL; return errno > 0 ? -errno : -EINVAL;
} }
*ret = x; *ret = x;
@@ -238,7 +238,7 @@ int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
errno = 0; errno = 0;
if (inet_pton(family, s, ret) <= 0) if (inet_pton(family, s, ret) <= 0)
return errno ? -errno : -EINVAL; return errno > 0 ? -errno : -EINVAL;
return 0; return 0;
} }

View File

@@ -35,6 +35,11 @@ union in_addr_union {
struct in6_addr in6; struct in6_addr in6;
}; };
struct in_addr_data {
int family;
union in_addr_union address;
};
int in_addr_is_null(int family, const union in_addr_union *u); int in_addr_is_null(int family, const union in_addr_union *u);
int in_addr_is_link_local(int family, const union in_addr_union *u); int in_addr_is_link_local(int family, const union in_addr_union *u);
int in_addr_is_localhost(int family, const union in_addr_union *u); int in_addr_is_localhost(int family, const union in_addr_union *u);

View File

@@ -28,6 +28,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/signalfd.h> #include <sys/signalfd.h>
#include <sys/socket.h>
#include <syslog.h> #include <syslog.h>
#include "sd-id128.h" #include "sd-id128.h"
@@ -130,6 +131,15 @@ int log_oom_internal(
int line, int line,
const char *func); const char *func);
int log_format_iovec(
struct iovec *iovec,
unsigned iovec_len,
unsigned *n,
bool newline_separator,
int error,
const char *format,
va_list ap);
/* This modifies the buffer passed! */ /* This modifies the buffer passed! */
int log_dump_internal( int log_dump_internal(
int level, int level,

View File

@@ -331,18 +331,47 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
#define SET_FLAG(v, flag, b) \ #define SET_FLAG(v, flag, b) \
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag)) (v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
#define IN_SET(x, y, ...) \ #define CASE_F(X) case X:
({ \ #define CASE_F_1(CASE, X) CASE_F(X)
static const typeof(y) _array[] = { (y), __VA_ARGS__ }; \ #define CASE_F_2(CASE, X, ...) CASE(X) CASE_F_1(CASE, __VA_ARGS__)
const typeof(y) _x = (x); \ #define CASE_F_3(CASE, X, ...) CASE(X) CASE_F_2(CASE, __VA_ARGS__)
unsigned _i; \ #define CASE_F_4(CASE, X, ...) CASE(X) CASE_F_3(CASE, __VA_ARGS__)
bool _found = false; \ #define CASE_F_5(CASE, X, ...) CASE(X) CASE_F_4(CASE, __VA_ARGS__)
for (_i = 0; _i < ELEMENTSOF(_array); _i++) \ #define CASE_F_6(CASE, X, ...) CASE(X) CASE_F_5(CASE, __VA_ARGS__)
if (_array[_i] == _x) { \ #define CASE_F_7(CASE, X, ...) CASE(X) CASE_F_6(CASE, __VA_ARGS__)
_found = true; \ #define CASE_F_8(CASE, X, ...) CASE(X) CASE_F_7(CASE, __VA_ARGS__)
break; \ #define CASE_F_9(CASE, X, ...) CASE(X) CASE_F_8(CASE, __VA_ARGS__)
} \ #define CASE_F_10(CASE, X, ...) CASE(X) CASE_F_9(CASE, __VA_ARGS__)
_found; \ #define CASE_F_11(CASE, X, ...) CASE(X) CASE_F_10(CASE, __VA_ARGS__)
#define CASE_F_12(CASE, X, ...) CASE(X) CASE_F_11(CASE, __VA_ARGS__)
#define CASE_F_13(CASE, X, ...) CASE(X) CASE_F_12(CASE, __VA_ARGS__)
#define CASE_F_14(CASE, X, ...) CASE(X) CASE_F_13(CASE, __VA_ARGS__)
#define CASE_F_15(CASE, X, ...) CASE(X) CASE_F_14(CASE, __VA_ARGS__)
#define CASE_F_16(CASE, X, ...) CASE(X) CASE_F_15(CASE, __VA_ARGS__)
#define CASE_F_17(CASE, X, ...) CASE(X) CASE_F_16(CASE, __VA_ARGS__)
#define CASE_F_18(CASE, X, ...) CASE(X) CASE_F_17(CASE, __VA_ARGS__)
#define CASE_F_19(CASE, X, ...) CASE(X) CASE_F_18(CASE, __VA_ARGS__)
#define CASE_F_20(CASE, X, ...) CASE(X) CASE_F_19(CASE, __VA_ARGS__)
#define GET_CASE_F(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,NAME,...) NAME
#define FOR_EACH_MAKE_CASE(...) \
GET_CASE_F(__VA_ARGS__,CASE_F_20,CASE_F_19,CASE_F_18,CASE_F_17,CASE_F_16,CASE_F_15,CASE_F_14,CASE_F_13,CASE_F_12,CASE_F_11, \
CASE_F_10,CASE_F_9,CASE_F_8,CASE_F_7,CASE_F_6,CASE_F_5,CASE_F_4,CASE_F_3,CASE_F_2,CASE_F_1) \
(CASE_F,__VA_ARGS__)
#define IN_SET(x, ...) \
({ \
bool _found = false; \
/* If the build breaks in the line below, you need to extend the case macros */ \
static _unused_ char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){__VA_ARGS__})/sizeof(int)]; \
switch(x) { \
FOR_EACH_MAKE_CASE(__VA_ARGS__) \
_found = true; \
break; \
default: \
break; \
} \
_found; \
}) })
/* Define C11 thread_local attribute even on older gcc compiler /* Define C11 thread_local attribute even on older gcc compiler

View File

@@ -85,7 +85,7 @@ int parse_mode(const char *s, mode_t *ret) {
errno = 0; errno = 0;
l = strtol(s, &x, 8); l = strtol(s, &x, 8);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -180,7 +180,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
errno = 0; errno = 0;
l = strtoull(p, &e, 10); l = strtoull(p, &e, 10);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (e == p) if (e == p)
return -EINVAL; return -EINVAL;
@@ -196,7 +196,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
char *e2; char *e2;
l2 = strtoull(e, &e2, 10); l2 = strtoull(e, &e2, 10);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
/* Ignore failure. E.g. 10.M is valid */ /* Ignore failure. E.g. 10.M is valid */
@@ -336,7 +336,7 @@ int safe_atou(const char *s, unsigned *ret_u) {
errno = 0; errno = 0;
l = strtoul(s, &x, 0); l = strtoul(s, &x, 0);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -358,7 +358,7 @@ int safe_atoi(const char *s, int *ret_i) {
errno = 0; errno = 0;
l = strtol(s, &x, 0); l = strtol(s, &x, 0);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -380,7 +380,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
errno = 0; errno = 0;
l = strtoull(s, &x, 0); l = strtoull(s, &x, 0);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -400,7 +400,7 @@ int safe_atolli(const char *s, long long int *ret_lli) {
errno = 0; errno = 0;
l = strtoll(s, &x, 0); l = strtoll(s, &x, 0);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -420,7 +420,7 @@ int safe_atou8(const char *s, uint8_t *ret) {
errno = 0; errno = 0;
l = strtoul(s, &x, 0); l = strtoul(s, &x, 0);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -444,7 +444,7 @@ int safe_atou16(const char *s, uint16_t *ret) {
errno = 0; errno = 0;
l = strtoul(s, &x, 0); l = strtoul(s, &x, 0);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -466,7 +466,7 @@ int safe_atoi16(const char *s, int16_t *ret) {
errno = 0; errno = 0;
l = strtol(s, &x, 0); l = strtol(s, &x, 0);
if (errno != 0) if (errno > 0)
return -errno; return -errno;
if (!x || x == s || *x) if (!x || x == s || *x)
return -EINVAL; return -EINVAL;
@@ -491,7 +491,7 @@ int safe_atod(const char *s, double *ret_d) {
errno = 0; errno = 0;
d = strtod_l(s, &x, loc); d = strtod_l(s, &x, loc);
if (errno != 0) { if (errno > 0) {
freelocale(loc); freelocale(loc);
return -errno; return -errno;
} }

View File

@@ -111,7 +111,7 @@ int path_make_absolute_cwd(const char *p, char **ret) {
cwd = get_current_dir_name(); cwd = get_current_dir_name();
if (!cwd) if (!cwd)
return -errno; return negative_errno();
c = strjoin(cwd, "/", p, NULL); c = strjoin(cwd, "/", p, NULL);
} }

View File

@@ -18,6 +18,8 @@ struct siphash {
void siphash24_init(struct siphash *state, const uint8_t k[16]); void siphash24_init(struct siphash *state, const uint8_t k[16]);
void siphash24_compress(const void *in, size_t inlen, struct siphash *state); void siphash24_compress(const void *in, size_t inlen, struct siphash *state);
#define siphash24_compress_byte(byte, state) siphash24_compress((const uint8_t[]) { (byte) }, 1, (state))
uint64_t siphash24_finalize(struct siphash *state); uint64_t siphash24_finalize(struct siphash *state);
uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]); uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]);

View File

@@ -91,7 +91,7 @@ int socket_address_listen(
mode_t directory_mode, mode_t directory_mode,
mode_t socket_mode, mode_t socket_mode,
const char *label); const char *label);
int make_socket_fd(int log_level, const char* address, int flags); int make_socket_fd(int log_level, const char* address, int type, int flags);
bool socket_address_is(const SocketAddress *a, const char *s, int type); bool socket_address_is(const SocketAddress *a, const char *s, int type);
bool socket_address_is_netlink(const SocketAddress *a, const char *s); bool socket_address_is_netlink(const SocketAddress *a, const char *s);
@@ -107,7 +107,7 @@ bool socket_ipv6_is_supported(void);
int sockaddr_port(const struct sockaddr *_sa) _pure_; int sockaddr_port(const struct sockaddr *_sa) _pure_;
int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret); int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret);
int getpeername_pretty(int fd, char **ret); int getpeername_pretty(int fd, bool include_port, char **ret);
int getsockname_pretty(int fd, char **ret); int getsockname_pretty(int fd, char **ret);
int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret); int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret);

View File

@@ -0,0 +1,80 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "nm-sd-adapt.h"
#include <printf.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include "macro.h"
#define xsprintf(buf, fmt, ...) \
assert_message_se((size_t) snprintf(buf, ELEMENTSOF(buf), fmt, __VA_ARGS__) < ELEMENTSOF(buf), "xsprintf: " #buf "[] must be big enough")
#define VA_FORMAT_ADVANCE(format, ap) \
do { \
int _argtypes[128]; \
size_t _i, _k; \
_k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
assert(_k < ELEMENTSOF(_argtypes)); \
for (_i = 0; _i < _k; _i++) { \
if (_argtypes[_i] & PA_FLAG_PTR) { \
(void) va_arg(ap, void*); \
continue; \
} \
\
switch (_argtypes[_i]) { \
case PA_INT: \
case PA_INT|PA_FLAG_SHORT: \
case PA_CHAR: \
(void) va_arg(ap, int); \
break; \
case PA_INT|PA_FLAG_LONG: \
(void) va_arg(ap, long int); \
break; \
case PA_INT|PA_FLAG_LONG_LONG: \
(void) va_arg(ap, long long int); \
break; \
case PA_WCHAR: \
(void) va_arg(ap, wchar_t); \
break; \
case PA_WSTRING: \
case PA_STRING: \
case PA_POINTER: \
(void) va_arg(ap, void*); \
break; \
case PA_FLOAT: \
case PA_DOUBLE: \
(void) va_arg(ap, double); \
break; \
case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \
(void) va_arg(ap, long double); \
break; \
default: \
assert_not_reached("Unknown format string argument."); \
} \
} \
} while(false)

View File

@@ -49,16 +49,34 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
} }
#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
scope type name##_from_string(const char *s) { \
int b; \
b = parse_boolean(s); \
if (b == 0) \
return (type) 0; \
else if (b > 0) \
return yes; \
return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \
}
#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ #define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \
struct __useless_struct_to_allow_trailing_semicolon__ struct __useless_struct_to_allow_trailing_semicolon__
#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \
_DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \
_DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \
struct __useless_struct_to_allow_trailing_semicolon__
#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) #define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static)
#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) #define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static)
#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,)
/* For string conversions where numbers are also acceptable */ /* For string conversions where numbers are also acceptable */
#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ #define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \
int name##_to_string_alloc(type i, char **str) { \ int name##_to_string_alloc(type i, char **str) { \

View File

@@ -321,18 +321,67 @@ char *truncate_nl(char *s) {
return s; return s;
} }
char ascii_tolower(char x) {
if (x >= 'A' && x <= 'Z')
return x - 'A' + 'a';
return x;
}
char *ascii_strlower(char *t) { char *ascii_strlower(char *t) {
char *p; char *p;
assert(t); assert(t);
for (p = t; *p; p++) for (p = t; *p; p++)
if (*p >= 'A' && *p <= 'Z') *p = ascii_tolower(*p);
*p = *p - 'A' + 'a';
return t; return t;
} }
char *ascii_strlower_n(char *t, size_t n) {
size_t i;
if (n <= 0)
return t;
for (i = 0; i < n; i++)
t[i] = ascii_tolower(t[i]);
return t;
}
int ascii_strcasecmp_n(const char *a, const char *b, size_t n) {
for (; n > 0; a++, b++, n--) {
int x, y;
x = (int) (uint8_t) ascii_tolower(*a);
y = (int) (uint8_t) ascii_tolower(*b);
if (x != y)
return x - y;
}
return 0;
}
int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) {
int r;
r = ascii_strcasecmp_n(a, b, MIN(n, m));
if (r != 0)
return r;
if (n < m)
return -1;
else if (n > m)
return 1;
else
return 0;
}
bool chars_intersect(const char *a, const char *b) { bool chars_intersect(const char *a, const char *b) {
const char *p; const char *p;

View File

@@ -132,7 +132,12 @@ char *strstrip(char *s);
char *delete_chars(char *s, const char *bad); char *delete_chars(char *s, const char *bad);
char *truncate_nl(char *s); char *truncate_nl(char *s);
char *ascii_strlower(char *path); char ascii_tolower(char x);
char *ascii_strlower(char *s);
char *ascii_strlower_n(char *s, size_t n);
int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
bool chars_intersect(const char *a, const char *b) _pure_; bool chars_intersect(const char *a, const char *b) _pure_;

View File

@@ -530,7 +530,7 @@ int on_ac_power(void) {
errno = 0; errno = 0;
de = readdir(d); de = readdir(d);
if (!de && errno != 0) if (!de && errno > 0)
return -errno; return -errno;
if (!de) if (!de)

View File

@@ -36,14 +36,14 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
assert(options); assert(options);
assert(offset); assert(offset);
if (code != DHCP_OPTION_END) if (code != SD_DHCP_OPTION_END)
/* always make sure there is space for an END option */ /* always make sure there is space for an END option */
size --; size --;
switch (code) { switch (code) {
case DHCP_OPTION_PAD: case SD_DHCP_OPTION_PAD:
case DHCP_OPTION_END: case SD_DHCP_OPTION_END:
if (size < *offset + 1) if (size < *offset + 1)
return -ENOBUFS; return -ENOBUFS;
@@ -93,7 +93,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
else if (r == -ENOBUFS && (file || sname)) { else if (r == -ENOBUFS && (file || sname)) {
/* did not fit, but we have more buffers to try /* did not fit, but we have more buffers to try
close the options array and move the offset to its end */ close the options array and move the offset to its end */
r = option_append(message->options, size, offset, DHCP_OPTION_END, 0, NULL); r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
if (r < 0) if (r < 0)
return r; return r;
@@ -114,7 +114,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset,
} else if (r == -ENOBUFS && sname) { } else if (r == -ENOBUFS && sname) {
/* did not fit, but we have more buffers to try /* did not fit, but we have more buffers to try
close the file array and move the offset to its end */ close the file array and move the offset to its end */
r = option_append(message->options, size, offset, DHCP_OPTION_END, 0, NULL); r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL);
if (r < 0) if (r < 0)
return r; return r;
@@ -154,10 +154,10 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
code = options[offset ++]; code = options[offset ++];
switch (code) { switch (code) {
case DHCP_OPTION_PAD: case SD_DHCP_OPTION_PAD:
continue; continue;
case DHCP_OPTION_END: case SD_DHCP_OPTION_END:
return 0; return 0;
} }
@@ -172,7 +172,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
option = &options[offset]; option = &options[offset];
switch (code) { switch (code) {
case DHCP_OPTION_MESSAGE_TYPE: case SD_DHCP_OPTION_MESSAGE_TYPE:
if (len != 1) if (len != 1)
return -EINVAL; return -EINVAL;
@@ -181,7 +181,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
break; break;
case DHCP_OPTION_ERROR_MESSAGE: case SD_DHCP_OPTION_ERROR_MESSAGE:
if (len == 0) if (len == 0)
return -EINVAL; return -EINVAL;
@@ -205,7 +205,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo
} }
break; break;
case DHCP_OPTION_OVERLOAD: case SD_DHCP_OPTION_OVERLOAD:
if (len != 1) if (len != 1)
return -EINVAL; return -EINVAL;

View File

@@ -46,7 +46,7 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
message->magic = htobe32(DHCP_MAGIC_COOKIE); message->magic = htobe32(DHCP_MAGIC_COOKIE);
r = dhcp_option_append(message, optlen, &offset, 0, r = dhcp_option_append(message, optlen, &offset, 0,
DHCP_OPTION_MESSAGE_TYPE, 1, &type); SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type);
if (r < 0) if (r < 0)
return r; return r;

View File

@@ -107,48 +107,6 @@ enum {
DHCP_OVERLOAD_SNAME = 2, DHCP_OVERLOAD_SNAME = 2,
}; };
enum {
DHCP_OPTION_PAD = 0,
DHCP_OPTION_SUBNET_MASK = 1,
DHCP_OPTION_TIME_OFFSET = 2,
DHCP_OPTION_ROUTER = 3,
DHCP_OPTION_DOMAIN_NAME_SERVER = 6,
DHCP_OPTION_HOST_NAME = 12,
DHCP_OPTION_BOOT_FILE_SIZE = 13,
DHCP_OPTION_DOMAIN_NAME = 15,
DHCP_OPTION_ROOT_PATH = 17,
DHCP_OPTION_ENABLE_IP_FORWARDING = 19,
DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20,
DHCP_OPTION_POLICY_FILTER = 21,
DHCP_OPTION_INTERFACE_MDR = 22,
DHCP_OPTION_INTERFACE_TTL = 23,
DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
DHCP_OPTION_INTERFACE_MTU = 26,
DHCP_OPTION_BROADCAST = 28,
DHCP_OPTION_STATIC_ROUTE = 33,
DHCP_OPTION_NTP_SERVER = 42,
DHCP_OPTION_VENDOR_SPECIFIC = 43,
DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
DHCP_OPTION_OVERLOAD = 52,
DHCP_OPTION_MESSAGE_TYPE = 53,
DHCP_OPTION_SERVER_IDENTIFIER = 54,
DHCP_OPTION_PARAMETER_REQUEST_LIST = 55,
DHCP_OPTION_ERROR_MESSAGE = 56,
DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57,
DHCP_OPTION_RENEWAL_T1_TIME = 58,
DHCP_OPTION_REBINDING_T2_TIME = 59,
DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
DHCP_OPTION_CLIENT_IDENTIFIER = 61,
DHCP_OPTION_FQDN = 81,
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,
DHCP_OPTION_END = 255,
};
#define DHCP_MAX_FQDN_LENGTH 255 #define DHCP_MAX_FQDN_LENGTH 255
enum { enum {

View File

@@ -25,6 +25,8 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <string.h> #include <string.h>
#include "sd-dhcp6-client.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "dhcp6-internal.h" #include "dhcp6-internal.h"
#include "dhcp6-protocol.h" #include "dhcp6-protocol.h"
@@ -92,11 +94,11 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
assert_return(buf && *buf && buflen && ia, -EINVAL); assert_return(buf && *buf && buflen && ia, -EINVAL);
switch (ia->type) { switch (ia->type) {
case DHCP6_OPTION_IA_NA: case SD_DHCP6_OPTION_IA_NA:
len = DHCP6_OPTION_IA_NA_LEN; len = DHCP6_OPTION_IA_NA_LEN;
break; break;
case DHCP6_OPTION_IA_TA: case SD_DHCP6_OPTION_IA_TA:
len = DHCP6_OPTION_IA_TA_LEN; len = DHCP6_OPTION_IA_TA_LEN;
break; break;
@@ -119,7 +121,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
*buflen -= len; *buflen -= len;
LIST_FOREACH(addresses, addr, ia->addresses) { LIST_FOREACH(addresses, addr, ia->addresses) {
r = option_append_hdr(buf, buflen, DHCP6_OPTION_IAADDR, r = option_append_hdr(buf, buflen, SD_DHCP6_OPTION_IAADDR,
sizeof(addr->iaaddr)); sizeof(addr->iaaddr));
if (r < 0) if (r < 0)
return r; return r;
@@ -198,7 +200,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
assert_return(!ia->addresses, -EINVAL); assert_return(!ia->addresses, -EINVAL);
switch (iatype) { switch (iatype) {
case DHCP6_OPTION_IA_NA: case SD_DHCP6_OPTION_IA_NA:
if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) + if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) +
sizeof(addr->iaaddr)) { sizeof(addr->iaaddr)) {
@@ -221,7 +223,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
break; break;
case DHCP6_OPTION_IA_TA: case SD_DHCP6_OPTION_IA_TA:
if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) + if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) +
sizeof(addr->iaaddr)) { sizeof(addr->iaaddr)) {
r = -ENOBUFS; r = -ENOBUFS;
@@ -249,7 +251,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) { while ((r = option_parse_hdr(buf, buflen, &opt, &optlen)) >= 0) {
switch (opt) { switch (opt) {
case DHCP6_OPTION_IAADDR: case SD_DHCP6_OPTION_IAADDR:
addr = new0(DHCP6Address, 1); addr = new0(DHCP6Address, 1);
if (!addr) { if (!addr) {
@@ -276,7 +278,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
break; break;
case DHCP6_OPTION_STATUS_CODE: case SD_DHCP6_OPTION_STATUS_CODE:
if (optlen < sizeof(status)) if (optlen < sizeof(status))
break; break;

View File

@@ -100,41 +100,6 @@ enum {
_DHCP6_MESSAGE_MAX = 14, _DHCP6_MESSAGE_MAX = 14,
}; };
enum {
DHCP6_OPTION_CLIENTID = 1,
DHCP6_OPTION_SERVERID = 2,
DHCP6_OPTION_IA_NA = 3,
DHCP6_OPTION_IA_TA = 4,
DHCP6_OPTION_IAADDR = 5,
DHCP6_OPTION_ORO = 6,
DHCP6_OPTION_PREFERENCE = 7,
DHCP6_OPTION_ELAPSED_TIME = 8,
DHCP6_OPTION_RELAY_MSG = 9,
/* option code 10 is unassigned */
DHCP6_OPTION_AUTH = 11,
DHCP6_OPTION_UNICAST = 12,
DHCP6_OPTION_STATUS_CODE = 13,
DHCP6_OPTION_RAPID_COMMIT = 14,
DHCP6_OPTION_USER_CLASS = 15,
DHCP6_OPTION_VENDOR_CLASS = 16,
DHCP6_OPTION_VENDOR_OPTS = 17,
DHCP6_OPTION_INTERFACE_ID = 18,
DHCP6_OPTION_RECONF_MSG = 19,
DHCP6_OPTION_RECONF_ACCEPT = 20,
DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */
DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */
DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */
/* option code 35 is unassigned */
DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */
/* option codes 89-142 are unassigned */
/* option codes 144-65535 are unassigned */
};
enum { enum {
DHCP6_NTP_SUBOPTION_SRV_ADDR = 1, DHCP6_NTP_SUBOPTION_SRV_ADDR = 1,
DHCP6_NTP_SUBOPTION_MC_ADDR = 2, DHCP6_NTP_SUBOPTION_MC_ADDR = 2,

View File

@@ -443,7 +443,7 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
return size; return size;
} }
void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) { void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
unsigned i; unsigned i;
assert(f); assert(f);
@@ -454,10 +454,15 @@ void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *route
fprintf(f, "%s=", key); fprintf(f, "%s=", key);
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr), struct in_addr dest, gw;
routes[i].dst_prefixlen); uint8_t length;
fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
(i < (size - 1)) ? " ": ""); assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0);
assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0);
assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0);
fprintf(f, "%s/%" PRIu8, inet_ntoa(dest), length);
fprintf(f, ",%s%s", inet_ntoa(gw), (i < (size - 1)) ? " ": "");
} }
fputs("\n", f); fputs("\n", f);

View File

@@ -25,6 +25,8 @@
#include <stdbool.h> #include <stdbool.h>
#include "sd-dhcp-lease.h"
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
#include "condition.h" #include "condition.h"
#include "udev.h" #include "udev.h"
@@ -78,7 +80,7 @@ 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 */ /* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
struct sd_dhcp_route; struct sd_dhcp_route;
void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size); void serialize_dhcp_routes(FILE *f, const char *key, 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 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 void *data, size_t size); int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);

View File

@@ -106,11 +106,11 @@ struct sd_dhcp_client {
}; };
static const uint8_t default_req_opts[] = { static const uint8_t default_req_opts[] = {
DHCP_OPTION_SUBNET_MASK, SD_DHCP_OPTION_SUBNET_MASK,
DHCP_OPTION_ROUTER, SD_DHCP_OPTION_ROUTER,
DHCP_OPTION_HOST_NAME, SD_DHCP_OPTION_HOST_NAME,
DHCP_OPTION_DOMAIN_NAME, SD_DHCP_OPTION_DOMAIN_NAME,
DHCP_OPTION_DOMAIN_NAME_SERVER, SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
}; };
static int client_receive_message_raw(sd_event_source *s, int fd, static int client_receive_message_raw(sd_event_source *s, int fd,
@@ -145,11 +145,11 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) {
DHCP_STATE_STOPPED), -EBUSY); DHCP_STATE_STOPPED), -EBUSY);
switch(option) { switch(option) {
case DHCP_OPTION_PAD: case SD_DHCP_OPTION_PAD:
case DHCP_OPTION_OVERLOAD: case SD_DHCP_OPTION_OVERLOAD:
case DHCP_OPTION_MESSAGE_TYPE: case SD_DHCP_OPTION_MESSAGE_TYPE:
case DHCP_OPTION_PARAMETER_REQUEST_LIST: case SD_DHCP_OPTION_PARAMETER_REQUEST_LIST:
case DHCP_OPTION_END: case SD_DHCP_OPTION_END:
return -EINVAL; return -EINVAL;
default: default:
@@ -488,7 +488,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
Identifier option is not set */ Identifier option is not set */
if (client->client_id_len) { if (client->client_id_len) {
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_CLIENT_IDENTIFIER, SD_DHCP_OPTION_CLIENT_IDENTIFIER,
client->client_id_len, client->client_id_len,
&client->client_id); &client->client_id);
if (r < 0) if (r < 0)
@@ -504,7 +504,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
messages. messages.
*/ */
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_PARAMETER_REQUEST_LIST, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
client->req_opts_size, client->req_opts); client->req_opts_size, client->req_opts);
if (r < 0) if (r < 0)
return r; return r;
@@ -533,7 +533,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
*/ */
max_size = htobe16(size); max_size = htobe16(size);
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0, r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
DHCP_OPTION_MAXIMUM_MESSAGE_SIZE, SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
2, &max_size); 2, &max_size);
if (r < 0) if (r < 0)
return r; return r;
@@ -559,7 +559,7 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t
r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false); r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3, false);
if (r > 0) if (r > 0)
r = dhcp_option_append(message, optlen, optoffset, 0, r = dhcp_option_append(message, optlen, optoffset, 0,
DHCP_OPTION_FQDN, 3 + r, buffer); SD_DHCP_OPTION_FQDN, 3 + r, buffer);
return r; return r;
} }
@@ -595,7 +595,7 @@ static int client_send_discover(sd_dhcp_client *client) {
*/ */
if (client->last_addr != INADDR_ANY) { if (client->last_addr != INADDR_ANY) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_REQUESTED_IP_ADDRESS, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->last_addr); 4, &client->last_addr);
if (r < 0) if (r < 0)
return r; return r;
@@ -611,7 +611,7 @@ static int client_send_discover(sd_dhcp_client *client) {
DHCPDISCOVER but dhclient does and so we do as well DHCPDISCOVER but dhclient does and so we do as well
*/ */
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_HOST_NAME, SD_DHCP_OPTION_HOST_NAME,
strlen(client->hostname), client->hostname); strlen(client->hostname), client->hostname);
} else } else
r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset, r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
@@ -622,7 +622,7 @@ static int client_send_discover(sd_dhcp_client *client) {
if (client->vendor_class_identifier) { if (client->vendor_class_identifier) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_VENDOR_CLASS_IDENTIFIER, SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER,
strlen(client->vendor_class_identifier), strlen(client->vendor_class_identifier),
client->vendor_class_identifier); client->vendor_class_identifier);
if (r < 0) if (r < 0)
@@ -630,7 +630,7 @@ static int client_send_discover(sd_dhcp_client *client) {
} }
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_END, 0, NULL); SD_DHCP_OPTION_END, 0, NULL);
if (r < 0) if (r < 0)
return r; return r;
@@ -669,13 +669,13 @@ static int client_send_request(sd_dhcp_client *client) {
*/ */
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_SERVER_IDENTIFIER, SD_DHCP_OPTION_SERVER_IDENTIFIER,
4, &client->lease->server_address); 4, &client->lease->server_address);
if (r < 0) if (r < 0)
return r; return r;
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_REQUESTED_IP_ADDRESS, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->lease->address); 4, &client->lease->address);
if (r < 0) if (r < 0)
return r; return r;
@@ -688,7 +688,7 @@ static int client_send_request(sd_dhcp_client *client) {
assigned address. ciaddr MUST be zero. assigned address. ciaddr MUST be zero.
*/ */
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_REQUESTED_IP_ADDRESS, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS,
4, &client->last_addr); 4, &client->last_addr);
if (r < 0) if (r < 0)
return r; return r;
@@ -723,7 +723,7 @@ static int client_send_request(sd_dhcp_client *client) {
if (client->hostname) { if (client->hostname) {
if (dns_name_is_single_label(client->hostname)) if (dns_name_is_single_label(client->hostname))
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_HOST_NAME, SD_DHCP_OPTION_HOST_NAME,
strlen(client->hostname), client->hostname); strlen(client->hostname), client->hostname);
else else
r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset, r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
@@ -733,7 +733,7 @@ static int client_send_request(sd_dhcp_client *client) {
} }
r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0, r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
DHCP_OPTION_END, 0, NULL); SD_DHCP_OPTION_END, 0, NULL);
if (r < 0) if (r < 0)
return r; return r;

View File

@@ -39,6 +39,7 @@
#include "in-addr-util.h" #include "in-addr-util.h"
#include "network-internal.h" #include "network-internal.h"
#include "parse-util.h" #include "parse-util.h"
#include "stdio-util.h"
#include "string-util.h" #include "string-util.h"
#include "unaligned.h" #include "unaligned.h"
@@ -207,14 +208,28 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
return 0; return 0;
} }
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes) { /*
* The returned routes array must be freed by the caller.
* Route objects have the same lifetime of the lease and must not be freed.
*/
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
sd_dhcp_route **ret;
unsigned i;
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(routes, -EINVAL); assert_return(routes, -EINVAL);
if (lease->static_route_size <= 0) if (lease->static_route_size <= 0)
return -ENODATA; return -ENODATA;
*routes = lease->static_route; ret = new(sd_dhcp_route *, lease->static_route_size);
if (!ret)
return -ENOMEM;
for (i = 0; i < lease->static_route_size; i++)
ret[i] = &lease->static_route[i];
*routes = ret;
return (int) lease->static_route_size; return (int) lease->static_route_size;
} }
@@ -454,7 +469,7 @@ static int lease_parse_classless_routes(
if (len < 4) if (len < 4)
return -EINVAL; return -EINVAL;
lease_parse_be32(option, 4, &route->gw_addr.s_addr); assert_se(lease_parse_be32(option, 4, &route->gw_addr.s_addr) >= 0);
option += 4; option += 4;
len -= 4; len -= 4;
@@ -472,21 +487,21 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
switch(code) { switch(code) {
case DHCP_OPTION_IP_ADDRESS_LEASE_TIME: case SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME:
r = lease_parse_u32(option, len, &lease->lifetime, 1); r = lease_parse_u32(option, len, &lease->lifetime, 1);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse lease time, ignoring: %m"); log_debug_errno(r, "Failed to parse lease time, ignoring: %m");
break; break;
case DHCP_OPTION_SERVER_IDENTIFIER: case SD_DHCP_OPTION_SERVER_IDENTIFIER:
r = lease_parse_be32(option, len, &lease->server_address); r = lease_parse_be32(option, len, &lease->server_address);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse server identifier, ignoring: %m"); log_debug_errno(r, "Failed to parse server identifier, ignoring: %m");
break; break;
case DHCP_OPTION_SUBNET_MASK: case SD_DHCP_OPTION_SUBNET_MASK:
r = lease_parse_be32(option, len, &lease->subnet_mask); r = lease_parse_be32(option, len, &lease->subnet_mask);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m"); log_debug_errno(r, "Failed to parse subnet mask, ignoring: %m");
@@ -494,7 +509,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
lease->have_subnet_mask = true; lease->have_subnet_mask = true;
break; break;
case DHCP_OPTION_BROADCAST: case SD_DHCP_OPTION_BROADCAST:
r = lease_parse_be32(option, len, &lease->broadcast); r = lease_parse_be32(option, len, &lease->broadcast);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m"); log_debug_errno(r, "Failed to parse broadcast address, ignoring: %m");
@@ -502,7 +517,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
lease->have_broadcast = true; lease->have_broadcast = true;
break; break;
case DHCP_OPTION_ROUTER: case SD_DHCP_OPTION_ROUTER:
if (len >= 4) { if (len >= 4) {
r = lease_parse_be32(option, 4, &lease->router); r = lease_parse_be32(option, 4, &lease->router);
if (r < 0) if (r < 0)
@@ -510,31 +525,31 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
} }
break; break;
case DHCP_OPTION_DOMAIN_NAME_SERVER: case SD_DHCP_OPTION_DOMAIN_NAME_SERVER:
r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size); r = lease_parse_in_addrs(option, len, &lease->dns, &lease->dns_size);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse DNS server, ignoring: %m"); log_debug_errno(r, "Failed to parse DNS server, ignoring: %m");
break; break;
case DHCP_OPTION_NTP_SERVER: case SD_DHCP_OPTION_NTP_SERVER:
r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size); r = lease_parse_in_addrs(option, len, &lease->ntp, &lease->ntp_size);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); log_debug_errno(r, "Failed to parse NTP server, ignoring: %m");
break; break;
case DHCP_OPTION_STATIC_ROUTE: case SD_DHCP_OPTION_STATIC_ROUTE:
r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse static routes, ignoring: %m"); log_debug_errno(r, "Failed to parse static routes, ignoring: %m");
break; break;
case DHCP_OPTION_INTERFACE_MTU: case SD_DHCP_OPTION_INTERFACE_MTU:
r = lease_parse_u16(option, len, &lease->mtu, 68); r = lease_parse_u16(option, len, &lease->mtu, 68);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse MTU, ignoring: %m"); log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
break; break;
case DHCP_OPTION_DOMAIN_NAME: { case SD_DHCP_OPTION_DOMAIN_NAME: {
_cleanup_free_ char *domainname = NULL, *normalized = NULL; _cleanup_free_ char *domainname = NULL, *normalized = NULL;
r = lease_parse_string(option, len, &domainname); r = lease_parse_string(option, len, &domainname);
@@ -561,7 +576,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
break; break;
} }
case DHCP_OPTION_HOST_NAME: { case SD_DHCP_OPTION_HOST_NAME: {
_cleanup_free_ char *hostname = NULL, *normalized = NULL; _cleanup_free_ char *hostname = NULL, *normalized = NULL;
r = lease_parse_string(option, len, &hostname); r = lease_parse_string(option, len, &hostname);
@@ -588,25 +603,25 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
break; break;
} }
case DHCP_OPTION_ROOT_PATH: case SD_DHCP_OPTION_ROOT_PATH:
r = lease_parse_string(option, len, &lease->root_path); r = lease_parse_string(option, len, &lease->root_path);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse root path, ignoring: %m"); log_debug_errno(r, "Failed to parse root path, ignoring: %m");
break; break;
case DHCP_OPTION_RENEWAL_T1_TIME: case SD_DHCP_OPTION_RENEWAL_T1_TIME:
r = lease_parse_u32(option, len, &lease->t1, 1); r = lease_parse_u32(option, len, &lease->t1, 1);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse T1 time, ignoring: %m"); log_debug_errno(r, "Failed to parse T1 time, ignoring: %m");
break; break;
case DHCP_OPTION_REBINDING_T2_TIME: case SD_DHCP_OPTION_REBINDING_T2_TIME:
r = lease_parse_u32(option, len, &lease->t2, 1); r = lease_parse_u32(option, len, &lease->t2, 1);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse T2 time, ignoring: %m"); log_debug_errno(r, "Failed to parse T2 time, ignoring: %m");
break; break;
case DHCP_OPTION_CLASSLESS_STATIC_ROUTE: case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
r = lease_parse_classless_routes( r = lease_parse_classless_routes(
option, len, option, len,
&lease->static_route, &lease->static_route,
@@ -616,7 +631,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
log_debug_errno(r, "Failed to parse classless routes, ignoring: %m"); log_debug_errno(r, "Failed to parse classless routes, ignoring: %m");
break; break;
case DHCP_OPTION_NEW_TZDB_TIMEZONE: { case SD_DHCP_OPTION_NEW_TZDB_TIMEZONE: {
_cleanup_free_ char *tz = NULL; _cleanup_free_ char *tz = NULL;
r = lease_parse_string(option, len, &tz); r = lease_parse_string(option, len, &tz);
@@ -637,7 +652,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
break; break;
} }
case DHCP_OPTION_VENDOR_SPECIFIC: case SD_DHCP_OPTION_VENDOR_SPECIFIC:
if (len <= 0) if (len <= 0)
lease->vendor_specific = mfree(lease->vendor_specific); lease->vendor_specific = mfree(lease->vendor_specific);
@@ -655,7 +670,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
lease->vendor_specific_len = len; lease->vendor_specific_len = len;
break; break;
case DHCP_OPTION_PRIVATE_BASE ... DHCP_OPTION_PRIVATE_LAST: case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST:
r = dhcp_lease_insert_private_option(lease, code, option, len); r = dhcp_lease_insert_private_option(lease, code, option, len);
if (r < 0) if (r < 0)
return r; return r;
@@ -724,7 +739,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
size_t client_id_len, data_len; size_t client_id_len, data_len;
const char *string; const char *string;
uint16_t mtu; uint16_t mtu;
struct sd_dhcp_route *routes; _cleanup_free_ sd_dhcp_route **routes = NULL;
uint32_t t1, t2, lifetime; uint32_t t1, t2, lifetime;
int r; int r;
@@ -841,7 +856,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
LIST_FOREACH(options, option, lease->private_options) { LIST_FOREACH(options, option, lease->private_options) {
char key[strlen("OPTION_000")+1]; char key[strlen("OPTION_000")+1];
snprintf(key, sizeof(key), "OPTION_%"PRIu8, option->tag); xsprintf(key, "OPTION_%" PRIu8, option->tag);
r = serialize_dhcp_option(f, key, option->data, option->length); r = serialize_dhcp_option(f, key, option->data, option->length);
if (r < 0) if (r < 0)
goto fail; goto fail;
@@ -884,7 +899,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
*lifetime = NULL, *lifetime = NULL,
*t1 = NULL, *t1 = NULL,
*t2 = NULL, *t2 = NULL,
*options[DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE + 1] = {}; *options[SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE + 1] = {};
int r, i; int r, i;
@@ -1052,7 +1067,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex); log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex);
} }
for (i = 0; i <= DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE; i++) { for (i = 0; i <= SD_DHCP_OPTION_PRIVATE_LAST - SD_DHCP_OPTION_PRIVATE_BASE; i++) {
_cleanup_free_ void *data = NULL; _cleanup_free_ void *data = NULL;
size_t len; size_t len;
@@ -1065,7 +1080,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
continue; continue;
} }
r = dhcp_lease_insert_private_option(lease, DHCP_OPTION_PRIVATE_BASE + i, data, len); r = dhcp_lease_insert_private_option(lease, SD_DHCP_OPTION_PRIVATE_BASE + i, data, len);
if (r < 0) if (r < 0)
return r; return r;
} }
@@ -1143,3 +1158,27 @@ int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
*tz = lease->timezone; *tz = lease->timezone;
return 0; return 0;
} }
int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) {
assert_return(route, -EINVAL);
assert_return(destination, -EINVAL);
*destination = route->dst_addr;
return 0;
}
int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) {
assert_return(route, -EINVAL);
assert_return(length, -EINVAL);
*length = route->dst_prefixlen;
return 0;
}
int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
assert_return(route, -EINVAL);
assert_return(gateway, -EINVAL);
*gateway = route->gw_addr;
return 0;
}

View File

@@ -74,10 +74,10 @@ struct sd_dhcp6_client {
}; };
static const uint16_t default_req_opts[] = { static const uint16_t default_req_opts[] = {
DHCP6_OPTION_DNS_SERVERS, SD_DHCP6_OPTION_DNS_SERVERS,
DHCP6_OPTION_DOMAIN_LIST, SD_DHCP6_OPTION_DOMAIN_LIST,
DHCP6_OPTION_NTP_SERVER, SD_DHCP6_OPTION_NTP_SERVER,
DHCP6_OPTION_SNTP_SERVERS, SD_DHCP6_OPTION_SNTP_SERVERS,
}; };
const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = { const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
@@ -247,10 +247,10 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
switch(option) { switch(option) {
case DHCP6_OPTION_DNS_SERVERS: case SD_DHCP6_OPTION_DNS_SERVERS:
case DHCP6_OPTION_DOMAIN_LIST: case SD_DHCP6_OPTION_DOMAIN_LIST:
case DHCP6_OPTION_SNTP_SERVERS: case SD_DHCP6_OPTION_SNTP_SERVERS:
case DHCP6_OPTION_NTP_SERVER: case SD_DHCP6_OPTION_NTP_SERVER:
break; break;
default: default:
@@ -364,7 +364,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
message->type = DHCP6_SOLICIT; message->type = DHCP6_SOLICIT;
r = dhcp6_option_append(&opt, &optlen, r = dhcp6_option_append(&opt, &optlen,
DHCP6_OPTION_RAPID_COMMIT, 0, NULL); SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
if (r < 0) if (r < 0)
return r; return r;
@@ -382,7 +382,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
else else
message->type = DHCP6_RENEW; message->type = DHCP6_RENEW;
r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_SERVERID, r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID,
client->lease->serverid_len, client->lease->serverid_len,
client->lease->serverid); client->lease->serverid);
if (r < 0) if (r < 0)
@@ -408,14 +408,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return -EINVAL; return -EINVAL;
} }
r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO, r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO,
client->req_opts_len * sizeof(be16_t), client->req_opts_len * sizeof(be16_t),
client->req_opts); client->req_opts);
if (r < 0) if (r < 0)
return r; return r;
assert (client->duid_len); assert (client->duid_len);
r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID, r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_CLIENTID,
client->duid_len, &client->duid); client->duid_len, &client->duid);
if (r < 0) if (r < 0)
return r; return r;
@@ -426,7 +426,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
else else
elapsed_time = 0xffff; elapsed_time = 0xffff;
r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ELAPSED_TIME, r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME,
sizeof(elapsed_time), &elapsed_time); sizeof(elapsed_time), &elapsed_time);
if (r < 0) if (r < 0)
return r; return r;
@@ -689,7 +689,7 @@ static int client_parse_message(sd_dhcp6_client *client,
while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen, while ((r = dhcp6_option_parse(&option, &len, &optcode, &optlen,
&optval)) >= 0) { &optval)) >= 0) {
switch (optcode) { switch (optcode) {
case DHCP6_OPTION_CLIENTID: case SD_DHCP6_OPTION_CLIENTID:
if (clientid) { if (clientid) {
log_dhcp6_client(client, "%s contains multiple clientids", log_dhcp6_client(client, "%s contains multiple clientids",
dhcp6_message_type_to_string(message->type)); dhcp6_message_type_to_string(message->type));
@@ -707,7 +707,7 @@ static int client_parse_message(sd_dhcp6_client *client,
break; break;
case DHCP6_OPTION_SERVERID: case SD_DHCP6_OPTION_SERVERID:
r = dhcp6_lease_get_serverid(lease, &id, &id_len); r = dhcp6_lease_get_serverid(lease, &id, &id_len);
if (r >= 0 && id) { if (r >= 0 && id) {
log_dhcp6_client(client, "%s contains multiple serverids", log_dhcp6_client(client, "%s contains multiple serverids",
@@ -721,7 +721,7 @@ static int client_parse_message(sd_dhcp6_client *client,
break; break;
case DHCP6_OPTION_PREFERENCE: case SD_DHCP6_OPTION_PREFERENCE:
if (optlen != 1) if (optlen != 1)
return -EINVAL; return -EINVAL;
@@ -731,7 +731,7 @@ static int client_parse_message(sd_dhcp6_client *client,
break; break;
case DHCP6_OPTION_STATUS_CODE: case SD_DHCP6_OPTION_STATUS_CODE:
if (optlen < 2) if (optlen < 2)
return -EINVAL; return -EINVAL;
@@ -745,7 +745,7 @@ static int client_parse_message(sd_dhcp6_client *client,
break; break;
case DHCP6_OPTION_IA_NA: case SD_DHCP6_OPTION_IA_NA:
if (client->state == DHCP6_STATE_INFORMATION_REQUEST) { if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
log_dhcp6_client(client, "Information request ignoring IA NA option"); log_dhcp6_client(client, "Information request ignoring IA NA option");
@@ -769,35 +769,35 @@ static int client_parse_message(sd_dhcp6_client *client,
break; break;
case DHCP6_OPTION_RAPID_COMMIT: case SD_DHCP6_OPTION_RAPID_COMMIT:
r = dhcp6_lease_set_rapid_commit(lease); r = dhcp6_lease_set_rapid_commit(lease);
if (r < 0) if (r < 0)
return r; return r;
break; break;
case DHCP6_OPTION_DNS_SERVERS: case SD_DHCP6_OPTION_DNS_SERVERS:
r = dhcp6_lease_set_dns(lease, optval, optlen); r = dhcp6_lease_set_dns(lease, optval, optlen);
if (r < 0) if (r < 0)
return r; return r;
break; break;
case DHCP6_OPTION_DOMAIN_LIST: case SD_DHCP6_OPTION_DOMAIN_LIST:
r = dhcp6_lease_set_domains(lease, optval, optlen); r = dhcp6_lease_set_domains(lease, optval, optlen);
if (r < 0) if (r < 0)
return r; return r;
break; break;
case DHCP6_OPTION_NTP_SERVER: case SD_DHCP6_OPTION_NTP_SERVER:
r = dhcp6_lease_set_ntp(lease, optval, optlen); r = dhcp6_lease_set_ntp(lease, optval, optlen);
if (r < 0) if (r < 0)
return r; return r;
break; break;
case DHCP6_OPTION_SNTP_SERVERS: case SD_DHCP6_OPTION_SNTP_SERVERS:
r = dhcp6_lease_set_sntp(lease, optval, optlen); r = dhcp6_lease_set_sntp(lease, optval, optlen);
if (r < 0) if (r < 0)
return r; return r;
@@ -1287,7 +1287,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
client->n_ref = 1; client->n_ref = 1;
client->ia_na.type = DHCP6_OPTION_IA_NA; client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
client->index = -1; client->index = -1;

View File

@@ -258,7 +258,7 @@ int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(optval, -EINVAL); assert_return(optval, -EINVAL);
free(lease->ntp); lease->ntp = mfree(lease->ntp);
lease->ntp_count = 0; lease->ntp_count = 0;
lease->ntp_allocated = 0; lease->ntp_allocated = 0;

View File

@@ -265,7 +265,6 @@ int dns_label_escape(const char *p, size_t l, char *dest, size_t sz) {
*(q++) = '0' + (char) ((uint8_t) *p % 10); *(q++) = '0' + (char) ((uint8_t) *p % 10);
sz -= 4; sz -= 4;
} }
p++; p++;
@@ -416,7 +415,6 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
for (;;) { for (;;) {
char label[DNS_LABEL_MAX]; char label[DNS_LABEL_MAX];
int k;
r = dns_label_unescape(&p, label, sizeof(label)); r = dns_label_unescape(&p, label, sizeof(label));
if (r < 0) if (r < 0)
@@ -435,12 +433,6 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
break; break;
} }
k = dns_label_undo_idna(label, r, label, sizeof(label));
if (k < 0)
return k;
if (k > 0)
r = k;
if (_ret) { if (_ret) {
if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
return -ENOMEM; return -ENOMEM;
@@ -489,27 +481,18 @@ void dns_name_hash_func(const void *s, struct siphash *state) {
assert(p); assert(p);
while (*p) { for (;;) {
char label[DNS_LABEL_MAX+1]; char label[DNS_LABEL_MAX+1];
int k;
r = dns_label_unescape(&p, label, sizeof(label)); r = dns_label_unescape(&p, label, sizeof(label));
if (r < 0) if (r < 0)
break; break;
k = dns_label_undo_idna(label, r, label, sizeof(label));
if (k < 0)
break;
if (k > 0)
r = k;
if (r == 0) if (r == 0)
break; break;
label[r] = 0; ascii_strlower_n(label, r);
ascii_strlower(label); siphash24_compress(label, r, state);
siphash24_compress_byte(0, state); /* make sure foobar and foo.bar result in different hashes */
string_hash_func(label, state);
} }
/* enforce that all names are terminated by the empty label */ /* enforce that all names are terminated by the empty label */
@@ -518,7 +501,7 @@ void dns_name_hash_func(const void *s, struct siphash *state) {
int dns_name_compare_func(const void *a, const void *b) { int dns_name_compare_func(const void *a, const void *b) {
const char *x, *y; const char *x, *y;
int r, q, k, w; int r, q;
assert(a); assert(a);
assert(b); assert(b);
@@ -527,7 +510,7 @@ int dns_name_compare_func(const void *a, const void *b) {
y = (const char *) b + strlen(b); y = (const char *) b + strlen(b);
for (;;) { for (;;) {
char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1]; char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
if (x == NULL && y == NULL) if (x == NULL && y == NULL)
return 0; return 0;
@@ -537,17 +520,7 @@ int dns_name_compare_func(const void *a, const void *b) {
if (r < 0 || q < 0) if (r < 0 || q < 0)
return r - q; return r - q;
k = dns_label_undo_idna(la, r, la, sizeof(la)); r = ascii_strcasecmp_nn(la, r, lb, q);
w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
if (k < 0 || w < 0)
return k - w;
if (k > 0)
r = k;
if (w > 0)
q = w;
la[r] = lb[q] = 0;
r = strcasecmp(la, lb);
if (r != 0) if (r != 0)
return r; return r;
} }
@@ -559,53 +532,35 @@ const struct hash_ops dns_name_hash_ops = {
}; };
int dns_name_equal(const char *x, const char *y) { int dns_name_equal(const char *x, const char *y) {
int r, q, k, w; int r, q;
assert(x); assert(x);
assert(y); assert(y);
for (;;) { for (;;) {
char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1]; char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
if (*x == 0 && *y == 0)
return true;
r = dns_label_unescape(&x, la, sizeof(la)); r = dns_label_unescape(&x, la, sizeof(la));
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) {
k = dns_label_undo_idna(la, r, la, sizeof(la));
if (k < 0)
return k;
if (k > 0)
r = k;
}
q = dns_label_unescape(&y, lb, sizeof(lb)); q = dns_label_unescape(&y, lb, sizeof(lb));
if (q < 0) if (q < 0)
return q; return q;
if (q > 0) {
w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
if (w < 0)
return w;
if (w > 0)
q = w;
}
/* If one name had fewer labels than the other, this if (r != q)
* will show up as empty label here, which the return false;
* strcasecmp() below will properly consider different if (r == 0)
* from a non-empty label. */ return true;
la[r] = lb[q] = 0; if (ascii_strcasecmp_n(la, lb, r) != 0)
if (strcasecmp(la, lb) != 0)
return false; return false;
} }
} }
int dns_name_endswith(const char *name, const char *suffix) { int dns_name_endswith(const char *name, const char *suffix) {
const char *n, *s, *saved_n = NULL; const char *n, *s, *saved_n = NULL;
int r, q, k, w; int r, q;
assert(name); assert(name);
assert(suffix); assert(suffix);
@@ -614,18 +569,11 @@ int dns_name_endswith(const char *name, const char *suffix) {
s = suffix; s = suffix;
for (;;) { for (;;) {
char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1]; char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
r = dns_label_unescape(&n, ln, sizeof(ln)); r = dns_label_unescape(&n, ln, sizeof(ln));
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) {
k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
if (k < 0)
return k;
if (k > 0)
r = k;
}
if (!saved_n) if (!saved_n)
saved_n = n; saved_n = n;
@@ -633,22 +581,13 @@ int dns_name_endswith(const char *name, const char *suffix) {
q = dns_label_unescape(&s, ls, sizeof(ls)); q = dns_label_unescape(&s, ls, sizeof(ls));
if (q < 0) if (q < 0)
return q; return q;
if (q > 0) {
w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
if (w < 0)
return w;
if (w > 0)
q = w;
}
if (r == 0 && q == 0) if (r == 0 && q == 0)
return true; return true;
if (r == 0 && saved_n == n) if (r == 0 && saved_n == n)
return false; return false;
ln[r] = ls[q] = 0; if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
if (r != q || strcasecmp(ln, ls)) {
/* Not the same, let's jump back, and try with the next label again */ /* Not the same, let's jump back, and try with the next label again */
s = suffix; s = suffix;
@@ -658,9 +597,39 @@ int dns_name_endswith(const char *name, const char *suffix) {
} }
} }
int dns_name_startswith(const char *name, const char *prefix) {
const char *n, *p;
int r, q;
assert(name);
assert(prefix);
n = name;
p = prefix;
for (;;) {
char ln[DNS_LABEL_MAX], lp[DNS_LABEL_MAX];
r = dns_label_unescape(&p, lp, sizeof(lp));
if (r < 0)
return r;
if (r == 0)
return true;
q = dns_label_unescape(&n, ln, sizeof(ln));
if (q < 0)
return q;
if (r != q)
return false;
if (ascii_strcasecmp_n(ln, lp, r) != 0)
return false;
}
}
int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) { int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret) {
const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix; const char *n, *s, *saved_before = NULL, *saved_after = NULL, *prefix;
int r, q, k, w; int r, q;
assert(name); assert(name);
assert(old_suffix); assert(old_suffix);
@@ -671,7 +640,7 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
s = old_suffix; s = old_suffix;
for (;;) { for (;;) {
char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1]; char ln[DNS_LABEL_MAX], ls[DNS_LABEL_MAX];
if (!saved_before) if (!saved_before)
saved_before = n; saved_before = n;
@@ -679,13 +648,6 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
r = dns_label_unescape(&n, ln, sizeof(ln)); r = dns_label_unescape(&n, ln, sizeof(ln));
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) {
k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
if (k < 0)
return k;
if (k > 0)
r = k;
}
if (!saved_after) if (!saved_after)
saved_after = n; saved_after = n;
@@ -693,13 +655,6 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
q = dns_label_unescape(&s, ls, sizeof(ls)); q = dns_label_unescape(&s, ls, sizeof(ls));
if (q < 0) if (q < 0)
return q; return q;
if (q > 0) {
w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
if (w < 0)
return w;
if (w > 0)
q = w;
}
if (r == 0 && q == 0) if (r == 0 && q == 0)
break; break;
@@ -708,9 +663,7 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char
return 0; return 0;
} }
ln[r] = ls[q] = 0; if (r != q || ascii_strcasecmp_n(ln, ls, r) != 0) {
if (r != q || strcasecmp(ln, ls)) {
/* Not the same, let's jump back, and try with the next label again */ /* Not the same, let's jump back, and try with the next label again */
s = old_suffix; s = old_suffix;
@@ -879,12 +832,11 @@ bool dns_name_is_root(const char *name) {
} }
bool dns_name_is_single_label(const char *name) { bool dns_name_is_single_label(const char *name) {
char label[DNS_LABEL_MAX+1];
int r; int r;
assert(name); assert(name);
r = dns_label_unescape(&name, label, sizeof(label)); r = dns_name_parent(&name);
if (r <= 0) if (r <= 0)
return false; return false;
@@ -917,19 +869,11 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, boo
if (r < 0) if (r < 0)
return r; return r;
if (canonical) { /* Optionally, output the name in DNSSEC canonical
size_t i; * format, as described in RFC 4034, section 6.2. Or
* in other words: in lower-case. */
/* Optionally, output the name in DNSSEC if (canonical)
* canonical format, as described in RFC 4034, ascii_strlower_n((char*) out, (size_t) r);
* section 6.2. Or in other words: in
* lower-case. */
for (i = 0; i < (size_t) r; i++) {
if (out[i] >= 'A' && out[i] <= 'Z')
out[i] = out[i] - 'A' + 'a';
}
}
/* Fill label length, move forward */ /* Fill label length, move forward */
*label_length = r; *label_length = r;
@@ -1114,17 +1058,15 @@ int dns_service_split(const char *joined, char **_name, char **_type, char **_do
if (x >= 3 && srv_type_label_is_valid(c, cn)) { if (x >= 3 && srv_type_label_is_valid(c, cn)) {
if (dns_service_name_label_is_valid(a, an)) { if (dns_service_name_label_is_valid(a, an)) {
/* OK, got <name> . <type> . <type2> . <domain> */ /* OK, got <name> . <type> . <type2> . <domain> */
name = strndup(a, an); name = strndup(a, an);
if (!name) if (!name)
return -ENOMEM; return -ENOMEM;
type = new(char, bn+1+cn+1); type = strjoin(b, ".", c, NULL);
if (!type) if (!type)
return -ENOMEM; return -ENOMEM;
strcpy(stpcpy(stpcpy(type, b), "."), c);
d = p; d = p;
goto finish; goto finish;
@@ -1136,10 +1078,9 @@ int dns_service_split(const char *joined, char **_name, char **_type, char **_do
name = NULL; name = NULL;
type = new(char, an+1+bn+1); type = strjoin(a, ".", b, NULL);
if (!type) if (!type)
return -ENOMEM; return -ENOMEM;
strcpy(stpcpy(stpcpy(type, a), "."), b);
d = q; d = q;
goto finish; goto finish;
@@ -1173,22 +1114,20 @@ finish:
return 0; return 0;
} }
int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) { static int dns_name_build_suffix_table(const char *name, const char*table[]) {
const char* labels[DNS_N_LABELS_MAX+1];
unsigned n = 0;
const char *p; const char *p;
unsigned n = 0;
int r; int r;
assert(name); assert(name);
assert(ret); assert(table);
p = name; p = name;
for (;;) { for (;;) {
if (n > DNS_N_LABELS_MAX) if (n > DNS_N_LABELS_MAX)
return -EINVAL; return -EINVAL;
labels[n] = p; table[n] = p;
r = dns_name_parent(&p); r = dns_name_parent(&p);
if (r < 0) if (r < 0)
return r; return r;
@@ -1198,13 +1137,47 @@ int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
n++; n++;
} }
if (n < n_labels) return (int) n;
}
int dns_name_suffix(const char *name, unsigned n_labels, const char **ret) {
const char* labels[DNS_N_LABELS_MAX+1];
int n;
assert(name);
assert(ret);
n = dns_name_build_suffix_table(name, labels);
if (n < 0)
return n;
if ((unsigned) n < n_labels)
return -EINVAL; return -EINVAL;
*ret = labels[n - n_labels]; *ret = labels[n - n_labels];
return (int) (n - n_labels); return (int) (n - n_labels);
} }
int dns_name_skip(const char *a, unsigned n_labels, const char **ret) {
int r;
assert(a);
assert(ret);
for (; n_labels > 0; n_labels --) {
r = dns_name_parent(&a);
if (r < 0)
return r;
if (r == 0) {
*ret = "";
return 0;
}
}
*ret = a;
return 1;
}
int dns_name_count_labels(const char *name) { int dns_name_count_labels(const char *name) {
unsigned n = 0; unsigned n = 0;
const char *p; const char *p;
@@ -1235,15 +1208,108 @@ int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b) {
assert(a); assert(a);
assert(b); assert(b);
while (n_labels > 0) { r = dns_name_skip(a, n_labels, &a);
if (r <= 0)
r = dns_name_parent(&a); return r;
if (r <= 0)
return r;
n_labels --;
}
return dns_name_equal(a, b); return dns_name_equal(a, b);
} }
int dns_name_common_suffix(const char *a, const char *b, const char **ret) {
const char *a_labels[DNS_N_LABELS_MAX+1], *b_labels[DNS_N_LABELS_MAX+1];
int n = 0, m = 0, k = 0, r, q;
assert(a);
assert(b);
assert(ret);
/* Determines the common suffix of domain names a and b */
n = dns_name_build_suffix_table(a, a_labels);
if (n < 0)
return n;
m = dns_name_build_suffix_table(b, b_labels);
if (m < 0)
return m;
for (;;) {
char la[DNS_LABEL_MAX], lb[DNS_LABEL_MAX];
const char *x, *y;
if (k >= n || k >= m) {
*ret = a_labels[n - k];
return 0;
}
x = a_labels[n - 1 - k];
r = dns_label_unescape(&x, la, sizeof(la));
if (r < 0)
return r;
y = b_labels[m - 1 - k];
q = dns_label_unescape(&y, lb, sizeof(lb));
if (q < 0)
return q;
if (r != q || ascii_strcasecmp_n(la, lb, r) != 0) {
*ret = a_labels[n - k];
return 0;
}
k++;
}
}
int dns_name_apply_idna(const char *name, char **ret) {
_cleanup_free_ char *buf = NULL;
size_t n = 0, allocated = 0;
bool first = true;
int r, q;
assert(name);
assert(ret);
for (;;) {
char label[DNS_LABEL_MAX];
r = dns_label_unescape(&name, label, sizeof(label));
if (r < 0)
return r;
if (r == 0)
break;
q = dns_label_apply_idna(label, r, label, sizeof(label));
if (q < 0)
return q;
if (q > 0)
r = q;
if (!GREEDY_REALLOC(buf, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
return -ENOMEM;
r = dns_label_escape(label, r, buf + n + !first, DNS_LABEL_ESCAPED_MAX);
if (r < 0)
return r;
if (first)
first = false;
else
buf[n++] = '.';
n +=r;
}
if (n > DNS_HOSTNAME_MAX)
return -EINVAL;
if (!GREEDY_REALLOC(buf, allocated, n + 1))
return -ENOMEM;
buf[n] = 0;
*ret = buf;
buf = NULL;
return (int) n;
}
#endif /* NM_IGNORED */ #endif /* NM_IGNORED */

View File

@@ -84,6 +84,7 @@ extern const struct hash_ops dns_name_hash_ops;
int dns_name_between(const char *a, const char *b, const char *c); int dns_name_between(const char *a, const char *b, const char *c);
int dns_name_equal(const char *x, const char *y); int dns_name_equal(const char *x, const char *y);
int dns_name_endswith(const char *name, const char *suffix); int dns_name_endswith(const char *name, const char *suffix);
int dns_name_startswith(const char *name, const char *prefix);
int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret); int dns_name_change_suffix(const char *name, const char *old_suffix, const char *new_suffix, char **ret);
@@ -104,4 +105,9 @@ int dns_service_split(const char *joined, char **name, char **type, char **domai
int dns_name_suffix(const char *name, unsigned n_labels, const char **ret); int dns_name_suffix(const char *name, unsigned n_labels, const char **ret);
int dns_name_count_labels(const char *name); int dns_name_count_labels(const char *name);
int dns_name_skip(const char *a, unsigned n_labels, const char **ret);
int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b); int dns_name_equal_skip(const char *a, unsigned n_labels, const char *b);
int dns_name_common_suffix(const char *a, const char *b, const char **ret);
int dns_name_apply_idna(const char *name, char **ret);

View File

@@ -44,6 +44,48 @@ enum {
SD_DHCP_CLIENT_EVENT_RENEW = 4, SD_DHCP_CLIENT_EVENT_RENEW = 4,
}; };
enum {
SD_DHCP_OPTION_PAD = 0,
SD_DHCP_OPTION_SUBNET_MASK = 1,
SD_DHCP_OPTION_TIME_OFFSET = 2,
SD_DHCP_OPTION_ROUTER = 3,
SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6,
SD_DHCP_OPTION_HOST_NAME = 12,
SD_DHCP_OPTION_BOOT_FILE_SIZE = 13,
SD_DHCP_OPTION_DOMAIN_NAME = 15,
SD_DHCP_OPTION_ROOT_PATH = 17,
SD_DHCP_OPTION_ENABLE_IP_FORWARDING = 19,
SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20,
SD_DHCP_OPTION_POLICY_FILTER = 21,
SD_DHCP_OPTION_INTERFACE_MDR = 22,
SD_DHCP_OPTION_INTERFACE_TTL = 23,
SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24,
SD_DHCP_OPTION_INTERFACE_MTU = 26,
SD_DHCP_OPTION_BROADCAST = 28,
SD_DHCP_OPTION_STATIC_ROUTE = 33,
SD_DHCP_OPTION_NTP_SERVER = 42,
SD_DHCP_OPTION_VENDOR_SPECIFIC = 43,
SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50,
SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51,
SD_DHCP_OPTION_OVERLOAD = 52,
SD_DHCP_OPTION_MESSAGE_TYPE = 53,
SD_DHCP_OPTION_SERVER_IDENTIFIER = 54,
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55,
SD_DHCP_OPTION_ERROR_MESSAGE = 56,
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57,
SD_DHCP_OPTION_RENEWAL_T1_TIME = 58,
SD_DHCP_OPTION_REBINDING_T2_TIME = 59,
SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61,
SD_DHCP_OPTION_FQDN = 81,
SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
SD_DHCP_OPTION_PRIVATE_BASE = 224,
SD_DHCP_OPTION_PRIVATE_LAST = 254,
SD_DHCP_OPTION_END = 255,
};
typedef struct sd_dhcp_client sd_dhcp_client; typedef struct sd_dhcp_client sd_dhcp_client;
typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event, typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event,

View File

@@ -35,7 +35,7 @@
_SD_BEGIN_DECLARATIONS; _SD_BEGIN_DECLARATIONS;
typedef struct sd_dhcp_lease sd_dhcp_lease; typedef struct sd_dhcp_lease sd_dhcp_lease;
struct sd_dhcp_route; typedef struct sd_dhcp_route sd_dhcp_route;
sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease); sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease);
sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease); sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease);
@@ -55,11 +55,15 @@ 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_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_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_root_path(sd_dhcp_lease *lease, const char **root_path);
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes); int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, 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_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_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone); int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone);
int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination);
int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length);
int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref);
_SD_END_DECLARATIONS; _SD_END_DECLARATIONS;

View File

@@ -43,6 +43,41 @@ enum {
SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST = 13, SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST = 13,
}; };
enum {
SD_DHCP6_OPTION_CLIENTID = 1,
SD_DHCP6_OPTION_SERVERID = 2,
SD_DHCP6_OPTION_IA_NA = 3,
SD_DHCP6_OPTION_IA_TA = 4,
SD_DHCP6_OPTION_IAADDR = 5,
SD_DHCP6_OPTION_ORO = 6,
SD_DHCP6_OPTION_PREFERENCE = 7,
SD_DHCP6_OPTION_ELAPSED_TIME = 8,
SD_DHCP6_OPTION_RELAY_MSG = 9,
/* option code 10 is unassigned */
SD_DHCP6_OPTION_AUTH = 11,
SD_DHCP6_OPTION_UNICAST = 12,
SD_DHCP6_OPTION_STATUS_CODE = 13,
SD_DHCP6_OPTION_RAPID_COMMIT = 14,
SD_DHCP6_OPTION_USER_CLASS = 15,
SD_DHCP6_OPTION_VENDOR_CLASS = 16,
SD_DHCP6_OPTION_VENDOR_OPTS = 17,
SD_DHCP6_OPTION_INTERFACE_ID = 18,
SD_DHCP6_OPTION_RECONF_MSG = 19,
SD_DHCP6_OPTION_RECONF_ACCEPT = 20,
SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */
SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */
SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */
/* option code 35 is unassigned */
SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */
/* option codes 89-142 are unassigned */
/* option codes 144-65535 are unassigned */
};
typedef struct sd_dhcp6_client sd_dhcp6_client; typedef struct sd_dhcp6_client sd_dhcp6_client;
typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event, typedef void (*sd_dhcp6_client_cb_t)(sd_dhcp6_client *client, int event,