dhcp: update system-dhcp code from upstream

This commit is contained in:
Dan Winship
2014-11-19 12:02:36 -05:00
22 changed files with 455 additions and 355 deletions

View File

@@ -99,6 +99,7 @@ libsystemd_dhcp_la_SOURCES = \
dhcp-manager/systemd-dhcp/src/shared/fileio.c \ dhcp-manager/systemd-dhcp/src/shared/fileio.c \
dhcp-manager/systemd-dhcp/src/shared/strv.h \ dhcp-manager/systemd-dhcp/src/shared/strv.h \
dhcp-manager/systemd-dhcp/src/shared/strv.c \ dhcp-manager/systemd-dhcp/src/shared/strv.c \
dhcp-manager/systemd-dhcp/src/shared/unaligned.h \
dhcp-manager/systemd-dhcp/src/shared/utf8.h \ dhcp-manager/systemd-dhcp/src/shared/utf8.h \
dhcp-manager/systemd-dhcp/src/shared/utf8.c \ dhcp-manager/systemd-dhcp/src/shared/utf8.c \
dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h \ dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h \

View File

@@ -389,7 +389,7 @@ nm_dhcp_systemd_get_lease_ip_configs (const char *iface,
return NULL; return NULL;
path = get_leasefile_path (iface, uuid, FALSE); path = get_leasefile_path (iface, uuid, FALSE);
r = sd_dhcp_lease_load (path, &lease); r = sd_dhcp_lease_load (&lease, path);
if (r == 0) { if (r == 0) {
ip4_config = lease_to_ip4_config (lease, NULL, 0, FALSE, NULL); ip4_config = lease_to_ip4_config (lease, NULL, 0, FALSE, NULL);
if (ip4_config) if (ip4_config)
@@ -457,7 +457,7 @@ bound4_handle (NMDhcpSystemd *self)
add_requests_to_options (options, dhcp4_requests); add_requests_to_options (options, dhcp4_requests);
sd_dhcp_lease_save (lease, priv->lease_file); sd_dhcp_lease_save (lease, priv->lease_file);
client_id = sd_dhcp_client_get_client_id(priv->client4, &type, &client_id_len); sd_dhcp_client_get_client_id(priv->client4, &type, &client_id, &client_id_len);
if (client_id) if (client_id)
_save_client_id (self, type, client_id, client_id_len); _save_client_id (self, type, client_id, client_id_len);
@@ -576,7 +576,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
goto error; goto error;
} }
sd_dhcp_lease_load (priv->lease_file, &lease); sd_dhcp_lease_load (&lease, priv->lease_file);
if (last_ip4_address) if (last_ip4_address)
inet_pton (AF_INET, last_ip4_address, &last_addr); inet_pton (AF_INET, last_ip4_address, &last_addr);

View File

@@ -68,12 +68,12 @@ sd_event_source_unref (sd_event_source *s)
} }
int int
sd_event_source_set_name(sd_event_source *s, const char *name) sd_event_source_set_description(sd_event_source *s, const char *description)
{ {
if (!s) if (!s)
return -EINVAL; return -EINVAL;
g_source_set_name_by_id (s->id, name); g_source_set_name_by_id (s->id, description);
return 0; return 0;
} }

View File

@@ -35,7 +35,7 @@
struct sd_dhcp_route { struct sd_dhcp_route {
struct in_addr dst_addr; struct in_addr dst_addr;
struct in_addr gw_addr; struct in_addr gw_addr;
uint8_t dst_prefixlen; unsigned char dst_prefixlen;
}; };
struct sd_dhcp_lease { struct sd_dhcp_lease {

View File

@@ -28,31 +28,37 @@
#include <string.h> #include <string.h>
#include "sparse-endian.h" #include "sparse-endian.h"
#include "unaligned.h"
#include "util.h" #include "util.h"
#include "dhcp6-internal.h" #include "dhcp6-internal.h"
#include "dhcp6-protocol.h" #include "dhcp6-protocol.h"
#define DHCP6_OPTION_HDR_LEN 4
#define DHCP6_OPTION_IA_NA_LEN 12 #define DHCP6_OPTION_IA_NA_LEN 12
#define DHCP6_OPTION_IA_TA_LEN 4 #define DHCP6_OPTION_IA_TA_LEN 4
typedef struct DHCP6Option {
be16_t code;
be16_t len;
uint8_t data[];
} _packed_ DHCP6Option;
static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode,
size_t optlen) { size_t optlen) {
DHCP6Option *option = (DHCP6Option*) *buf;
assert_return(buf, -EINVAL); assert_return(buf, -EINVAL);
assert_return(*buf, -EINVAL); assert_return(*buf, -EINVAL);
assert_return(buflen, -EINVAL); assert_return(buflen, -EINVAL);
if (optlen > 0xffff || *buflen < optlen + DHCP6_OPTION_HDR_LEN) if (optlen > 0xffff || *buflen < optlen + sizeof(DHCP6Option))
return -ENOBUFS; return -ENOBUFS;
(*buf)[0] = optcode >> 8; option->code = htobe16(optcode);
(*buf)[1] = optcode & 0xff; option->len = htobe16(optlen);
(*buf)[2] = optlen >> 8;
(*buf)[3] = optlen & 0xff;
*buf += DHCP6_OPTION_HDR_LEN; *buf += sizeof(DHCP6Option);
*buflen -= DHCP6_OPTION_HDR_LEN; *buflen -= sizeof(DHCP6Option);
return 0; return 0;
} }
@@ -104,8 +110,8 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
ia_hdr = *buf; ia_hdr = *buf;
ia_buflen = *buflen; ia_buflen = *buflen;
*buf += DHCP6_OPTION_HDR_LEN; *buf += sizeof(DHCP6Option);
*buflen -= DHCP6_OPTION_HDR_LEN; *buflen -= sizeof(DHCP6Option);
memcpy(*buf, &ia->id, len); memcpy(*buf, &ia->id, len);
@@ -123,7 +129,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
*buf += sizeof(addr->iaaddr); *buf += sizeof(addr->iaaddr);
*buflen -= sizeof(addr->iaaddr); *buflen -= sizeof(addr->iaaddr);
ia_addrlen += DHCP6_OPTION_HDR_LEN + sizeof(addr->iaaddr); ia_addrlen += sizeof(DHCP6Option) + sizeof(addr->iaaddr);
} }
r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen); r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen);
@@ -134,23 +140,23 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
} }
static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *opt, static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) {
size_t *optlen) { DHCP6Option *option = (DHCP6Option*) *buf;
uint16_t len; uint16_t len;
assert_return(buf, -EINVAL); assert_return(buf, -EINVAL);
assert_return(opt, -EINVAL); assert_return(optcode, -EINVAL);
assert_return(optlen, -EINVAL); assert_return(optlen, -EINVAL);
if (*buflen < 4) if (*buflen < sizeof(DHCP6Option))
return -ENOMSG; return -ENOMSG;
len = (*buf)[2] << 8 | (*buf)[3]; len = be16toh(option->len);
if (len > *buflen) if (len > *buflen)
return -ENOMSG; return -ENOMSG;
*opt = (*buf)[0] << 8 | (*buf)[1]; *optcode = be16toh(option->code);
*optlen = len; *optlen = len;
*buf += 4; *buf += 4;
@@ -194,7 +200,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
switch (iatype) { switch (iatype) {
case DHCP6_OPTION_IA_NA: case DHCP6_OPTION_IA_NA:
if (*buflen < DHCP6_OPTION_IA_NA_LEN + DHCP6_OPTION_HDR_LEN + if (*buflen < DHCP6_OPTION_IA_NA_LEN + sizeof(DHCP6Option) +
sizeof(addr->iaaddr)) { sizeof(addr->iaaddr)) {
r = -ENOBUFS; r = -ENOBUFS;
goto error; goto error;
@@ -216,7 +222,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
break; break;
case DHCP6_OPTION_IA_TA: case DHCP6_OPTION_IA_TA:
if (*buflen < DHCP6_OPTION_IA_TA_LEN + DHCP6_OPTION_HDR_LEN + if (*buflen < DHCP6_OPTION_IA_TA_LEN + sizeof(DHCP6Option) +
sizeof(addr->iaaddr)) { sizeof(addr->iaaddr)) {
r = -ENOBUFS; r = -ENOBUFS;
goto error; goto error;

View File

@@ -109,16 +109,16 @@ bool net_match_config(const struct ether_addr *match_mac,
const char *dev_type, const char *dev_type,
const char *dev_name) { const char *dev_name) {
if (match_host && !condition_test_host(match_host)) if (match_host && !condition_test(match_host))
return 0; return 0;
if (match_virt && !condition_test_virtualization(match_virt)) if (match_virt && !condition_test(match_virt))
return 0; return 0;
if (match_kernel && !condition_test_kernel_command_line(match_kernel)) if (match_kernel && !condition_test(match_kernel))
return 0; return 0;
if (match_arch && !condition_test_architecture(match_arch)) if (match_arch && !condition_test(match_arch))
return 0; return 0;
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN))) if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))

View File

@@ -29,7 +29,7 @@
#if 0 /* NM_IGNORED */ #if 0 /* NM_IGNORED */
#include "udev.h" #include "udev.h"
#include "condition-util.h" #include "condition.h"
bool net_match_config(const struct ether_addr *match_mac, bool net_match_config(const struct ether_addr *match_mac,
const char *match_path, const char *match_path,

View File

@@ -42,7 +42,7 @@
#include "dhcp-lease-internal.h" #include "dhcp-lease-internal.h"
#include "sd-dhcp-client.h" #include "sd-dhcp-client.h"
#define MAX_CLIENT_ID_LEN 32 #define MAX_CLIENT_ID_LEN 64 /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
struct sd_dhcp_client { struct sd_dhcp_client {
@@ -231,20 +231,25 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
return 0; return 0;
} }
const uint8_t *sd_dhcp_client_get_client_id(sd_dhcp_client *client, int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
uint8_t *type, const uint8_t **data, size_t *data_len) {
size_t *len) {
assert_return(client, NULL); assert_return(client, -EINVAL);
assert_return(type, NULL); assert_return(type, -EINVAL);
assert_return(len, NULL); assert_return(data, -EINVAL);
assert_return(data_len, -EINVAL);
if (!client->client_id_len) *type = 0;
return NULL; *data = NULL;
*data_len = 0;
if (client->client_id_len) {
*type = client->client_id.raw.type;
*data = client->client_id.raw.data;
*data_len = client->client_id_len -
sizeof (client->client_id.raw.type);
}
*type = client->client_id.raw.type; return 0;
*len = client->client_id_len - 1; /* -1 for sizeof(type) */
return (const uint8_t *) &client->client_id.raw.data;
} }
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
@@ -269,7 +274,7 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
break; break;
} }
if (client->client_id_len == data_len + 1 && if (client->client_id_len == data_len + sizeof (client->client_id.raw.type) &&
client->client_id.raw.type == type && client->client_id.raw.type == type &&
memcmp(&client->client_id.raw.data, data, data_len) == 0) memcmp(&client->client_id.raw.data, data, data_len) == 0)
return 0; return 0;
@@ -283,7 +288,7 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
client->client_id.raw.type = type; client->client_id.raw.type = type;
memcpy(&client->client_id.raw.data, data, data_len); memcpy(&client->client_id.raw.data, data, data_len);
client->client_id_len = data_len + 1; /* +1 for sizeof(type) */ client->client_id_len = data_len + sizeof (client->client_id.raw.type);
if (need_restart && client->state != DHCP_STATE_STOPPED) if (need_restart && client->state != DHCP_STATE_STOPPED)
sd_dhcp_client_start(client); sd_dhcp_client_start(client);
@@ -814,8 +819,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
if (r < 0) if (r < 0)
goto error; goto error;
r = sd_event_source_set_name(client->timeout_resend, r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
"dhcp4-resend-timer");
if (r < 0) if (r < 0)
goto error; goto error;
@@ -892,8 +896,7 @@ static int client_initialize_io_events(sd_dhcp_client *client,
if (r < 0) if (r < 0)
goto error; goto error;
r = sd_event_source_set_name(client->receive_message, r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
"dhcp4-receive-message");
if (r < 0) if (r < 0)
goto error; goto error;
@@ -923,8 +926,7 @@ static int client_initialize_time_events(sd_dhcp_client *client) {
r = sd_event_source_set_priority(client->timeout_resend, r = sd_event_source_set_priority(client->timeout_resend,
client->event_priority); client->event_priority);
r = sd_event_source_set_name(client->timeout_resend, r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
"dhcp4-resend-timer");
if (r < 0) if (r < 0)
goto error; goto error;
@@ -1035,7 +1037,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
if (client->client_id_len) { if (client->client_id_len) {
r = dhcp_lease_set_client_id(lease, r = dhcp_lease_set_client_id(lease,
(uint8_t *) &client->client_id, (uint8_t *) &client->client_id.raw,
client->client_id_len); client->client_id_len);
if (r < 0) if (r < 0)
return r; return r;
@@ -1102,7 +1104,7 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
if (client->client_id_len) { if (client->client_id_len) {
r = dhcp_lease_set_client_id(lease, r = dhcp_lease_set_client_id(lease,
(uint8_t *) &client->client_id, (uint8_t *) &client->client_id.raw,
client->client_id_len); client->client_id_len);
if (r < 0) if (r < 0)
return r; return r;
@@ -1254,8 +1256,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_name(client->timeout_expire, r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
"dhcp4-lifetime");
if (r < 0) if (r < 0)
return r; return r;
@@ -1282,8 +1283,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_name(client->timeout_t2, r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
"dhcp4-t2-timeout");
if (r < 0) if (r < 0)
return r; return r;
@@ -1309,8 +1309,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_name(client->timeout_t1, r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
"dhcp4-t1-timer");
if (r < 0) if (r < 0)
return r; return r;
@@ -1355,8 +1354,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
if (r < 0) if (r < 0)
goto error; goto error;
r = sd_event_source_set_name(client->timeout_resend, r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
"dhcp4-resend-timer");
if (r < 0) if (r < 0)
goto error; goto error;
} else if (r == -ENOMSG) } else if (r == -ENOMSG)

View File

@@ -36,6 +36,7 @@
#include "mkdir.h" #include "mkdir.h"
#endif #endif
#include "fileio.h" #include "fileio.h"
#include "unaligned.h"
#include "in-addr-util.h" #include "in-addr-util.h"
#include "dhcp-protocol.h" #include "dhcp-protocol.h"
@@ -212,14 +213,11 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
} }
static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) { static void lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
be32_t val;
assert(option); assert(option);
assert(ret); assert(ret);
if (len == 4) { if (len == 4) {
memcpy(&val, option, 4); *ret = unaligned_read_be32((be32_t*) option);
*ret = be32toh(val);
if (*ret < min) if (*ret < min)
*ret = min; *ret = min;
@@ -231,14 +229,11 @@ static void lease_parse_s32(const uint8_t *option, size_t len, int32_t *ret) {
} }
static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) { static void lease_parse_u16(const uint8_t *option, size_t len, uint16_t *ret, uint16_t min) {
be16_t val;
assert(option); assert(option);
assert(ret); assert(ret);
if (len == 2) { if (len == 2) {
memcpy(&val, option, 2); *ret = unaligned_read_be16((be16_t*) option);
*ret = be16toh(val);
if (*ret < min) if (*ret < min)
*ret = min; *ret = min;
@@ -322,23 +317,6 @@ static int lease_parse_in_addrs_pairs(const uint8_t *option, size_t len, struct
return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2); return lease_parse_in_addrs_aux(option, len, ret, ret_size, 2);
} }
static int class_prefixlen(uint8_t msb_octet, uint8_t *ret) {
if (msb_octet < 128)
/* Class A */
*ret = 8;
else if (msb_octet < 192)
/* Class B */
*ret = 16;
else if (msb_octet < 224)
/* Class C */
*ret = 24;
else
/* Class D or E -- no subnet mask */
return -ERANGE;
return 0;
}
static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes, static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
size_t *routes_size, size_t *routes_allocated) { size_t *routes_size, size_t *routes_allocated) {
@@ -360,8 +338,10 @@ static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_
while (len >= 8) { while (len >= 8) {
struct sd_dhcp_route *route = *routes + *routes_size; struct sd_dhcp_route *route = *routes + *routes_size;
int r;
if (class_prefixlen(*option, &route->dst_prefixlen) < 0) { r = in_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen);
if (r < 0) {
log_error("Failed to determine destination prefix length from class based IP, ignoring"); log_error("Failed to determine destination prefix length from class based IP, ignoring");
continue; continue;
} }
@@ -716,7 +696,7 @@ finish:
return r; return r;
} }
int sd_dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) { int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
_cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL; _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
_cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL, _cleanup_free_ char *address = NULL, *router = NULL, *netmask = NULL,
*server_address = NULL, *next_server = NULL, *server_address = NULL, *next_server = NULL,

View File

@@ -597,8 +597,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
if (r < 0) if (r < 0)
goto error; goto error;
r = sd_event_source_set_name(client->timeout_resend, r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer");
"dhcp6-resend-timer");
if (r < 0) if (r < 0)
goto error; goto error;
@@ -621,8 +620,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
if (r < 0) if (r < 0)
goto error; goto error;
r = sd_event_source_set_name(client->timeout_resend_expire, r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer");
"dhcp6-resend-expire-timer");
if (r < 0) if (r < 0)
goto error; goto error;
} }
@@ -994,8 +992,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_name(client->receive_message, r = sd_event_source_set_description(client->receive_message, "dhcp6-receive-message");
"dhcp6-receive-message");
if (r < 0) if (r < 0)
return r; return r;
@@ -1043,8 +1040,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_name(client->lease->ia.timeout_t1, r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
"dhcp6-t1-timeout");
if (r < 0) if (r < 0)
return r; return r;
@@ -1068,8 +1064,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_name(client->lease->ia.timeout_t2, r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
"dhcp6-t2-timeout");
if (r < 0) if (r < 0)
return r; return r;
@@ -1092,8 +1087,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_source_set_name(client->timeout_resend, r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout");
"dhcp6-resend-timeout");
if (r < 0) if (r < 0)
return r; return r;

View File

@@ -22,12 +22,12 @@
#include "config.h" #include "config.h"
#include <unistd.h> #include <unistd.h>
#include <sys/sendfile.h>
#include "fileio.h"
#include "util.h" #include "util.h"
#include "strv.h" #include "strv.h"
#include "utf8.h" #include "utf8.h"
#include "ctype.h" #include "ctype.h"
#include "fileio.h"
int write_string_stream(FILE *f, const char *line) { int write_string_stream(FILE *f, const char *line) {
assert(f); assert(f);
@@ -68,7 +68,7 @@ int write_string_file_no_create(const char *fn, const char *line) {
assert(line); assert(line);
/* We manually build our own version of fopen(..., "we") that /* We manually build our own version of fopen(..., "we") that
* without O_CREAT */ * works without O_CREAT */
fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY); fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0) if (fd < 0)
return -errno; return -errno;
@@ -96,20 +96,10 @@ int write_string_file_atomic(const char *fn, const char *line) {
fchmod_umask(fileno(f), 0644); fchmod_umask(fileno(f), 0644);
errno = 0; r = write_string_stream(f, line);
fputs(line, f); if (r >= 0) {
if (!endswith(line, "\n"))
fputc('\n', f);
fflush(f);
if (ferror(f))
r = errno ? -errno : -EIO;
else {
if (rename(p, fn) < 0) if (rename(p, fn) < 0)
r = -errno; r = -errno;
else
r = 0;
} }
if (r < 0) if (r < 0)
@@ -146,77 +136,6 @@ int read_one_line_file(const char *fn, char **line) {
return 0; return 0;
} }
ssize_t sendfile_full(int out_fd, const char *fn) {
_cleanup_fclose_ FILE *f = NULL;
struct stat st;
int r;
ssize_t s;
size_t n, l;
_cleanup_free_ char *buf = NULL;
assert(out_fd > 0);
assert(fn);
f = fopen(fn, "re");
if (!f)
return -errno;
r = fstat(fileno(f), &st);
if (r < 0)
return -errno;
s = sendfile(out_fd, fileno(f), NULL, st.st_size);
if (s < 0)
if (errno == EINVAL || errno == ENOSYS) {
/* continue below */
} else
return -errno;
else
return s;
/* sendfile() failed, fall back to read/write */
/* Safety check */
if (st.st_size > 4*1024*1024)
return -E2BIG;
n = st.st_size > 0 ? st.st_size : LINE_MAX;
l = 0;
while (true) {
char *t;
size_t k;
t = realloc(buf, n);
if (!t)
return -ENOMEM;
buf = t;
k = fread(buf + l, 1, n - l, f);
if (k <= 0) {
if (ferror(f))
return -errno;
break;
}
l += k;
n *= 2;
/* Safety check */
if (n > 4*1024*1024)
return -E2BIG;
}
r = write(out_fd, buf, l);
if (r < 0)
return -errno;
return (ssize_t) l;
}
int read_full_stream(FILE *f, char **contents, size_t *size) { int read_full_stream(FILE *f, char **contents, size_t *size) {
size_t n, l; size_t n, l;
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;

View File

@@ -33,7 +33,6 @@ int write_string_file_atomic(const char *fn, const char *line);
int read_one_line_file(const char *fn, char **line); int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size); int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size); int read_full_stream(FILE *f, char **contents, size_t *size);
ssize_t sendfile_full(int out_fd, const char *fn);
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l); int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);

View File

@@ -252,21 +252,20 @@ unsigned in_addr_netmask_to_prefixlen(const struct in_addr *addr) {
} }
int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) { int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen) {
uint32_t address; uint8_t msb_octet = *(uint8_t*) addr;
/* addr may not be aligned, so make sure we only access it byte-wise */
assert(addr); assert(addr);
assert(addr->s_addr != INADDR_ANY);
assert(prefixlen); assert(prefixlen);
address = be32toh(addr->s_addr); if (msb_octet < 128)
if ((address >> 31) == 0x0)
/* class A, leading bits: 0 */ /* class A, leading bits: 0 */
*prefixlen = 8; *prefixlen = 8;
else if ((address >> 30) == 0x2) else if (msb_octet < 192)
/* class B, leading bits 10 */ /* class B, leading bits 10 */
*prefixlen = 16; *prefixlen = 16;
else if ((address >> 29) == 0x6) else if (msb_octet < 224)
/* class C, leading bits 110 */ /* class C, leading bits 110 */
*prefixlen = 24; *prefixlen = 24;
else else

View File

@@ -252,40 +252,6 @@ char **strv_split(const char *s, const char *separator) {
return r; return r;
} }
int strv_split_quoted(char ***t, const char *s) {
const char *word, *state;
size_t l;
unsigned n, i;
char **r;
assert(s);
n = 0;
FOREACH_WORD_QUOTED(word, l, s, state)
n++;
if (!isempty(state))
/* bad syntax */
return -EINVAL;
r = new(char*, n+1);
if (!r)
return -ENOMEM;
i = 0;
FOREACH_WORD_QUOTED(word, l, s, state) {
r[i] = cunescape_length(word, l);
if (!r[i]) {
strv_free(r);
return -ENOMEM;
}
i++;
}
r[i] = NULL;
*t = r;
return 0;
}
char **strv_split_newlines(const char *s) { char **strv_split_newlines(const char *s) {
char **l; char **l;
unsigned n; unsigned n;
@@ -311,6 +277,43 @@ char **strv_split_newlines(const char *s) {
return l; return l;
} }
#if 0 /* NM_IGNORED */
int strv_split_quoted(char ***t, const char *s, bool relax) {
size_t n = 0, allocated = 0;
_cleanup_strv_free_ char **l = NULL;
int r;
assert(t);
assert(s);
for (;;) {
_cleanup_free_ char *word = NULL;
r = unquote_first_word(&s, &word, relax);
if (r < 0)
return r;
if (r == 0)
break;
if (!GREEDY_REALLOC(l, allocated, n + 2))
return -ENOMEM;
l[n++] = word;
word = NULL;
l[n] = NULL;
}
if (!l)
l = new0(char*, 1);
*t = l;
l = NULL;
return 0;
}
#endif
char *strv_join(char **l, const char *separator) { char *strv_join(char **l, const char *separator) {
char *r, *e; char *r, *e;
char **s; char **s;

View File

@@ -63,9 +63,10 @@ static inline bool strv_isempty(char * const *l) {
} }
char **strv_split(const char *s, const char *separator); char **strv_split(const char *s, const char *separator);
int strv_split_quoted(char ***t, const char *s);
char **strv_split_newlines(const char *s); char **strv_split_newlines(const char *s);
int strv_split_quoted(char ***t, const char *s, bool relax);
char *strv_join(char **l, const char *separator); char *strv_join(char **l, const char *separator);
char *strv_join_quoted(char **l); char *strv_join_quoted(char **l);

View File

@@ -0,0 +1,66 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2014 Tom Gundersen
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 <stdint.h>
static inline uint16_t unaligned_read_be16(const void *_u) {
const uint8_t *u = _u;
return (((uint16_t) u[0]) << 8) |
((uint16_t) u[1]);
}
static inline uint32_t unaligned_read_be32(const void *_u) {
const uint8_t *u = _u;
return (((uint32_t) unaligned_read_be16(u)) << 16) |
((uint32_t) unaligned_read_be16(u + 2));
}
static inline uint64_t unaligned_read_be64(const void *_u) {
const uint8_t *u = _u;
return (((uint64_t) unaligned_read_be32(u)) << 32) |
((uint64_t) unaligned_read_be32(u + 4));
}
static inline void unaligned_write_be16(void *_u, uint16_t a) {
uint8_t *u = _u;
u[0] = (uint8_t) (a >> 8);
u[1] = (uint8_t) a;
}
static inline void unaligned_write_be32(void *_u, uint32_t a) {
uint8_t *u = _u;
unaligned_write_be16(u, (uint16_t) (a >> 16));
unaligned_write_be16(u + 2, (uint16_t) a);
}
static inline void unaligned_write_be64(void *_u, uint64_t a) {
uint8_t *u = _u;
unaligned_write_be32(u, (uint32_t) (a >> 32));
unaligned_write_be32(u + 4, (uint32_t) a);
}

View File

@@ -154,10 +154,12 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
int encoded_len, val; int encoded_len, val;
encoded_len = utf8_encoded_valid_unichar((const char *) p); encoded_len = utf8_encoded_valid_unichar((const char *) p);
val = utf8_encoded_to_unichar((const char*) p);
if (encoded_len < 0 || if (encoded_len < 0 ||
val < 0 || (size_t) encoded_len > length)
return false;
val = utf8_encoded_to_unichar((const char*) p);
if (val < 0 ||
is_unicode_control(val) || is_unicode_control(val) ||
(!newline && val == '\n')) (!newline && val == '\n'))
return false; return false;

View File

@@ -374,6 +374,46 @@ int safe_atou8(const char *s, uint8_t *ret) {
return 0; return 0;
} }
int safe_atou16(const char *s, uint16_t *ret) {
char *x = NULL;
unsigned long l;
assert(s);
assert(ret);
errno = 0;
l = strtoul(s, &x, 0);
if (!x || x == s || *x || errno)
return errno > 0 ? -errno : -EINVAL;
if ((unsigned long) (uint16_t) l != l)
return -ERANGE;
*ret = (uint16_t) l;
return 0;
}
int safe_atoi16(const char *s, int16_t *ret) {
char *x = NULL;
long l;
assert(s);
assert(ret);
errno = 0;
l = strtol(s, &x, 0);
if (!x || x == s || *x || errno)
return errno > 0 ? -errno : -EINVAL;
if ((long) (int16_t) l != l)
return -ERANGE;
*ret = (int16_t) l;
return 0;
}
int safe_atollu(const char *s, long long unsigned *ret_llu) { int safe_atollu(const char *s, long long unsigned *ret_llu) {
char *x = NULL; char *x = NULL;
unsigned long long l; unsigned long long l;
@@ -710,7 +750,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
} }
/* Kernel threads have no argv[] */ /* Kernel threads have no argv[] */
if (r == NULL || r[0] == 0) { if (isempty(r)) {
_cleanup_free_ char *t = NULL; _cleanup_free_ char *t = NULL;
int h; int h;
@@ -910,6 +950,28 @@ int readlink_malloc(const char *p, char **ret) {
return readlinkat_malloc(AT_FDCWD, p, ret); return readlinkat_malloc(AT_FDCWD, p, ret);
} }
int readlink_value(const char *p, char **ret) {
_cleanup_free_ char *link = NULL;
char *value;
int r;
r = readlink_malloc(p, &link);
if (r < 0)
return r;
value = basename(link);
if (!value)
return -ENOENT;
value = strdup(value);
if (!value)
return -ENOMEM;
*ret = value;
return 0;
}
int readlink_and_make_absolute(const char *p, char **r) { int readlink_and_make_absolute(const char *p, char **r) {
_cleanup_free_ char *target = NULL; _cleanup_free_ char *target = NULL;
char *k; char *k;
@@ -2492,14 +2554,58 @@ char* dirname_malloc(const char *path) {
#endif #endif
int dev_urandom(void *p, size_t n) { int dev_urandom(void *p, size_t n) {
_cleanup_close_ int fd = -1; #if 0 /* NM_IGNORED */
static int have_syscall = -1;
int r, fd;
ssize_t k; ssize_t k;
/* Gathers some randomness from the kernel. This call will
* never block, and will always return some data from the
* kernel, regardless if the random pool is fully initialized
* or not. It thus makes no guarantee for the quality of the
* returned entropy, but is good enough for or usual usecases
* of seeding the hash functions for hashtable */
/* Use the getrandom() syscall unless we know we don't have
* it, or when the requested size is too large for it. */
if (have_syscall != 0 || (size_t) (int) n != n) {
r = getrandom(p, n, GRND_NONBLOCK);
if (r == (int) n) {
have_syscall = true;
return 0;
}
if (r < 0) {
if (errno == ENOSYS)
/* we lack the syscall, continue with
* reading from /dev/urandom */
have_syscall = false;
else if (errno == EAGAIN)
/* not enough entropy for now. Let's
* remember to use the syscall the
* next time, again, but also read
* from /dev/urandom for now, which
* doesn't care about the current
* amount of entropy. */
have_syscall = true;
else
return -errno;
} else
/* too short read? */
return -EIO;
}
#else /* NM IGNORED */
int fd;
ssize_t k;
#endif
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0) if (fd < 0)
return errno == ENOENT ? -ENOSYS : -errno; return errno == ENOENT ? -ENOSYS : -errno;
k = loop_read(fd, p, n, true); k = loop_read(fd, p, n, true);
safe_close(fd);
if (k < 0) if (k < 0)
return (int) k; return (int) k;
if ((size_t) k != n) if ((size_t) k != n)
@@ -2508,8 +2614,36 @@ int dev_urandom(void *p, size_t n) {
return 0; return 0;
} }
void random_bytes(void *p, size_t n) { void initialize_srand(void) {
static bool srand_called = false; static bool srand_called = false;
unsigned x;
#ifdef HAVE_SYS_AUXV_H
void *auxv;
#endif
if (srand_called)
return;
x = 0;
#ifdef HAVE_SYS_AUXV_H
/* The kernel provides us with a bit of entropy in auxv, so
* let's try to make use of that to seed the pseudo-random
* generator. It's better than nothing... */
auxv = (void*) getauxval(AT_RANDOM);
if (auxv)
x ^= *(unsigned*) auxv;
#endif
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
srand(x);
srand_called = true;
}
void random_bytes(void *p, size_t n) {
uint8_t *q; uint8_t *q;
int r; int r;
@@ -2520,28 +2654,7 @@ void random_bytes(void *p, size_t n) {
/* If some idiot made /dev/urandom unavailable to us, he'll /* If some idiot made /dev/urandom unavailable to us, he'll
* get a PRNG instead. */ * get a PRNG instead. */
if (!srand_called) { initialize_srand();
unsigned x = 0;
#ifdef HAVE_SYS_AUXV_H
/* The kernel provides us with a bit of entropy in
* auxv, so let's try to make use of that to seed the
* pseudo-random generator. It's better than
* nothing... */
void *auxv;
auxv = (void*) getauxval(AT_RANDOM);
if (auxv)
x ^= *(unsigned*) auxv;
#endif
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
srand(x);
srand_called = true;
}
for (q = p; q < (uint8_t*) p + n; q ++) for (q = p; q < (uint8_t*) p + n; q ++)
*q = rand(); *q = rand();
@@ -2764,7 +2877,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
if (k < 0) if (k < 0)
return k; return k;
snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr)); sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
k = readlink_malloc(fn, &s); k = readlink_malloc(fn, &s);
if (k < 0) { if (k < 0) {
@@ -2922,6 +3035,19 @@ int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root
return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev); return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
} }
static int file_is_priv_sticky(const char *p) {
struct stat st;
assert(p);
if (lstat(p, &st) < 0)
return -errno;
return
(st.st_uid == 0 || st.st_uid == getuid()) &&
(st.st_mode & S_ISVTX);
}
static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) { static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
int fd, r; int fd, r;
struct statfs s; struct statfs s;
@@ -3160,7 +3286,8 @@ char *replace_env(const char *format, char **env) {
case CURLY: case CURLY:
if (*e == '{') { if (*e == '{') {
if (!(k = strnappend(r, word, e-word-1))) k = strnappend(r, word, e-word-1);
if (!k)
goto fail; goto fail;
free(r); free(r);
@@ -3170,7 +3297,8 @@ char *replace_env(const char *format, char **env) {
state = VARIABLE; state = VARIABLE;
} else if (*e == '$') { } else if (*e == '$') {
if (!(k = strnappend(r, word, e-word))) k = strnappend(r, word, e-word);
if (!k)
goto fail; goto fail;
free(r); free(r);
@@ -3202,7 +3330,8 @@ char *replace_env(const char *format, char **env) {
} }
} }
if (!(k = strnappend(r, word, e-word))) k = strnappend(r, word, e-word);
if (!k)
goto fail; goto fail;
free(r); free(r);
@@ -3213,6 +3342,7 @@ fail:
return NULL; return NULL;
} }
#if 0 /* NM_IGNORED */
char **replace_env_argv(char **argv, char **env) { char **replace_env_argv(char **argv, char **env) {
char **ret, **i; char **ret, **i;
unsigned k = 0, l = 0; unsigned k = 0, l = 0;
@@ -3235,7 +3365,7 @@ char **replace_env_argv(char **argv, char **env) {
if (e) { if (e) {
int r; int r;
r = strv_split_quoted(&m, e); r = strv_split_quoted(&m, e, true);
if (r < 0) { if (r < 0) {
ret[k] = NULL; ret[k] = NULL;
strv_free(ret); strv_free(ret);
@@ -3277,6 +3407,7 @@ char **replace_env_argv(char **argv, char **env) {
ret[k] = NULL; ret[k] = NULL;
return ret; return ret;
} }
#endif
int fd_columns(int fd) { int fd_columns(int fd) {
struct winsize ws = {}; struct winsize ws = {};
@@ -3556,41 +3687,33 @@ char *unquote(const char *s, const char* quotes) {
} }
char *normalize_env_assignment(const char *s) { char *normalize_env_assignment(const char *s) {
_cleanup_free_ char *name = NULL, *value = NULL, *p = NULL; _cleanup_free_ char *value = NULL;
char *eq, *r; const char *eq;
char *p, *name;
eq = strchr(s, '='); eq = strchr(s, '=');
if (!eq) { if (!eq) {
char *t; char *r, *t;
r = strdup(s); r = strdup(s);
if (!r) if (!r)
return NULL; return NULL;
t = strstrip(r); t = strstrip(r);
if (t == r) if (t != r)
return r; memmove(r, t, strlen(t) + 1);
memmove(r, t, strlen(t) + 1);
return r; return r;
} }
name = strndup(s, eq - s); name = strndupa(s, eq - s);
if (!name) p = strdupa(eq + 1);
return NULL;
p = strdup(eq + 1);
if (!p)
return NULL;
value = unquote(strstrip(p), QUOTES); value = unquote(strstrip(p), QUOTES);
if (!value) if (!value)
return NULL; return NULL;
if (asprintf(&r, "%s=%s", strstrip(name), value) < 0) return strjoin(strstrip(name), "=", value, NULL);
r = NULL;
return r;
} }
int wait_for_terminate(pid_t pid, siginfo_t *status) { int wait_for_terminate(pid_t pid, siginfo_t *status) {
@@ -4813,19 +4936,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
return -ENOENT; return -ENOENT;
} }
int file_is_priv_sticky(const char *p) {
struct stat st;
assert(p);
if (lstat(p, &st) < 0)
return -errno;
return
(st.st_uid == 0 || st.st_uid == getuid()) &&
(st.st_mode & S_ISVTX);
}
static const char *const ioprio_class_table[] = { static const char *const ioprio_class_table[] = {
[IOPRIO_CLASS_NONE] = "none", [IOPRIO_CLASS_NONE] = "none",
[IOPRIO_CLASS_RT] = "realtime", [IOPRIO_CLASS_RT] = "realtime",
@@ -6136,27 +6246,28 @@ int split_pair(const char *s, const char *sep, char **l, char **r) {
int shall_restore_state(void) { int shall_restore_state(void) {
_cleanup_free_ char *line = NULL; _cleanup_free_ char *line = NULL;
const char *word, *state; const char *p;
size_t l;
int r; int r;
r = proc_cmdline(&line); r = proc_cmdline(&line);
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) /* Container ... */
return 1;
r = 1; r = 1;
p = line;
FOREACH_WORD_QUOTED(word, l, line, state) { for (;;) {
_cleanup_free_ char *word = NULL;
const char *e; const char *e;
char n[l+1];
int k; int k;
memcpy(n, word, l); k = unquote_first_word(&p, &word, true);
n[l] = 0; if (k < 0)
return k;
if (k == 0)
break;
e = startswith(n, "systemd.restore_state="); e = startswith(word, "systemd.restore_state=");
if (!e) if (!e)
continue; continue;
@@ -6169,51 +6280,35 @@ int shall_restore_state(void) {
} }
int proc_cmdline(char **ret) { int proc_cmdline(char **ret) {
int r; assert(ret);
if (detect_container(NULL) > 0) { if (detect_container(NULL) > 0)
char *buf = NULL, *p; return get_process_cmdline(1, 0, false, ret);
size_t sz = 0; else
return read_one_line_file("/proc/cmdline", ret);
r = read_full_file("/proc/1/cmdline", &buf, &sz);
if (r < 0)
return r;
for (p = buf; p + 1 < buf + sz; p++)
if (*p == 0)
*p = ' ';
*p = 0;
*ret = buf;
return 1;
}
r = read_one_line_file("/proc/cmdline", ret);
if (r < 0)
return r;
return 1;
} }
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) { int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
_cleanup_free_ char *line = NULL; _cleanup_free_ char *line = NULL;
const char *w, *state; const char *p;
size_t l;
int r; int r;
assert(parse_item); assert(parse_item);
r = proc_cmdline(&line); r = proc_cmdline(&line);
if (r < 0) if (r < 0)
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r)); return r;
if (r <= 0)
return 0;
FOREACH_WORD_QUOTED(w, l, line, state) { p = line;
char word[l+1], *value; for (;;) {
_cleanup_free_ char *word = NULL;
char *value = NULL;
memcpy(word, w, l); r = unquote_first_word(&p, &word, true);
word[l] = 0; if (r < 0)
return r;
if (r == 0)
break;
/* Filter out arguments that are intended only for the /* Filter out arguments that are intended only for the
* initrd */ * initrd */
@@ -6983,19 +7078,19 @@ int is_symlink(const char *path) {
int is_dir(const char* path, bool follow) { int is_dir(const char* path, bool follow) {
struct stat st; struct stat st;
int r;
if (follow) { if (follow)
if (stat(path, &st) < 0) r = stat(path, &st);
return -errno; else
} else { r = lstat(path, &st);
if (lstat(path, &st) < 0) if (r < 0)
return -errno; return -errno;
}
return !!S_ISDIR(st.st_mode); return !!S_ISDIR(st.st_mode);
} }
int unquote_first_word(const char **p, char **ret) { int unquote_first_word(const char **p, char **ret, bool relax) {
_cleanup_free_ char *s = NULL; _cleanup_free_ char *s = NULL;
size_t allocated = 0, sz = 0; size_t allocated = 0, sz = 0;
@@ -7054,8 +7149,11 @@ int unquote_first_word(const char **p, char **ret) {
break; break;
case VALUE_ESCAPE: case VALUE_ESCAPE:
if (c == 0) if (c == 0) {
if (relax)
goto finish;
return -EINVAL; return -EINVAL;
}
if (!GREEDY_REALLOC(s, allocated, sz+2)) if (!GREEDY_REALLOC(s, allocated, sz+2))
return -ENOMEM; return -ENOMEM;
@@ -7066,9 +7164,11 @@ int unquote_first_word(const char **p, char **ret) {
break; break;
case SINGLE_QUOTE: case SINGLE_QUOTE:
if (c == 0) if (c == 0) {
if (relax)
goto finish;
return -EINVAL; return -EINVAL;
else if (c == '\'') } else if (c == '\'')
state = VALUE; state = VALUE;
else if (c == '\\') else if (c == '\\')
state = SINGLE_QUOTE_ESCAPE; state = SINGLE_QUOTE_ESCAPE;
@@ -7082,8 +7182,11 @@ int unquote_first_word(const char **p, char **ret) {
break; break;
case SINGLE_QUOTE_ESCAPE: case SINGLE_QUOTE_ESCAPE:
if (c == 0) if (c == 0) {
if (relax)
goto finish;
return -EINVAL; return -EINVAL;
}
if (!GREEDY_REALLOC(s, allocated, sz+2)) if (!GREEDY_REALLOC(s, allocated, sz+2))
return -ENOMEM; return -ENOMEM;
@@ -7109,8 +7212,11 @@ int unquote_first_word(const char **p, char **ret) {
break; break;
case DOUBLE_QUOTE_ESCAPE: case DOUBLE_QUOTE_ESCAPE:
if (c == 0) if (c == 0) {
if (relax)
goto finish;
return -EINVAL; return -EINVAL;
}
if (!GREEDY_REALLOC(s, allocated, sz+2)) if (!GREEDY_REALLOC(s, allocated, sz+2))
return -ENOMEM; return -ENOMEM;
@@ -7170,7 +7276,7 @@ int unquote_many_words(const char **p, ...) {
l = newa0(char*, n); l = newa0(char*, n);
for (c = 0; c < n; c++) { for (c = 0; c < n; c++) {
r = unquote_first_word(p, &l[c]); r = unquote_first_word(p, &l[c], false);
if (r < 0) { if (r < 0) {
int j; int j;

View File

@@ -251,6 +251,9 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) {
return safe_atolli(s, (long long int*) ret_i); return safe_atolli(s, (long long int*) ret_i);
} }
int safe_atou16(const char *s, uint16_t *ret);
int safe_atoi16(const char *s, int16_t *ret);
const char* split(const char **state, size_t *l, const char *separator, bool quoted); const char* split(const char **state, size_t *l, const char *separator, bool quoted);
#define FOREACH_WORD(word, length, s, state) \ #define FOREACH_WORD(word, length, s, state) \
@@ -276,6 +279,7 @@ char **replace_env_argv(char **argv, char **env);
int readlinkat_malloc(int fd, const char *p, char **ret); int readlinkat_malloc(int fd, const char *p, char **ret);
int readlink_malloc(const char *p, char **r); int readlink_malloc(const char *p, char **r);
int readlink_value(const char *p, char **ret);
int readlink_and_make_absolute(const char *p, char **r); int readlink_and_make_absolute(const char *p, char **r);
int readlink_and_canonicalize(const char *p, char **r); int readlink_and_canonicalize(const char *p, char **r);
@@ -327,6 +331,7 @@ int make_console_stdio(void);
int dev_urandom(void *p, size_t n); int dev_urandom(void *p, size_t n);
void random_bytes(void *p, size_t n); void random_bytes(void *p, size_t n);
void initialize_srand(void);
static inline uint64_t random_u64(void) { static inline uint64_t random_u64(void) {
uint64_t u; uint64_t u;
@@ -587,8 +592,6 @@ static inline bool _pure_ in_charset(const char *s, const char* charset) {
int block_get_whole_disk(dev_t d, dev_t *ret); int block_get_whole_disk(dev_t d, dev_t *ret);
int file_is_priv_sticky(const char *p);
#define NULSTR_FOREACH(i, l) \ #define NULSTR_FOREACH(i, l) \
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1) for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
@@ -799,6 +802,15 @@ static inline void _reset_errno_(int *saved_errno) {
#define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno #define PROTECT_ERRNO _cleanup_(_reset_errno_) __attribute__((unused)) int _saved_errno_ = errno
static inline int negative_errno(void) {
/* This helper should be used to shut up gcc if you know 'errno' is
* negative. Instead of "return -errno;", use "return negative_errno();"
* It will suppress bogus gcc warnings in case it assumes 'errno' might
* be 0 and thus the caller's error-handling might not be triggered. */
assert_return(errno > 0, -EINVAL);
return -errno;
}
struct _umask_struct_ { struct _umask_struct_ {
mode_t mask; mode_t mask;
bool quit; bool quit;
@@ -835,6 +847,21 @@ static inline int log2i(int x) {
return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1; return __SIZEOF_INT__ * 8 - __builtin_clz(x) - 1;
} }
static inline unsigned log2u(unsigned x) {
assert(x > 0);
return sizeof(unsigned) * 8 - __builtin_clz(x) - 1;
}
static inline unsigned log2u_round_up(unsigned x) {
assert(x > 0);
if (x == 1)
return 0;
return log2u(x - 1) + 1;
}
static inline bool logind_running(void) { static inline bool logind_running(void) {
return access("/run/systemd/seats/", F_OK) >= 0; return access("/run/systemd/seats/", F_OK) >= 0;
} }
@@ -1003,7 +1030,7 @@ int take_password_lock(const char *root);
int is_symlink(const char *path); int is_symlink(const char *path);
int is_dir(const char *path, bool follow); int is_dir(const char *path, bool follow);
int unquote_first_word(const char **p, char **ret); int unquote_first_word(const char **p, char **ret, bool relax);
int unquote_many_words(const char **p, ...) _sentinel_; int unquote_many_words(const char **p, ...) _sentinel_;
int free_and_strdup(char **p, const char *s); int free_and_strdup(char **p, const char *s);

View File

@@ -53,9 +53,8 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
size_t addr_len, uint16_t arp_type); size_t addr_len, uint16_t arp_type);
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
const uint8_t *data, size_t data_len); const uint8_t *data, size_t data_len);
const uint8_t *sd_dhcp_client_get_client_id(sd_dhcp_client *client, int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
uint8_t *type, const uint8_t **data, size_t *data_len);
size_t *len);
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu); int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname); int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname);
int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci); int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci);

View File

@@ -49,6 +49,6 @@ int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
size_t *client_id_len); size_t *client_id_len);
int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
int sd_dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret); int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
#endif #endif

View File

@@ -109,8 +109,8 @@ sd_event *sd_event_source_get_event(sd_event_source *s);
void* sd_event_source_get_userdata(sd_event_source *s); void* sd_event_source_get_userdata(sd_event_source *s);
void* sd_event_source_set_userdata(sd_event_source *s, void *userdata); void* sd_event_source_set_userdata(sd_event_source *s, void *userdata);
int sd_event_source_set_name(sd_event_source *s, const char *name); int sd_event_source_set_description(sd_event_source *s, const char *description);
int sd_event_source_get_name(sd_event_source *s, const char **name); int sd_event_source_get_description(sd_event_source *s, const char **description);
int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback); int sd_event_source_set_prepare(sd_event_source *s, sd_event_handler_t callback);
int sd_event_source_get_pending(sd_event_source *s); int sd_event_source_get_pending(sd_event_source *s);
int sd_event_source_get_priority(sd_event_source *s, int64_t *priority); int sd_event_source_get_priority(sd_event_source *s, int64_t *priority);