mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 08:20:08 +01:00
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
This commit is contained in:
parent
20462b5095
commit
e2e4637cf4
19 changed files with 630 additions and 370 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "dhcp-lease-internal.h"
|
||||
#include "sd-dhcp-client.h"
|
||||
|
||||
#define MAX_CLIENT_ID_LEN 64 /* Arbitrary limit */
|
||||
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
|
||||
|
||||
struct sd_dhcp_client {
|
||||
|
|
@ -56,19 +57,38 @@ struct sd_dhcp_client {
|
|||
size_t req_opts_allocated;
|
||||
size_t req_opts_size;
|
||||
be32_t last_addr;
|
||||
struct {
|
||||
uint8_t type;
|
||||
struct ether_addr mac_addr;
|
||||
} _packed_ client_id;
|
||||
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
|
||||
size_t mac_addr_len;
|
||||
uint16_t arp_type;
|
||||
union {
|
||||
struct {
|
||||
uint8_t type; /* 0: Generic (non-LL) (RFC 2132) */
|
||||
uint8_t data[MAX_CLIENT_ID_LEN];
|
||||
} _packed_ gen;
|
||||
struct {
|
||||
uint8_t type; /* 1: Ethernet Link-Layer (RFC 2132) */
|
||||
uint8_t haddr[ETH_ALEN];
|
||||
} _packed_ eth;
|
||||
struct {
|
||||
uint8_t type; /* 2 - 254: ARP/Link-Layer (RFC 2132) */
|
||||
uint8_t haddr[0];
|
||||
} _packed_ ll;
|
||||
struct {
|
||||
uint8_t type; /* 255: Node-specific (RFC 4361) */
|
||||
uint8_t iaid[4];
|
||||
uint8_t duid[MAX_CLIENT_ID_LEN - 4];
|
||||
} _packed_ ns;
|
||||
struct {
|
||||
uint8_t type;
|
||||
uint8_t data[MAX_CLIENT_ID_LEN];
|
||||
} _packed_ raw;
|
||||
} client_id;
|
||||
size_t client_id_len;
|
||||
char *hostname;
|
||||
char *vendor_class_identifier;
|
||||
uint32_t mtu;
|
||||
uint32_t xid;
|
||||
usec_t start_time;
|
||||
uint16_t secs;
|
||||
unsigned int attempt;
|
||||
usec_t request_sent;
|
||||
sd_event_source *timeout_t1;
|
||||
|
|
@ -201,8 +221,70 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
|
|||
client->mac_addr_len = addr_len;
|
||||
client->arp_type = arp_type;
|
||||
|
||||
memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
|
||||
client->client_id.type = 0x01;
|
||||
if (need_restart && client->state != DHCP_STATE_STOPPED)
|
||||
sd_dhcp_client_start(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
|
||||
const uint8_t **data, size_t *data_len) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(type, -EINVAL);
|
||||
assert_return(data, -EINVAL);
|
||||
assert_return(data_len, -EINVAL);
|
||||
|
||||
*type = 0;
|
||||
*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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
||||
const uint8_t *data, size_t data_len) {
|
||||
DHCP_CLIENT_DONT_DESTROY(client);
|
||||
bool need_restart = false;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(data, -EINVAL);
|
||||
assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
|
||||
|
||||
switch (type) {
|
||||
case ARPHRD_ETHER:
|
||||
if (data_len != ETH_ALEN)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case ARPHRD_INFINIBAND:
|
||||
if (data_len != INFINIBAND_ALEN)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (client->client_id_len == data_len + sizeof (client->client_id.raw.type) &&
|
||||
client->client_id.raw.type == type &&
|
||||
memcmp(&client->client_id.raw.data, data, data_len) == 0)
|
||||
return 0;
|
||||
|
||||
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
|
||||
log_dhcp_client(client, "Changing client ID on running DHCP "
|
||||
"client, restarting");
|
||||
need_restart = true;
|
||||
client_stop(client, DHCP_EVENT_STOP);
|
||||
}
|
||||
|
||||
client->client_id.raw.type = type;
|
||||
memcpy(&client->client_id.raw.data, data, data_len);
|
||||
client->client_id_len = data_len + sizeof (client->client_id.raw.type);
|
||||
|
||||
if (need_restart && client->state != DHCP_STATE_STOPPED)
|
||||
sd_dhcp_client_start(client);
|
||||
|
|
@ -321,10 +403,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
|||
_cleanup_free_ DHCPPacket *packet;
|
||||
size_t optlen, optoffset, size;
|
||||
be16_t max_size;
|
||||
usec_t time_now;
|
||||
uint16_t secs;
|
||||
int r;
|
||||
|
||||
assert(client);
|
||||
assert(client->secs);
|
||||
assert(client->start_time);
|
||||
assert(ret);
|
||||
assert(_optlen);
|
||||
assert(_optoffset);
|
||||
|
|
@ -344,7 +428,15 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
|||
|
||||
/* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
|
||||
refuse to issue an DHCP lease if 'secs' is set to zero */
|
||||
packet->dhcp.secs = htobe16(client->secs);
|
||||
r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(time_now >= client->start_time);
|
||||
|
||||
/* seconds between sending first and last DISCOVER
|
||||
* must always be strictly positive to deal with broken servers */
|
||||
secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
|
||||
packet->dhcp.secs = htobe16(secs);
|
||||
|
||||
/* RFC2132 section 4.1
|
||||
A client that cannot receive unicast IP datagrams until its protocol
|
||||
|
|
@ -369,14 +461,24 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
|
|||
if (client->arp_type == ARPHRD_ETHER)
|
||||
memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
|
||||
|
||||
/* If no client identifier exists, construct one from an ethernet
|
||||
address if present */
|
||||
if (client->client_id_len == 0 && client->arp_type == ARPHRD_ETHER) {
|
||||
client->client_id.eth.type = ARPHRD_ETHER;
|
||||
memcpy(&client->client_id.eth.haddr, &client->mac_addr, ETH_ALEN);
|
||||
client->client_id_len = sizeof (client->client_id.eth);
|
||||
}
|
||||
|
||||
/* Some DHCP servers will refuse to issue an DHCP lease if the Client
|
||||
Identifier option is not set */
|
||||
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
|
||||
DHCP_OPTION_CLIENT_IDENTIFIER,
|
||||
sizeof(client->client_id), &client->client_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (client->client_id_len) {
|
||||
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
|
||||
DHCP_OPTION_CLIENT_IDENTIFIER,
|
||||
client->client_id_len,
|
||||
&client->client_id.raw);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* RFC2131 section 3.5:
|
||||
in its initial DHCPDISCOVER or DHCPREQUEST message, a
|
||||
|
|
@ -441,24 +543,12 @@ static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
|
|||
static int client_send_discover(sd_dhcp_client *client) {
|
||||
_cleanup_free_ DHCPPacket *discover = NULL;
|
||||
size_t optoffset, optlen;
|
||||
usec_t time_now;
|
||||
int r;
|
||||
|
||||
assert(client);
|
||||
assert(client->state == DHCP_STATE_INIT ||
|
||||
client->state == DHCP_STATE_SELECTING);
|
||||
|
||||
/* See RFC2131 section 4.4.1 */
|
||||
|
||||
r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(time_now >= client->start_time);
|
||||
|
||||
/* seconds between sending first and last DISCOVER
|
||||
* must always be strictly positive to deal with broken servers */
|
||||
client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
|
||||
|
||||
r = client_message_init(client, &discover, DHCP_DISCOVER,
|
||||
&optlen, &optoffset);
|
||||
if (r < 0)
|
||||
|
|
@ -723,8 +813,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,
|
||||
"dhcp4-resend-timer");
|
||||
r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
|
|
@ -801,8 +890,7 @@ static int client_initialize_io_events(sd_dhcp_client *client,
|
|||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_event_source_set_name(client->receive_message,
|
||||
"dhcp4-receive-message");
|
||||
r = sd_event_source_set_description(client->receive_message, "dhcp4-receive-message");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
|
|
@ -832,8 +920,7 @@ static int client_initialize_time_events(sd_dhcp_client *client) {
|
|||
r = sd_event_source_set_priority(client->timeout_resend,
|
||||
client->event_priority);
|
||||
|
||||
r = sd_event_source_set_name(client->timeout_resend,
|
||||
"dhcp4-resend-timer");
|
||||
r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
|
|
@ -875,10 +962,8 @@ static int client_start(sd_dhcp_client *client) {
|
|||
}
|
||||
client->fd = r;
|
||||
|
||||
if (client->state == DHCP_STATE_INIT) {
|
||||
if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
|
||||
client->start_time = now(clock_boottime_or_monotonic());
|
||||
client->secs = 0;
|
||||
}
|
||||
|
||||
return client_initialize_events(client, client_receive_message_raw);
|
||||
}
|
||||
|
|
@ -944,6 +1029,14 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (client->client_id_len) {
|
||||
r = dhcp_lease_set_client_id(lease,
|
||||
(uint8_t *) &client->client_id.raw,
|
||||
client->client_id_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dhcp_option_parse(offer, len, dhcp_lease_parse_options, lease);
|
||||
if (r != DHCP_OFFER) {
|
||||
log_dhcp_client(client, "received message was not an OFFER, ignoring");
|
||||
|
|
@ -1003,6 +1096,14 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (client->client_id_len) {
|
||||
r = dhcp_lease_set_client_id(lease,
|
||||
(uint8_t *) &client->client_id.raw,
|
||||
client->client_id_len);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
|
||||
if (r == DHCP_NAK) {
|
||||
log_dhcp_client(client, "NAK");
|
||||
|
|
@ -1149,8 +1250,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_name(client->timeout_expire,
|
||||
"dhcp4-lifetime");
|
||||
r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
@ -1177,8 +1277,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_name(client->timeout_t2,
|
||||
"dhcp4-t2-timeout");
|
||||
r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
@ -1204,8 +1303,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_name(client->timeout_t1,
|
||||
"dhcp4-t1-timer");
|
||||
r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
@ -1250,8 +1348,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
|||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_event_source_set_name(client->timeout_resend,
|
||||
"dhcp4-resend-timer");
|
||||
r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
} else if (r == -ENOMSG)
|
||||
|
|
@ -1269,6 +1366,9 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
|
|||
if (r >= 0) {
|
||||
client->timeout_resend =
|
||||
sd_event_source_unref(client->timeout_resend);
|
||||
client->receive_message =
|
||||
sd_event_source_unref(client->receive_message);
|
||||
client->fd = asynchronous_close(client->fd);
|
||||
|
||||
if (IN_SET(client->state, DHCP_STATE_REQUESTING,
|
||||
DHCP_STATE_REBOOTING))
|
||||
|
|
|
|||
|
|
@ -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 < 192)
|
||||
/* class B, leading bits 10 */
|
||||
*prefixlen = 16;
|
||||
else if ((address >> 29) == 0x6)
|
||||
else if (msb_octet < 224)
|
||||
/* class C, leading bits 110 */
|
||||
*prefixlen = 24;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -248,40 +248,6 @@ char **strv_split(const char *s, const char *separator) {
|
|||
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 **l;
|
||||
unsigned n;
|
||||
|
|
@ -307,6 +273,41 @@ char **strv_split_newlines(const char *s) {
|
|||
return l;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
char *strv_join(char **l, const char *separator) {
|
||||
char *r, *e;
|
||||
char **s;
|
||||
|
|
|
|||
|
|
@ -63,9 +63,10 @@ static inline bool strv_isempty(char * const *l) {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
int strv_split_quoted(char ***t, const char *s, bool relax);
|
||||
|
||||
char *strv_join(char **l, const char *separator);
|
||||
char *strv_join_quoted(char **l);
|
||||
|
||||
|
|
|
|||
66
src/dhcp-manager/systemd-dhcp/src/shared/unaligned.h
Normal file
66
src/dhcp-manager/systemd-dhcp/src/shared/unaligned.h
Normal 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);
|
||||
}
|
||||
|
|
@ -150,10 +150,12 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool newline) {
|
|||
int encoded_len, val;
|
||||
|
||||
encoded_len = utf8_encoded_valid_unichar((const char *) p);
|
||||
val = utf8_encoded_to_unichar((const char*) p);
|
||||
|
||||
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) ||
|
||||
(!newline && val == '\n'))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -363,6 +363,46 @@ int safe_atou8(const char *s, uint8_t *ret) {
|
|||
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) {
|
||||
char *x = NULL;
|
||||
unsigned long long l;
|
||||
|
|
@ -695,7 +735,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
|
|||
}
|
||||
|
||||
/* Kernel threads have no argv[] */
|
||||
if (r == NULL || r[0] == 0) {
|
||||
if (isempty(r)) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
int h;
|
||||
|
||||
|
|
@ -893,6 +933,28 @@ int readlink_malloc(const char *p, char **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) {
|
||||
_cleanup_free_ char *target = NULL;
|
||||
char *k;
|
||||
|
|
@ -2466,14 +2528,53 @@ char* dirname_malloc(const char *path) {
|
|||
}
|
||||
|
||||
int dev_urandom(void *p, size_t n) {
|
||||
_cleanup_close_ int fd;
|
||||
static int have_syscall = -1;
|
||||
int r, fd;
|
||||
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;
|
||||
}
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return errno == ENOENT ? -ENOSYS : -errno;
|
||||
|
||||
k = loop_read(fd, p, n, true);
|
||||
safe_close(fd);
|
||||
|
||||
if (k < 0)
|
||||
return (int) k;
|
||||
if ((size_t) k != n)
|
||||
|
|
@ -2482,8 +2583,36 @@ int dev_urandom(void *p, size_t n) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void random_bytes(void *p, size_t n) {
|
||||
void initialize_srand(void) {
|
||||
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;
|
||||
int r;
|
||||
|
||||
|
|
@ -2494,28 +2623,7 @@ void random_bytes(void *p, size_t n) {
|
|||
/* If some idiot made /dev/urandom unavailable to us, he'll
|
||||
* get a PRNG instead. */
|
||||
|
||||
if (!srand_called) {
|
||||
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;
|
||||
}
|
||||
initialize_srand();
|
||||
|
||||
for (q = p; q < (uint8_t*) p + n; q ++)
|
||||
*q = rand();
|
||||
|
|
@ -2737,7 +2845,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
|
|||
if (k < 0)
|
||||
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);
|
||||
if (k < 0) {
|
||||
|
|
@ -2895,6 +3003,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);
|
||||
}
|
||||
|
||||
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) {
|
||||
int fd, r;
|
||||
struct statfs s;
|
||||
|
|
@ -3133,7 +3254,8 @@ char *replace_env(const char *format, char **env) {
|
|||
|
||||
case CURLY:
|
||||
if (*e == '{') {
|
||||
if (!(k = strnappend(r, word, e-word-1)))
|
||||
k = strnappend(r, word, e-word-1);
|
||||
if (!k)
|
||||
goto fail;
|
||||
|
||||
free(r);
|
||||
|
|
@ -3143,7 +3265,8 @@ char *replace_env(const char *format, char **env) {
|
|||
state = VARIABLE;
|
||||
|
||||
} else if (*e == '$') {
|
||||
if (!(k = strnappend(r, word, e-word)))
|
||||
k = strnappend(r, word, e-word);
|
||||
if (!k)
|
||||
goto fail;
|
||||
|
||||
free(r);
|
||||
|
|
@ -3175,7 +3298,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;
|
||||
|
||||
free(r);
|
||||
|
|
@ -3208,7 +3332,7 @@ char **replace_env_argv(char **argv, char **env) {
|
|||
if (e) {
|
||||
int r;
|
||||
|
||||
r = strv_split_quoted(&m, e);
|
||||
r = strv_split_quoted(&m, e, true);
|
||||
if (r < 0) {
|
||||
ret[k] = NULL;
|
||||
strv_free(ret);
|
||||
|
|
@ -3529,41 +3653,33 @@ char *unquote(const char *s, const char* quotes) {
|
|||
}
|
||||
|
||||
char *normalize_env_assignment(const char *s) {
|
||||
_cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
|
||||
char *eq, *r;
|
||||
_cleanup_free_ char *value = NULL;
|
||||
const char *eq;
|
||||
char *p, *name;
|
||||
|
||||
eq = strchr(s, '=');
|
||||
if (!eq) {
|
||||
char *t;
|
||||
char *r, *t;
|
||||
|
||||
r = strdup(s);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
t = strstrip(r);
|
||||
if (t == r)
|
||||
return r;
|
||||
if (t != r)
|
||||
memmove(r, t, strlen(t) + 1);
|
||||
|
||||
memmove(r, t, strlen(t) + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
name = strndup(s, eq - s);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
p = strdup(eq + 1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
name = strndupa(s, eq - s);
|
||||
p = strdupa(eq + 1);
|
||||
|
||||
value = unquote(strstrip(p), QUOTES);
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
|
||||
r = NULL;
|
||||
|
||||
return r;
|
||||
return strjoin(strstrip(name), "=", value, NULL);
|
||||
}
|
||||
|
||||
int wait_for_terminate(pid_t pid, siginfo_t *status) {
|
||||
|
|
@ -4780,19 +4896,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
|
|||
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[] = {
|
||||
[IOPRIO_CLASS_NONE] = "none",
|
||||
[IOPRIO_CLASS_RT] = "realtime",
|
||||
|
|
@ -6097,27 +6200,28 @@ int split_pair(const char *s, const char *sep, char **l, char **r) {
|
|||
|
||||
int shall_restore_state(void) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
r = proc_cmdline(&line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) /* Container ... */
|
||||
return 1;
|
||||
|
||||
r = 1;
|
||||
p = line;
|
||||
|
||||
FOREACH_WORD_QUOTED(word, l, line, state) {
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
const char *e;
|
||||
char n[l+1];
|
||||
int k;
|
||||
|
||||
memcpy(n, word, l);
|
||||
n[l] = 0;
|
||||
k = unquote_first_word(&p, &word, true);
|
||||
if (k < 0)
|
||||
return k;
|
||||
if (k == 0)
|
||||
break;
|
||||
|
||||
e = startswith(n, "systemd.restore_state=");
|
||||
e = startswith(word, "systemd.restore_state=");
|
||||
if (!e)
|
||||
continue;
|
||||
|
||||
|
|
@ -6130,51 +6234,35 @@ int shall_restore_state(void) {
|
|||
}
|
||||
|
||||
int proc_cmdline(char **ret) {
|
||||
int r;
|
||||
assert(ret);
|
||||
|
||||
if (detect_container(NULL) > 0) {
|
||||
char *buf = NULL, *p;
|
||||
size_t sz = 0;
|
||||
|
||||
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;
|
||||
if (detect_container(NULL) > 0)
|
||||
return get_process_cmdline(1, 0, false, ret);
|
||||
else
|
||||
return read_one_line_file("/proc/cmdline", ret);
|
||||
}
|
||||
|
||||
int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
const char *w, *state;
|
||||
size_t l;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(parse_item);
|
||||
|
||||
r = proc_cmdline(&line);
|
||||
if (r < 0)
|
||||
log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
return r;
|
||||
|
||||
FOREACH_WORD_QUOTED(w, l, line, state) {
|
||||
char word[l+1], *value;
|
||||
p = line;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
char *value = NULL;
|
||||
|
||||
memcpy(word, w, l);
|
||||
word[l] = 0;
|
||||
r = unquote_first_word(&p, &word, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
/* Filter out arguments that are intended only for the
|
||||
* initrd */
|
||||
|
|
@ -6938,19 +7026,19 @@ int is_symlink(const char *path) {
|
|||
|
||||
int is_dir(const char* path, bool follow) {
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
if (follow) {
|
||||
if (stat(path, &st) < 0)
|
||||
return -errno;
|
||||
} else {
|
||||
if (lstat(path, &st) < 0)
|
||||
return -errno;
|
||||
}
|
||||
if (follow)
|
||||
r = stat(path, &st);
|
||||
else
|
||||
r = lstat(path, &st);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
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;
|
||||
size_t allocated = 0, sz = 0;
|
||||
|
||||
|
|
@ -7009,8 +7097,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case VALUE_ESCAPE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
|
@ -7021,9 +7112,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case SINGLE_QUOTE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
else if (c == '\'')
|
||||
} else if (c == '\'')
|
||||
state = VALUE;
|
||||
else if (c == '\\')
|
||||
state = SINGLE_QUOTE_ESCAPE;
|
||||
|
|
@ -7037,8 +7130,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case SINGLE_QUOTE_ESCAPE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
|
@ -7064,8 +7160,11 @@ int unquote_first_word(const char **p, char **ret) {
|
|||
break;
|
||||
|
||||
case DOUBLE_QUOTE_ESCAPE:
|
||||
if (c == 0)
|
||||
if (c == 0) {
|
||||
if (relax)
|
||||
goto finish;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!GREEDY_REALLOC(s, allocated, sz+2))
|
||||
return -ENOMEM;
|
||||
|
|
@ -7125,7 +7224,7 @@ int unquote_many_words(const char **p, ...) {
|
|||
l = newa0(char*, n);
|
||||
for (c = 0; c < n; c++) {
|
||||
|
||||
r = unquote_first_word(p, &l[c]);
|
||||
r = unquote_first_word(p, &l[c], false);
|
||||
if (r < 0) {
|
||||
int j;
|
||||
|
||||
|
|
|
|||
|
|
@ -245,6 +245,9 @@ static inline int safe_atoi64(const char *s, int64_t *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);
|
||||
|
||||
#define FOREACH_WORD(word, length, s, state) \
|
||||
|
|
@ -270,6 +273,7 @@ char **replace_env_argv(char **argv, char **env);
|
|||
|
||||
int readlinkat_malloc(int fd, const char *p, char **ret);
|
||||
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_canonicalize(const char *p, char **r);
|
||||
|
||||
|
|
@ -321,6 +325,7 @@ int make_console_stdio(void);
|
|||
|
||||
int dev_urandom(void *p, size_t n);
|
||||
void random_bytes(void *p, size_t n);
|
||||
void initialize_srand(void);
|
||||
|
||||
static inline uint64_t random_u64(void) {
|
||||
uint64_t u;
|
||||
|
|
@ -581,8 +586,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 file_is_priv_sticky(const char *p);
|
||||
|
||||
#define NULSTR_FOREACH(i, l) \
|
||||
for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
|
||||
|
||||
|
|
@ -793,6 +796,15 @@ static inline void _reset_errno_(int *saved_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_ {
|
||||
mode_t mask;
|
||||
bool quit;
|
||||
|
|
@ -829,6 +841,21 @@ static inline int log2i(int x) {
|
|||
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) {
|
||||
return access("/run/systemd/seats/", F_OK) >= 0;
|
||||
}
|
||||
|
|
@ -993,7 +1020,7 @@ int take_password_lock(const char *root);
|
|||
int is_symlink(const char *path);
|
||||
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 free_and_strdup(char **p, const char *s);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
|
|||
int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
|
||||
int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type);
|
||||
int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
|
||||
const uint8_t *data, size_t data_len);
|
||||
int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
|
||||
const uint8_t **data, size_t *data_len);
|
||||
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_vendor_class_identifier(sd_dhcp_client *client, const char *vci);
|
||||
|
|
|
|||
|
|
@ -45,5 +45,10 @@ int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname);
|
|||
int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname);
|
||||
int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path);
|
||||
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routesgn);
|
||||
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id,
|
||||
size_t *client_id_len);
|
||||
|
||||
int sd_dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file);
|
||||
int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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_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_get_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_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_get_pending(sd_event_source *s);
|
||||
int sd_event_source_get_priority(sd_event_source *s, int64_t *priority);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue