Commit e2e4637c authored by Dan Winship's avatar Dan Winship

dhcp: update systemd DHCP code

This is a direct dump from systemd git on 2014-11-19, git commit
a4962513.  Only relevant files were included.

    SYSTEMD_DIR=../systemd
    COMMIT=a4962513c555fe3ac4b5bebf97a71701361a45b0

    (
       cd "$SYSTEMD_DIR"
       git checkout "$COMMIT"
       git clean -fdx
    )
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp-internal.h ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-internal.h
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp-lease-internal.h ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-lease-internal.h
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp-network.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-network.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp-option.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-option.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp-packet.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-packet.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp-protocol.h ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp-protocol.h
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp6-internal.h ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp6-internal.h
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp6-lease-internal.h ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp6-lease-internal.h
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp6-network.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp6-network.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp6-option.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp6-option.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/dhcp6-protocol.h ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/dhcp6-protocol.h
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/network-internal.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/network-internal.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/network-internal.h ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/network-internal.h
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/sd-dhcp-client.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-client.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/sd-dhcp-lease.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp-lease.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/sd-dhcp6-client.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-client.c
    /bin/cp "$SYSTEMD_DIR"/src/libsystemd-network/sd-dhcp6-lease.c ./src/dhcp-manager/systemd-dhcp/src/libsystemd-network/sd-dhcp6-lease.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/async.h ./src/dhcp-manager/systemd-dhcp/src/shared/async.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/fileio.c ./src/dhcp-manager/systemd-dhcp/src/shared/fileio.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/fileio.h ./src/dhcp-manager/systemd-dhcp/src/shared/fileio.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/list.h ./src/dhcp-manager/systemd-dhcp/src/shared/list.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/macro.h ./src/dhcp-manager/systemd-dhcp/src/shared/macro.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/refcnt.h ./src/dhcp-manager/systemd-dhcp/src/shared/refcnt.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/siphash24.c ./src/dhcp-manager/systemd-dhcp/src/shared/siphash24.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/siphash24.h ./src/dhcp-manager/systemd-dhcp/src/shared/siphash24.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/socket-util.h ./src/dhcp-manager/systemd-dhcp/src/shared/socket-util.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/sparse-endian.h ./src/dhcp-manager/systemd-dhcp/src/shared/sparse-endian.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/strv.c ./src/dhcp-manager/systemd-dhcp/src/shared/strv.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/strv.h ./src/dhcp-manager/systemd-dhcp/src/shared/strv.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/time-util.c ./src/dhcp-manager/systemd-dhcp/src/shared/time-util.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/time-util.h ./src/dhcp-manager/systemd-dhcp/src/shared/time-util.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/utf8.c ./src/dhcp-manager/systemd-dhcp/src/shared/utf8.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/utf8.h ./src/dhcp-manager/systemd-dhcp/src/shared/utf8.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/util.c ./src/dhcp-manager/systemd-dhcp/src/shared/util.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/util.h ./src/dhcp-manager/systemd-dhcp/src/shared/util.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/unaligned.h ./src/dhcp-manager/systemd-dhcp/src/shared/unaligned.h
    /bin/cp "$SYSTEMD_DIR"/src/shared/in-addr-util.c ./src/dhcp-manager/systemd-dhcp/src/shared/in-addr-util.c
    /bin/cp "$SYSTEMD_DIR"/src/shared/in-addr-util.h ./src/dhcp-manager/systemd-dhcp/src/shared/in-addr-util.h
    /bin/cp "$SYSTEMD_DIR"/src/systemd/_sd-common.h ./src/dhcp-manager/systemd-dhcp/src/systemd/_sd-common.h
    /bin/cp "$SYSTEMD_DIR"/src/systemd/sd-dhcp-client.h ./src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-client.h
    /bin/cp "$SYSTEMD_DIR"/src/systemd/sd-dhcp-lease.h ./src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp-lease.h
    /bin/cp "$SYSTEMD_DIR"/src/systemd/sd-dhcp6-client.h ./src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp6-client.h
    /bin/cp "$SYSTEMD_DIR"/src/systemd/sd-dhcp6-lease.h ./src/dhcp-manager/systemd-dhcp/src/systemd/sd-dhcp6-lease.h
    /bin/cp "$SYSTEMD_DIR"/src/systemd/sd-event.h ./src/dhcp-manager/systemd-dhcp/src/systemd/sd-event.h
    /bin/cp "$SYSTEMD_DIR"/src/systemd/sd-id128.h ./src/dhcp-manager/systemd-dhcp/src/systemd/sd-id128.h
parent 20462b50
......@@ -35,7 +35,7 @@
struct sd_dhcp_route {
struct in_addr dst_addr;
struct in_addr gw_addr;
uint8_t dst_prefixlen;
unsigned char dst_prefixlen;
};
struct sd_dhcp_lease {
......@@ -70,16 +70,18 @@ struct sd_dhcp_lease {
char *domainname;
char *hostname;
char *root_path;
uint8_t *client_id;
size_t client_id_len;
};
int dhcp_lease_new(sd_dhcp_lease **ret);
int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option,
void *user_data);
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret);
int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease);
int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id,
size_t client_id_len);
DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref);
#define _cleanup_dhcp_lease_unref_ _cleanup_(sd_dhcp_lease_unrefp)
......@@ -24,31 +24,37 @@
#include <string.h>
#include "sparse-endian.h"
#include "unaligned.h"
#include "util.h"
#include "dhcp6-internal.h"
#include "dhcp6-protocol.h"
#define DHCP6_OPTION_HDR_LEN 4
#define DHCP6_OPTION_IA_NA_LEN 12
#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,
size_t optlen) {
DHCP6Option *option = (DHCP6Option*) *buf;
assert_return(buf, -EINVAL);
assert_return(*buf, -EINVAL);
assert_return(buflen, -EINVAL);
if (optlen > 0xffff || *buflen < optlen + DHCP6_OPTION_HDR_LEN)
if (optlen > 0xffff || *buflen < optlen + sizeof(DHCP6Option))
return -ENOBUFS;
(*buf)[0] = optcode >> 8;
(*buf)[1] = optcode & 0xff;
(*buf)[2] = optlen >> 8;
(*buf)[3] = optlen & 0xff;
option->code = htobe16(optcode);
option->len = htobe16(optlen);
*buf += DHCP6_OPTION_HDR_LEN;
*buflen -= DHCP6_OPTION_HDR_LEN;
*buf += sizeof(DHCP6Option);
*buflen -= sizeof(DHCP6Option);
return 0;
}
......@@ -100,8 +106,8 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
ia_hdr = *buf;
ia_buflen = *buflen;
*buf += DHCP6_OPTION_HDR_LEN;
*buflen -= DHCP6_OPTION_HDR_LEN;
*buf += sizeof(DHCP6Option);
*buflen -= sizeof(DHCP6Option);
memcpy(*buf, &ia->id, len);
......@@ -119,7 +125,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
*buf += 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);
......@@ -130,23 +136,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,
size_t *optlen) {
static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen) {
DHCP6Option *option = (DHCP6Option*) *buf;
uint16_t len;
assert_return(buf, -EINVAL);
assert_return(opt, -EINVAL);
assert_return(optcode, -EINVAL);
assert_return(optlen, -EINVAL);
if (*buflen < 4)
if (*buflen < sizeof(DHCP6Option))
return -ENOMSG;
len = (*buf)[2] << 8 | (*buf)[3];
len = be16toh(option->len);
if (len > *buflen)
return -ENOMSG;
*opt = (*buf)[0] << 8 | (*buf)[1];
*optcode = be16toh(option->code);
*optlen = len;
*buf += 4;
......@@ -190,7 +196,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
switch (iatype) {
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)) {
r = -ENOBUFS;
goto error;
......@@ -212,7 +218,7 @@ int dhcp6_option_parse_ia(uint8_t **buf, size_t *buflen, uint16_t iatype,
break;
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)) {
r = -ENOBUFS;
goto error;
......
......@@ -98,16 +98,16 @@ bool net_match_config(const struct ether_addr *match_mac,
const char *dev_type,
const char *dev_name) {
if (match_host && !condition_test_host(match_host))
if (match_host && !condition_test(match_host))
return 0;
if (match_virt && !condition_test_virtualization(match_virt))
if (match_virt && !condition_test(match_virt))
return 0;
if (match_kernel && !condition_test_kernel_command_line(match_kernel))
if (match_kernel && !condition_test(match_kernel))
return 0;
if (match_arch && !condition_test_architecture(match_arch))
if (match_arch && !condition_test(match_arch))
return 0;
if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
......
......@@ -26,7 +26,7 @@
#include <stdbool.h>
#include "udev.h"
#include "condition-util.h"
#include "condition.h"
bool net_match_config(const struct ether_addr *match_mac,
const char *match_path,
......
......@@ -30,6 +30,7 @@
#include "list.h"
#include "mkdir.h"
#include "fileio.h"
#include "unaligned.h"
#include "in-addr-util.h"
#include "dhcp-protocol.h"
......@@ -198,6 +199,7 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
free(lease->dns);
free(lease->ntp);
free(lease->static_route);
free(lease->client_id);
free(lease);
}
......@@ -205,14 +207,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) {
be32_t val;
assert(option);
assert(ret);
if (len == 4) {
memcpy(&val, option, 4);
*ret = be32toh(val);
*ret = unaligned_read_be32((be32_t*) option);
if (*ret < min)
*ret = min;
......@@ -224,14 +223,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) {
be16_t val;
assert(option);
assert(ret);
if (len == 2) {
memcpy(&val, option, 2);
*ret = be16toh(val);
*ret = unaligned_read_be16((be16_t*) option);
if (*ret < min)
*ret = min;
......@@ -315,23 +311,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);
}
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,
size_t *routes_size, size_t *routes_allocated) {
......@@ -353,8 +332,10 @@ static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_
while (len >= 8) {
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");
continue;
}
......@@ -600,11 +581,13 @@ int dhcp_lease_new(sd_dhcp_lease **ret) {
return 0;
}
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
struct in_addr address;
const struct in_addr *addresses;
const uint8_t *client_id;
size_t client_id_len;
const char *string;
uint16_t mtu;
struct sd_dhcp_route *routes;
......@@ -678,6 +661,18 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
if (r >= 0)
serialize_dhcp_routes(f, "ROUTES", routes, r);
r = sd_dhcp_lease_get_client_id(lease, &client_id, &client_id_len);
if (r >= 0) {
_cleanup_free_ char *client_id_hex;
client_id_hex = hexmem (client_id, client_id_len);
if (!client_id_hex) {
r = -ENOMEM;
goto finish;
}
fprintf(f, "CLIENTID=%s\n", client_id_hex);
}
r = 0;
fflush(f);
......@@ -695,11 +690,12 @@ finish:
return r;
}
int 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_free_ char *address = NULL, *router = NULL, *netmask = NULL,
*server_address = NULL, *next_server = NULL,
*dns = NULL, *ntp = NULL, *mtu = NULL, *routes = NULL;
*dns = NULL, *ntp = NULL, *mtu = NULL,
*routes = NULL, *client_id_hex = NULL;
struct in_addr addr;
int r;
......@@ -723,6 +719,7 @@ int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) {
"HOSTNAME", &lease->hostname,
"ROOT_PATH", &lease->root_path,
"ROUTES", &routes,
"CLIENTID", &client_id_hex,
NULL);
if (r < 0) {
if (r == -ENOENT)
......@@ -797,6 +794,16 @@ int dhcp_lease_load(const char *lease_file, sd_dhcp_lease **ret) {
return r;
}
if (client_id_hex) {
if (strlen (client_id_hex) % 2)
return -EINVAL;
lease->client_id = unhexmem (client_id_hex, strlen (client_id_hex));
if (!lease->client_id)
return -ENOMEM;
lease->client_id_len = strlen (client_id_hex) / 2;
}
*ret = lease;
lease = NULL;
......@@ -821,3 +828,32 @@ int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
return 0;
}
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
size_t *client_id_len) {
assert_return(lease, -EINVAL);
assert_return(client_id, -EINVAL);
assert_return(client_id_len, -EINVAL);
*client_id = lease->client_id;
*client_id_len = lease->client_id_len;
return 0;
}
int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id,
size_t client_id_len) {
assert_return(lease, -EINVAL);
assert_return((!client_id && !client_id_len) ||
(client_id && client_id_len), -EINVAL);
free (lease->client_id);
lease->client_id = NULL;
lease->client_id_len = 0;
if (client_id) {
lease->client_id = memdup (client_id, client_id_len);
lease->client_id_len = client_id_len;
}
return 0;
}
......@@ -200,19 +200,19 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
switch (type) {
case DHCP6_DUID_LLT:
if (duid_len <= sizeof(client->duid.llt))
if (duid_len <= sizeof(client->duid.llt) - 2)
return -EINVAL;
break;
case DHCP6_DUID_EN:
if (duid_len != sizeof(client->duid.en))
if (duid_len != sizeof(client->duid.en) - 2)
return -EINVAL;
break;
case DHCP6_DUID_LL:
if (duid_len <= sizeof(client->duid.ll))
if (duid_len <= sizeof(client->duid.ll) - 2)
return -EINVAL;
break;
case DHCP6_DUID_UUID:
if (duid_len != sizeof(client->duid.uuid))
if (duid_len != sizeof(client->duid.uuid) - 2)
return -EINVAL;
break;
default:
......@@ -222,7 +222,7 @@ int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *du
client->duid.raw.type = htobe16(type);
memcpy(&client->duid.raw.data, duid, duid_len);
client->duid_len = duid_len;
client->duid_len = duid_len + 2; /* +2 for sizeof(type) */
return 0;
}
......@@ -590,8 +590,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
if (r < 0)
goto error;
r = sd_event_source_set_name(client->timeout_resend,
"dhcp6-resend-timer");
r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer");
if (r < 0)
goto error;
......@@ -614,8 +613,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
if (r < 0)
goto error;
r = sd_event_source_set_name(client->timeout_resend_expire,
"dhcp6-resend-expire-timer");
r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer");
if (r < 0)
goto error;
}
......@@ -1010,8 +1008,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0)
return r;
r = sd_event_source_set_name(client->receive_message,
"dhcp6-receive-message");
r = sd_event_source_set_description(client->receive_message, "dhcp6-receive-message");
if (r < 0)
return r;
......@@ -1059,8 +1056,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0)
return r;
r = sd_event_source_set_name(client->lease->ia.timeout_t1,
"dhcp6-t1-timeout");
r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
if (r < 0)
return r;
......@@ -1084,8 +1080,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0)
return r;
r = sd_event_source_set_name(client->lease->ia.timeout_t2,
"dhcp6-t2-timeout");
r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
if (r < 0)
return r;
......@@ -1108,8 +1103,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state)
if (r < 0)
return r;
r = sd_event_source_set_name(client->timeout_resend,
"dhcp6-resend-timeout");
r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout");
if (r < 0)
return r;
......
......@@ -20,12 +20,12 @@
***/
#include <unistd.h>
#include <sys/sendfile.h>
#include "fileio.h"
#include "util.h"
#include "strv.h"
#include "utf8.h"
#include "ctype.h"
#include "fileio.h"
int write_string_stream(FILE *f, const char *line) {
assert(f);
......@@ -66,7 +66,7 @@ int write_string_file_no_create(const char *fn, const char *line) {
assert(line);
/* 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);
if (fd < 0)
return -errno;
......@@ -94,20 +94,10 @@ int write_string_file_atomic(const char *fn, const char *line) {
fchmod_umask(fileno(f), 0644);
errno = 0;
fputs(line, f);
if (!endswith(line, "\n"))
fputc('\n', f);
fflush(f);
if (ferror(f))
r = errno ? -errno : -EIO;
else {
r = write_string_stream(f, line);
if (r >= 0) {
if (rename(p, fn) < 0)
r = -errno;
else
r = 0;
}
if (r < 0)
......@@ -144,77 +134,6 @@ int read_one_line_file(const char *fn, char **line) {
return 0;
}
ssize_t sendfile_full(int out_fd, const char *fn) {
_cleanup_fclose_ FILE *f;
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) {
size_t n, l;
_cleanup_free_ char *buf = NULL;
......
......@@ -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_full_file(const char *fn, 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 load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
......
......@@ -250,21 +250,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) {
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->s_addr != INADDR_ANY);
assert(prefixlen);
address = be32toh(addr->s_addr);
if ((address >> 31) == 0x0)
if (msb_octet < 128)
/* class A, leading bits: 0 */
*prefixlen = 8;
else if ((address >> 30) == 0x2)
else if (msb_octet < 19