systemd: update code from upstream (2022-08-10)

This is a direct dump from systemd git.

  $ git clean -fdx && \
    git cat-file -p HEAD | sed '1,/^======$/ d' | bash - && \
    git add .

======

SYSTEMD_DIR=../systemd
COMMIT=e8d0eb3915ac33cc0d3da87a836cee6e61645227

(
  cd "$SYSTEMD_DIR"
  git checkout "$COMMIT"
  git reset --hard
  git clean -fdx
)

git ls-files -z :/src/libnm-systemd-core/src/ \
                :/src/libnm-systemd-shared/src/ \
                :/src/libnm-std-aux/unaligned.h | \
  xargs -0 rm -f

nm_copy_sd_shared() {
    mkdir -p "./src/libnm-systemd-shared/$(dirname "$1")"
    cp "$SYSTEMD_DIR/$1" "./src/libnm-systemd-shared/$1"
}

nm_copy_sd_core() {
    mkdir -p "./src/libnm-systemd-core/$(dirname "$1")"
    cp "$SYSTEMD_DIR/$1" "./src/libnm-systemd-core/$1"
}

nm_copy_sd_stdaux() {
    mkdir -p "./src/libnm-std-aux/"
    cp "$SYSTEMD_DIR/$1" "./src/libnm-std-aux/${1##*/}"
}

nm_copy_sd_core "src/libsystemd-network/arp-util.c"
nm_copy_sd_core "src/libsystemd-network/arp-util.h"
nm_copy_sd_core "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd_core "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd_core "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd_core "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd_core "src/libsystemd-network/dhcp6-option.h"
nm_copy_sd_core "src/libsystemd-network/dhcp6-protocol.c"
nm_copy_sd_core "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd_core "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd_core "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd_core "src/libsystemd-network/lldp-network.c"
nm_copy_sd_core "src/libsystemd-network/lldp-network.h"
nm_copy_sd_core "src/libsystemd-network/lldp-rx-internal.h"
nm_copy_sd_core "src/libsystemd-network/network-common.c"
nm_copy_sd_core "src/libsystemd-network/network-common.h"
nm_copy_sd_core "src/libsystemd-network/network-internal.h"
nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd_core "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd_core "src/libsystemd-network/sd-lldp-rx.c"
nm_copy_sd_core "src/libsystemd/sd-event/event-source.h"
nm_copy_sd_core "src/libsystemd/sd-event/event-util.c"
nm_copy_sd_core "src/libsystemd/sd-event/event-util.h"
nm_copy_sd_core "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd_core "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd_core "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd_core "src/systemd/_sd-common.h"
nm_copy_sd_core "src/systemd/sd-dhcp6-client.h"
nm_copy_sd_core "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd_core "src/systemd/sd-dhcp6-option.h"
nm_copy_sd_core "src/systemd/sd-event.h"
nm_copy_sd_core "src/systemd/sd-id128.h"
nm_copy_sd_core "src/systemd/sd-lldp-rx.h"
nm_copy_sd_core "src/systemd/sd-lldp.h"
nm_copy_sd_core "src/systemd/sd-ndisc.h"
nm_copy_sd_shared "src/basic/alloc-util.c"
nm_copy_sd_shared "src/basic/alloc-util.h"
nm_copy_sd_shared "src/basic/async.h"
nm_copy_sd_shared "src/basic/cgroup-util.h"
nm_copy_sd_shared "src/basic/dns-def.h"
nm_copy_sd_shared "src/basic/env-file.c"
nm_copy_sd_shared "src/basic/env-file.h"
nm_copy_sd_shared "src/basic/env-util.c"
nm_copy_sd_shared "src/basic/env-util.h"
nm_copy_sd_shared "src/basic/errno-util.h"
nm_copy_sd_shared "src/basic/escape.c"
nm_copy_sd_shared "src/basic/escape.h"
nm_copy_sd_shared "src/basic/ether-addr-util.c"
nm_copy_sd_shared "src/basic/ether-addr-util.h"
nm_copy_sd_shared "src/basic/extract-word.c"
nm_copy_sd_shared "src/basic/extract-word.h"
nm_copy_sd_shared "src/basic/fd-util.c"
nm_copy_sd_shared "src/basic/fd-util.h"
nm_copy_sd_shared "src/basic/fileio.c"
nm_copy_sd_shared "src/basic/fileio.h"
nm_copy_sd_shared "src/basic/format-util.c"
nm_copy_sd_shared "src/basic/format-util.h"
nm_copy_sd_shared "src/basic/fs-util.c"
nm_copy_sd_shared "src/basic/fs-util.h"
nm_copy_sd_shared "src/basic/glyph-util.c"
nm_copy_sd_shared "src/basic/glyph-util.h"
nm_copy_sd_shared "src/basic/hash-funcs.c"
nm_copy_sd_shared "src/basic/hash-funcs.h"
nm_copy_sd_shared "src/basic/hashmap.c"
nm_copy_sd_shared "src/basic/hashmap.h"
nm_copy_sd_shared "src/basic/hexdecoct.c"
nm_copy_sd_shared "src/basic/hexdecoct.h"
nm_copy_sd_shared "src/basic/hostname-util.c"
nm_copy_sd_shared "src/basic/hostname-util.h"
nm_copy_sd_shared "src/basic/in-addr-util.c"
nm_copy_sd_shared "src/basic/in-addr-util.h"
nm_copy_sd_shared "src/basic/inotify-util.c"
nm_copy_sd_shared "src/basic/inotify-util.h"
nm_copy_sd_shared "src/basic/io-util.c"
nm_copy_sd_shared "src/basic/io-util.h"
nm_copy_sd_shared "src/basic/list.h"
nm_copy_sd_shared "src/basic/locale-util.c"
nm_copy_sd_shared "src/basic/locale-util.h"
nm_copy_sd_shared "src/basic/log.h"
nm_copy_sd_shared "src/basic/macro.h"
nm_copy_sd_shared "src/basic/memory-util.c"
nm_copy_sd_shared "src/basic/memory-util.h"
nm_copy_sd_shared "src/basic/mempool.c"
nm_copy_sd_shared "src/basic/mempool.h"
nm_copy_sd_shared "src/basic/missing_fcntl.h"
nm_copy_sd_shared "src/basic/missing_random.h"
nm_copy_sd_shared "src/basic/missing_socket.h"
nm_copy_sd_shared "src/basic/missing_stat.h"
nm_copy_sd_shared "src/basic/missing_syscall.h"
nm_copy_sd_shared "src/basic/missing_type.h"
nm_copy_sd_shared "src/basic/ordered-set.c"
nm_copy_sd_shared "src/basic/ordered-set.h"
nm_copy_sd_shared "src/basic/parse-util.c"
nm_copy_sd_shared "src/basic/parse-util.h"
nm_copy_sd_shared "src/basic/path-util.c"
nm_copy_sd_shared "src/basic/path-util.h"
nm_copy_sd_shared "src/basic/prioq.c"
nm_copy_sd_shared "src/basic/prioq.h"
nm_copy_sd_shared "src/basic/process-util.c"
nm_copy_sd_shared "src/basic/process-util.h"
nm_copy_sd_shared "src/basic/random-util.c"
nm_copy_sd_shared "src/basic/random-util.h"
nm_copy_sd_shared "src/basic/ratelimit.c"
nm_copy_sd_shared "src/basic/ratelimit.h"
nm_copy_sd_shared "src/basic/set.h"
nm_copy_sd_shared "src/basic/signal-util.c"
nm_copy_sd_shared "src/basic/signal-util.h"
nm_copy_sd_shared "src/basic/siphash24.h"
nm_copy_sd_shared "src/basic/socket-util.c"
nm_copy_sd_shared "src/basic/socket-util.h"
nm_copy_sd_shared "src/basic/sort-util.h"
nm_copy_sd_shared "src/basic/sparse-endian.h"
nm_copy_sd_shared "src/basic/stat-util.c"
nm_copy_sd_shared "src/basic/stat-util.h"
nm_copy_sd_shared "src/basic/stdio-util.h"
nm_copy_sd_shared "src/basic/string-table.c"
nm_copy_sd_shared "src/basic/string-table.h"
nm_copy_sd_shared "src/basic/string-util.c"
nm_copy_sd_shared "src/basic/string-util.h"
nm_copy_sd_shared "src/basic/strv.c"
nm_copy_sd_shared "src/basic/strv.h"
nm_copy_sd_shared "src/basic/strxcpyx.c"
nm_copy_sd_shared "src/basic/strxcpyx.h"
nm_copy_sd_shared "src/basic/time-util.c"
nm_copy_sd_shared "src/basic/time-util.h"
nm_copy_sd_shared "src/basic/tmpfile-util.c"
nm_copy_sd_shared "src/basic/tmpfile-util.h"
nm_copy_sd_shared "src/basic/umask-util.h"
nm_copy_sd_shared "src/basic/user-util.h"
nm_copy_sd_shared "src/basic/utf8.c"
nm_copy_sd_shared "src/basic/utf8.h"
nm_copy_sd_shared "src/basic/util.c"
nm_copy_sd_shared "src/basic/util.h"
nm_copy_sd_shared "src/fundamental/macro-fundamental.h"
nm_copy_sd_shared "src/fundamental/sha256.c"
nm_copy_sd_shared "src/fundamental/sha256.h"
nm_copy_sd_shared "src/fundamental/string-util-fundamental.c"
nm_copy_sd_shared "src/fundamental/string-util-fundamental.h"
nm_copy_sd_shared "src/shared/dns-domain.c"
nm_copy_sd_shared "src/shared/dns-domain.h"
nm_copy_sd_shared "src/shared/log-link.h"
nm_copy_sd_shared "src/shared/web-util.c"
nm_copy_sd_shared "src/shared/web-util.h"
nm_copy_sd_stdaux "src/basic/unaligned.h"
This commit is contained in:
Thomas Haller 2022-08-10 17:35:21 +02:00
parent 3a603c8764
commit 7c0de1517c
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
34 changed files with 273 additions and 2888 deletions

View file

@ -63,20 +63,26 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict) {
return 0;
}
static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, uint16_t arp_type, usec_t t, struct duid *ret_duid, size_t *ret_len) {
static int dhcp_identifier_set_duid_llt(
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t t,
struct duid *ret_duid,
size_t *ret_len) {
uint16_t time_from_2000y;
assert(addr);
assert(hw_addr);
assert(ret_duid);
assert(ret_len);
if (addr_len == 0)
if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
@ -88,33 +94,38 @@ static int dhcp_identifier_set_duid_llt(const uint8_t *addr, size_t addr_len, ui
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LLT);
unaligned_write_be16(&ret_duid->llt.htype, arp_type);
unaligned_write_be32(&ret_duid->llt.time, time_from_2000y);
memcpy(ret_duid->llt.haddr, addr, addr_len);
memcpy(ret_duid->llt.haddr, hw_addr->bytes, hw_addr->length);
*ret_len = offsetof(struct duid, llt.haddr) + addr_len;
*ret_len = offsetof(struct duid, llt.haddr) + hw_addr->length;
return 0;
}
static int dhcp_identifier_set_duid_ll(const uint8_t *addr, size_t addr_len, uint16_t arp_type, struct duid *ret_duid, size_t *ret_len) {
assert(addr);
static int dhcp_identifier_set_duid_ll(
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
struct duid *ret_duid,
size_t *ret_len) {
assert(hw_addr);
assert(ret_duid);
assert(ret_len);
if (addr_len == 0)
if (hw_addr->length == 0)
return -EOPNOTSUPP;
if (arp_type == ARPHRD_ETHER)
assert_return(addr_len == ETH_ALEN, -EINVAL);
assert_return(hw_addr->length == ETH_ALEN, -EINVAL);
else if (arp_type == ARPHRD_INFINIBAND)
assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
assert_return(hw_addr->length == INFINIBAND_ALEN, -EINVAL);
else
return -EOPNOTSUPP;
unaligned_write_be16(&ret_duid->type, DUID_TYPE_LL);
unaligned_write_be16(&ret_duid->ll.htype, arp_type);
memcpy(ret_duid->ll.haddr, addr, addr_len);
memcpy(ret_duid->ll.haddr, hw_addr->bytes, hw_addr->length);
*ret_len = offsetof(struct duid, ll.haddr) + addr_len;
*ret_len = offsetof(struct duid, ll.haddr) + hw_addr->length;
return 0;
}
@ -174,8 +185,7 @@ static int dhcp_identifier_set_duid_uuid(struct duid *ret_duid, size_t *ret_len)
int dhcp_identifier_set_duid(
DUIDType duid_type,
const uint8_t *addr,
size_t addr_len,
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@ -184,11 +194,11 @@ int dhcp_identifier_set_duid(
switch (duid_type) {
case DUID_TYPE_LLT:
return dhcp_identifier_set_duid_llt(addr, addr_len, arp_type, llt_time, ret_duid, ret_len);
return dhcp_identifier_set_duid_llt(hw_addr, arp_type, llt_time, ret_duid, ret_len);
case DUID_TYPE_EN:
return dhcp_identifier_set_duid_en(test_mode, ret_duid, ret_len);
case DUID_TYPE_LL:
return dhcp_identifier_set_duid_ll(addr, addr_len, arp_type, ret_duid, ret_len);
return dhcp_identifier_set_duid_ll(hw_addr, arp_type, ret_duid, ret_len);
case DUID_TYPE_UUID:
return dhcp_identifier_set_duid_uuid(ret_duid, ret_len);
default:
@ -198,8 +208,7 @@ int dhcp_identifier_set_duid(
int dhcp_identifier_set_iaid(
int ifindex,
const uint8_t *mac,
size_t mac_len,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret) {
@ -212,6 +221,10 @@ int dhcp_identifier_set_iaid(
uint64_t id;
int r;
assert(ifindex > 0);
assert(hw_addr);
assert(ret);
if (udev_available() && !use_mac) {
/* udev should be around */
@ -240,7 +253,7 @@ int dhcp_identifier_set_iaid(
id = siphash24(name, strlen(name), HASH_KEY.bytes);
else
/* fall back to MAC address if no predictable name available */
id = siphash24(mac, mac_len, HASH_KEY.bytes);
id = siphash24(hw_addr->bytes, hw_addr->length, HASH_KEY.bytes);
id32 = (id & 0xffffffff) ^ (id >> 32);

View file

@ -3,6 +3,7 @@
#include "sd-id128.h"
#include "ether-addr-util.h"
#include "macro.h"
#include "sparse-endian.h"
#include "time-util.h"
@ -58,8 +59,7 @@ int dhcp_validate_duid_len(DUIDType duid_type, size_t duid_len, bool strict);
int dhcp_identifier_set_duid_en(bool test_mode, struct duid *ret_duid, size_t *ret_len);
int dhcp_identifier_set_duid(
DUIDType duid_type,
const uint8_t *addr,
size_t addr_len,
const struct hw_addr_data *hw_addr,
uint16_t arp_type,
usec_t llt_time,
bool test_mode,
@ -67,8 +67,7 @@ int dhcp_identifier_set_duid(
size_t *ret_len);
int dhcp_identifier_set_iaid(
int ifindex,
const uint8_t *mac,
size_t mac_len,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret);

View file

@ -1,84 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/***
Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <stdint.h>
#include "sd-dhcp-client.h"
#include "dhcp-protocol.h"
#include "network-common.h"
#include "socket-util.h"
typedef struct sd_dhcp_option {
unsigned n_ref;
uint8_t option;
void *data;
size_t length;
} sd_dhcp_option;
typedef struct DHCPServerData {
struct in_addr *addr;
size_t size;
} DHCPServerData;
extern const struct hash_ops dhcp_option_hash_ops;
typedef struct sd_dhcp_client sd_dhcp_client;
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid,
const uint8_t *mac_addr, size_t mac_addr_len,
const uint8_t *bcast_addr, size_t bcast_addr_len,
uint16_t arp_type, uint16_t port);
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type);
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
const void *packet, size_t len);
int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
const void *packet, size_t len);
int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload,
uint8_t code, size_t optlen, const void *optval);
int dhcp_option_find_option(uint8_t *options, size_t length, uint8_t wanted_code, size_t *ret_offset);
int dhcp_option_remove_option(uint8_t *options, size_t buflen, uint8_t option_code);
typedef int (*dhcp_option_callback_t)(uint8_t code, uint8_t len,
const void *option, void *userdata);
int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **error_message);
int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
uint8_t type, uint16_t arp_type, uint8_t hlen, const uint8_t *chaddr,
size_t optlen, size_t *optoffset);
uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len);
void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
uint16_t source, be32_t destination_addr,
uint16_t destination, uint16_t len, int ip_service_type);
int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port);
void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode);
/* If we are invoking callbacks of a dhcp-client, ensure unreffing the
* client from the callback doesn't destroy the object we are working
* on */
#define DHCP_CLIENT_DONT_DESTROY(client) \
_cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client)
#define log_dhcp_client_errno(client, error, fmt, ...) \
log_interface_prefix_full_errno( \
"DHCPv4 client: ", \
sd_dhcp_client, client, \
error, fmt, ##__VA_ARGS__)
#define log_dhcp_client(client, fmt, ...) \
log_interface_prefix_full_errno_zerook( \
"DHCPv4 client: ", \
sd_dhcp_client, client, \
0, fmt, ##__VA_ARGS__)

View file

@ -1,255 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/***
Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <errno.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <stdio.h>
#include <string.h>
#include <linux/filter.h>
#include <linux/if_infiniband.h>
#include <linux/if_packet.h>
#include "dhcp-internal.h"
#include "fd-util.h"
#include "socket-util.h"
#include "unaligned.h"
static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
uint32_t xid,
const uint8_t *bcast_addr,
size_t bcast_addr_len,
const struct ether_addr *eth_mac,
uint16_t arp_type, uint8_t dhcp_hlen,
uint16_t port) {
struct sock_filter filter[] = {
BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */
BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0), /* packet >= DHCPPacket ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.protocol)), /* A <- IP protocol */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0), /* IP protocol == UDP ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags */
BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x20), /* A <- A & 0x20 (More Fragments bit) */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, ip.frag_off)), /* A <- Flags + Fragment offset */
BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x1fff), /* A <- A & 0x1fff (Fragment offset) */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, udp.dest)), /* A <- UDP destination port */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, port, 1, 0), /* UDP destination port == DHCP client port ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.op)), /* A <- DHCP op */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0), /* op == BOOTREPLY ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.htype)), /* A <- DHCP header type */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arp_type, 1, 0), /* header type == arp_type ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)), /* A <- client identifier */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0), /* client identifier == xid ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)), /* A <- MAC address length */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0), /* address length == dhcp_hlen ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
/* We only support MAC address length to be either 0 or 6 (ETH_ALEN). Optionally
* compare chaddr for ETH_ALEN bytes. */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 8), /* A (the MAC address length) == ETH_ALEN ? */
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(&eth_mac->ether_addr_octet[0])), /* X <- 4 bytes of client's MAC */
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(&eth_mac->ether_addr_octet[4])), /* X <- remainder of client's MAC */
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)), /* A <- DHCP magic cookie */
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0), /* cookie == DHCP magic cookie ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */
};
struct sock_fprog fprog = {
.len = ELEMENTSOF(filter),
.filter = filter
};
_cleanup_close_ int s = -1;
int r;
assert(ifindex > 0);
assert(link);
s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0)
return -errno;
r = setsockopt_int(s, SOL_PACKET, PACKET_AUXDATA, true);
if (r < 0)
return r;
r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
if (r < 0)
return -errno;
link->ll = (struct sockaddr_ll) {
.sll_family = AF_PACKET,
.sll_protocol = htobe16(ETH_P_IP),
.sll_ifindex = ifindex,
.sll_hatype = htobe16(arp_type),
.sll_halen = bcast_addr_len,
};
memcpy(link->ll.sll_addr, bcast_addr, bcast_addr_len); /* We may overflow link->ll. link->ll_buffer ensures we have enough space. */
r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll));
if (r < 0)
return -errno;
return TAKE_FD(s);
}
int dhcp_network_bind_raw_socket(
int ifindex,
union sockaddr_union *link,
uint32_t xid,
const uint8_t *mac_addr,
size_t mac_addr_len,
const uint8_t *bcast_addr,
size_t bcast_addr_len,
uint16_t arp_type,
uint16_t port) {
static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* Default broadcast address for IPoIB */
static const uint8_t ib_bcast[] = {
0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff
};
struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } };
const uint8_t *default_bcast_addr;
size_t expected_bcast_addr_len;
uint8_t dhcp_hlen = 0;
if (arp_type == ARPHRD_ETHER) {
assert_return(mac_addr_len == ETH_ALEN, -EINVAL);
memcpy(&eth_mac, mac_addr, ETH_ALEN);
dhcp_hlen = ETH_ALEN;
default_bcast_addr = eth_bcast;
expected_bcast_addr_len = ETH_ALEN;
} else if (arp_type == ARPHRD_INFINIBAND) {
default_bcast_addr = ib_bcast;
expected_bcast_addr_len = INFINIBAND_ALEN;
} else
return -EINVAL;
if (bcast_addr && bcast_addr_len > 0)
assert_return(bcast_addr_len == expected_bcast_addr_len, -EINVAL);
else {
bcast_addr = default_bcast_addr;
bcast_addr_len = expected_bcast_addr_len;
}
return _bind_raw_socket(ifindex, link, xid, bcast_addr, bcast_addr_len,
&eth_mac, arp_type, dhcp_hlen, port);
}
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {
union sockaddr_union src = {
.in.sin_family = AF_INET,
.in.sin_port = htobe16(port),
.in.sin_addr.s_addr = address,
};
_cleanup_close_ int s = -1;
int r;
s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0)
return -errno;
if (ip_service_type >= 0)
r = setsockopt_int(s, IPPROTO_IP, IP_TOS, ip_service_type);
else
r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6);
if (r < 0)
return r;
r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
return r;
if (ifindex > 0) {
r = socket_bind_to_ifindex(s, ifindex);
if (r < 0)
return r;
}
if (port == DHCP_PORT_SERVER) {
r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true);
if (r < 0)
return r;
if (address == INADDR_ANY) {
/* IP_PKTINFO filter should not be applied when packets are
allowed to enter/leave through the interface other than
DHCP server sits on(BindToInterface option). */
r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
return r;
}
} else {
r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true);
if (r < 0)
return r;
}
if (bind(s, &src.sa, sizeof(src.in)) < 0)
return -errno;
return TAKE_FD(s);
}
int dhcp_network_send_raw_socket(
int s,
const union sockaddr_union *link,
const void *packet,
size_t len) {
/* Do not add assert(s >= 0) here, as this is called in fuzz-dhcp-server, and in that case this
* function should fail with negative errno. */
assert(link);
assert(packet);
assert(len > 0);
if (sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)) < 0)
return -errno;
return 0;
}
int dhcp_network_send_udp_socket(
int s,
be32_t address,
uint16_t port,
const void *packet,
size_t len) {
union sockaddr_union dest = {
.in.sin_family = AF_INET,
.in.sin_port = htobe16(port),
.in.sin_addr.s_addr = address,
};
assert(s >= 0);
assert(packet);
assert(len > 0);
if (sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)) < 0)
return -errno;
return 0;
}

View file

@ -1,108 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
/***
Copyright © 2013 Intel Corporation. All rights reserved.
***/
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <stdint.h>
#include "macro.h"
#include "sparse-endian.h"
struct DHCPMessage {
uint8_t op;
uint8_t htype;
uint8_t hlen;
uint8_t hops;
be32_t xid;
be16_t secs;
be16_t flags;
be32_t ciaddr;
be32_t yiaddr;
be32_t siaddr;
be32_t giaddr;
uint8_t chaddr[16];
uint8_t sname[64];
uint8_t file[128];
be32_t magic;
uint8_t options[0];
} _packed_;
typedef struct DHCPMessage DHCPMessage;
struct DHCPPacket {
struct iphdr ip;
struct udphdr udp;
DHCPMessage dhcp;
} _packed_;
typedef struct DHCPPacket DHCPPacket;
#define DHCP_IP_SIZE (int32_t)(sizeof(struct iphdr))
#define DHCP_IP_UDP_SIZE (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE)
#define DHCP_MESSAGE_SIZE (int32_t)(sizeof(DHCPMessage))
#define DHCP_DEFAULT_MIN_SIZE 576 /* the minimum internet hosts must be able to receive */
#define DHCP_MIN_OPTIONS_SIZE (DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE)
#define DHCP_MAGIC_COOKIE (uint32_t)(0x63825363)
enum {
DHCP_PORT_SERVER = 67,
DHCP_PORT_CLIENT = 68,
};
enum DHCPState {
DHCP_STATE_INIT = 0,
DHCP_STATE_SELECTING = 1,
DHCP_STATE_INIT_REBOOT = 2,
DHCP_STATE_REBOOTING = 3,
DHCP_STATE_REQUESTING = 4,
DHCP_STATE_BOUND = 5,
DHCP_STATE_RENEWING = 6,
DHCP_STATE_REBINDING = 7,
DHCP_STATE_STOPPED = 8,
};
typedef enum DHCPState DHCPState;
enum {
BOOTREQUEST = 1,
BOOTREPLY = 2,
};
enum {
DHCP_DISCOVER = 1, /* [RFC2132] */
DHCP_OFFER = 2, /* [RFC2132] */
DHCP_REQUEST = 3, /* [RFC2132] */
DHCP_DECLINE = 4, /* [RFC2132] */
DHCP_ACK = 5, /* [RFC2132] */
DHCP_NAK = 6, /* [RFC2132] */
DHCP_RELEASE = 7, /* [RFC2132] */
DHCP_INFORM = 8, /* [RFC2132] */
DHCP_FORCERENEW = 9, /* [RFC3203] */
DHCPLEASEQUERY = 10, /* [RFC4388] */
DHCPLEASEUNASSIGNED = 11, /* [RFC4388] */
DHCPLEASEUNKNOWN = 12, /* [RFC4388] */
DHCPLEASEACTIVE = 13, /* [RFC4388] */
DHCPBULKLEASEQUERY = 14, /* [RFC6926] */
DHCPLEASEQUERYDONE = 15, /* [RFC6926] */
DHCPACTIVELEASEQUERY = 16, /* [RFC7724] */
DHCPLEASEQUERYSTATUS = 17, /* [RFC7724] */
DHCPTLS = 18, /* [RFC7724] */
};
enum {
DHCP_OVERLOAD_FILE = 1,
DHCP_OVERLOAD_SNAME = 2,
};
#define DHCP_MAX_FQDN_LENGTH 255
enum {
DHCP_FQDN_FLAG_S = (1 << 0),
DHCP_FQDN_FLAG_O = (1 << 1),
DHCP_FQDN_FLAG_E = (1 << 2),
DHCP_FQDN_FLAG_N = (1 << 3),
};

View file

@ -71,6 +71,7 @@ struct sd_dhcp6_client {
char **vendor_class;
OrderedHashmap *extra_options;
OrderedSet *vendor_options;
bool rapid_commit;
struct sd_dhcp6_lease *lease;

View file

@ -508,7 +508,7 @@ int dhcp6_option_parse(
if (buflen < offsetof(DHCP6Option, data))
return -EBADMSG;
if (*offset >= buflen - offsetof(DHCP6Option, data))
if (*offset > buflen - offsetof(DHCP6Option, data))
return -EBADMSG;
len = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, len));
@ -518,14 +518,14 @@ int dhcp6_option_parse(
*ret_option_code = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, code));
*ret_option_data_len = len;
*ret_option_data = buf + *offset + offsetof(DHCP6Option, data);
*ret_option_data = len == 0 ? NULL : buf + *offset + offsetof(DHCP6Option, data);
*offset += offsetof(DHCP6Option, data) + len;
return 0;
}
int dhcp6_option_parse_status(const uint8_t *data, size_t data_len, char **ret_status_message) {
assert(data);
assert(data || data_len == 0);
if (data_len < sizeof(uint16_t))
return -EBADMSG;
@ -803,7 +803,7 @@ int dhcp6_option_parse_addresses(
struct in6_addr **addrs,
size_t *count) {
assert(optval);
assert(optval || optlen == 0);
assert(addrs);
assert(count);
@ -826,8 +826,8 @@ static int parse_domain(const uint8_t **data, size_t *len, char **ret) {
int r;
assert(data);
assert(*data);
assert(len);
assert(*data || *len == 0);
assert(ret);
optval = *data;
@ -891,7 +891,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, size_t optlen, char **r
_cleanup_free_ char *domain = NULL;
int r;
assert(optval);
assert(optval || optlen == 0);
assert(ret);
r = parse_domain(&optval, &optlen, &domain);
@ -910,7 +910,7 @@ int dhcp6_option_parse_domainname_list(const uint8_t *optval, size_t optlen, cha
_cleanup_strv_free_ char **names = NULL;
int r;
assert(optval);
assert(optval || optlen == 0);
assert(ret);
if (optlen <= 1)

File diff suppressed because it is too large Load diff

View file

@ -116,9 +116,8 @@ int sd_dhcp6_client_set_mac(
return 0;
}
memcpy(client->hw_addr.bytes, addr, addr_len);
client->hw_addr.length = addr_len;
client->arp_type = arp_type;
hw_addr_set(&client->hw_addr, addr, addr_len);
return 0;
}
@ -216,8 +215,8 @@ static int dhcp6_client_set_duid_internal(
client->duid_len = sizeof(client->duid.type) + duid_len;
} else {
r = dhcp_identifier_set_duid(duid_type, client->hw_addr.bytes, client->hw_addr.length,
client->arp_type, llt_time, client->test_mode, &client->duid, &client->duid_len);
r = dhcp_identifier_set_duid(duid_type, &client->hw_addr, client->arp_type, llt_time,
client->test_mode, &client->duid, &client->duid_len);
if (r == -EOPNOTSUPP)
return log_dhcp6_client_errno(client, r,
"Failed to set %s. MAC address is not set or "
@ -300,7 +299,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
if (client->iaid_set)
return 0;
r = dhcp_identifier_set_iaid(client->ifindex, client->hw_addr.bytes, client->hw_addr.length,
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&iaid);
@ -491,6 +490,14 @@ int dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transactio
return 0;
}
int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp6_client_is_running(client), -EBUSY);
client->rapid_commit = enable;
return 0;
}
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
assert_return(client, -EINVAL);
@ -714,9 +721,11 @@ int dhcp6_client_send_message(sd_dhcp6_client *client) {
break;
case DHCP6_STATE_SOLICITATION:
r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
if (r < 0)
return r;
if (client->rapid_commit) {
r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
if (r < 0)
return r;
}
r = client_append_common_options_in_managed_mode(client, &opt, &optlen,
&client->ia_na, &client->ia_pd);
@ -1160,6 +1169,10 @@ static int client_process_advertise_or_rapid_commit_reply(
if (message->type == DHCP6_MESSAGE_REPLY) {
bool rapid_commit;
if (!client->rapid_commit)
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
"Received unexpected reply message, even we sent a solicit message without the rapid commit option, ignoring.");
r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
if (r < 0)
return r;
@ -1467,6 +1480,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
.ifindex = -1,
.request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD,
.fd = -1,
.rapid_commit = true,
};
*ret = TAKE_PTR(client);

View file

@ -467,7 +467,9 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse(message->options, len, &offset, &optcode, &optlen, &optval);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r,
"Failed to parse option header at offset %zu of total length %zu: %m",
offset, len);
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
@ -477,7 +479,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_clientid(lease, optval, optlen);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set client ID: %m");
break;
@ -488,17 +490,17 @@ static int dhcp6_lease_parse_message(
r = dhcp6_lease_set_serverid(lease, optval, optlen);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set server ID: %m");
break;
case SD_DHCP6_OPTION_PREFERENCE:
if (optlen != 1)
return -EINVAL;
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Received invalid length for preference.");
r = dhcp6_lease_set_preference(lease, optval[0]);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set preference: %m");
break;
@ -507,7 +509,7 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_status(optval, optlen, &msg);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to parse status code: %m");
if (r > 0)
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
@ -527,9 +529,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_na.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
return r;
if (r < 0)
return log_oom_debug();
if (r < 0) {
log_dhcp6_client_errno(client, r, "Failed to parse IA_NA option, ignoring: %m");
continue;
}
if (lease->ia_na) {
log_dhcp6_client(client, "Received duplicate matching IA_NA option, ignoring.");
@ -550,9 +554,11 @@ static int dhcp6_lease_parse_message(
r = dhcp6_option_parse_ia(client, client->ia_pd.header.id, optcode, optlen, optval, &ia);
if (r == -ENOMEM)
return r;
if (r < 0)
return log_oom_debug();
if (r < 0) {
log_dhcp6_client_errno(client, r, "Failed to parse IA_PD option, ignoring: %m");
continue;
}
if (lease->ia_pd) {
log_dhcp6_client(client, "Received duplicate matching IA_PD option, ignoring.");
@ -564,9 +570,12 @@ static int dhcp6_lease_parse_message(
break;
}
case SD_DHCP6_OPTION_RAPID_COMMIT:
if (optlen != 0)
log_dhcp6_client(client, "Received rapid commit option with an invalid length (%zu), ignoring.", optlen);
r = dhcp6_lease_set_rapid_commit(lease);
if (r < 0)
return r;
return log_dhcp6_client_errno(client, r, "Failed to set rapid commit flag: %m");
break;
@ -607,7 +616,8 @@ static int dhcp6_lease_parse_message(
case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME:
if (optlen != 4)
return -EINVAL;
return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL),
"Received information refresh time option with an invalid length (%zu).", optlen);
irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC;
break;

View file

@ -49,19 +49,19 @@ static bool event_source_is_offline(sd_event_source *s) {
}
static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = {
[SOURCE_IO] = "io",
[SOURCE_TIME_REALTIME] = "realtime",
[SOURCE_TIME_BOOTTIME] = "bootime",
[SOURCE_TIME_MONOTONIC] = "monotonic",
[SOURCE_IO] = "io",
[SOURCE_TIME_REALTIME] = "realtime",
[SOURCE_TIME_BOOTTIME] = "bootime",
[SOURCE_TIME_MONOTONIC] = "monotonic",
[SOURCE_TIME_REALTIME_ALARM] = "realtime-alarm",
[SOURCE_TIME_BOOTTIME_ALARM] = "boottime-alarm",
[SOURCE_SIGNAL] = "signal",
[SOURCE_CHILD] = "child",
[SOURCE_DEFER] = "defer",
[SOURCE_POST] = "post",
[SOURCE_EXIT] = "exit",
[SOURCE_WATCHDOG] = "watchdog",
[SOURCE_INOTIFY] = "inotify",
[SOURCE_SIGNAL] = "signal",
[SOURCE_CHILD] = "child",
[SOURCE_DEFER] = "defer",
[SOURCE_POST] = "post",
[SOURCE_EXIT] = "exit",
[SOURCE_WATCHDOG] = "watchdog",
[SOURCE_INOTIFY] = "inotify",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int);
@ -124,10 +124,10 @@ struct sd_event {
Hashmap *inotify_data; /* indexed by priority */
/* A list of inode structures that still have an fd open, that we need to close before the next loop iteration */
LIST_HEAD(struct inode_data, inode_data_to_close);
LIST_HEAD(struct inode_data, inode_data_to_close_list);
/* A list of inotify objects that already have events buffered which aren't processed yet */
LIST_HEAD(struct inotify_data, inotify_data_buffered);
LIST_HEAD(struct inotify_data, buffered_inotify_data_list);
pid_t original_pid;
@ -420,6 +420,8 @@ fail:
}
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
#define PROTECT_EVENT(e) \
_unused_ _cleanup_(sd_event_unrefp) sd_event *_ref = sd_event_ref(e);
_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
if (s)
@ -1692,7 +1694,7 @@ static void event_free_inotify_data(sd_event *e, struct inotify_data *d) {
assert(hashmap_isempty(d->wd));
if (d->buffer_filled > 0)
LIST_REMOVE(buffered, e->inotify_data_buffered, d);
LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
hashmap_free(d->inodes);
hashmap_free(d->wd);
@ -1801,10 +1803,10 @@ static void event_free_inode_data(
if (!d)
return;
assert(LIST_IS_EMPTY(d->event_sources));
assert(!d->event_sources);
if (d->fd >= 0) {
LIST_REMOVE(to_close, e->inode_data_to_close, d);
LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
safe_close(d->fd);
}
@ -1864,7 +1866,7 @@ static void event_gc_inode_data(
if (!d)
return;
if (!LIST_IS_EMPTY(d->event_sources))
if (d->event_sources)
return;
inotify_data = d->inotify_data;
@ -2066,7 +2068,7 @@ static int event_add_inotify_fd_internal(
}
}
LIST_PREPEND(to_close, e->inode_data_to_close, inode_data);
LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data);
}
/* Link our event source to the inode data object */
@ -2139,12 +2141,9 @@ static sd_event_source* event_source_free(sd_event_source *s) {
* we still retain a valid event source object after
* the callback. */
if (s->dispatching) {
if (s->type == SOURCE_IO)
source_io_unregister(s);
if (s->dispatching)
source_disconnect(s);
} else
else
source_free(s);
return NULL;
@ -2353,7 +2352,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority)
goto fail;
}
LIST_PREPEND(to_close, s->event->inode_data_to_close, new_inode_data);
LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data);
}
/* Move the event source to the new inode data structure */
@ -3419,7 +3418,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t
assert(n > 0);
d->buffer_filled = (size_t) n;
LIST_PREPEND(buffered, e->inotify_data_buffered, d);
LIST_PREPEND(buffered, e->buffered_inotify_data_list, d);
return 1;
}
@ -3437,7 +3436,7 @@ static void event_inotify_data_drop(sd_event *e, struct inotify_data *d, size_t
d->buffer_filled -= sz;
if (d->buffer_filled == 0)
LIST_REMOVE(buffered, e->inotify_data_buffered, d);
LIST_REMOVE(buffered, e->buffered_inotify_data_list, d);
}
static int event_inotify_data_process(sd_event *e, struct inotify_data *d) {
@ -3530,7 +3529,7 @@ static int process_inotify(sd_event *e) {
assert(e);
LIST_FOREACH(buffered, d, e->inotify_data_buffered) {
LIST_FOREACH(buffered, d, e->buffered_inotify_data_list) {
r = event_inotify_data_process(e, d);
if (r < 0)
return r;
@ -3542,8 +3541,8 @@ static int process_inotify(sd_event *e) {
}
static int source_dispatch(sd_event_source *s) {
_cleanup_(sd_event_unrefp) sd_event *saved_event = NULL;
EventSourceType saved_type;
sd_event *saved_event;
int r = 0;
assert(s);
@ -3555,7 +3554,8 @@ static int source_dispatch(sd_event_source *s) {
/* Similarly, store a reference to the event loop object, so that we can still access it after the
* callback might have invalidated/disconnected the event source. */
saved_event = sd_event_ref(s->event);
saved_event = s->event;
PROTECT_EVENT(saved_event);
/* Check if we hit the ratelimit for this event source, and if so, let's disable it. */
assert(!s->ratelimited);
@ -3756,7 +3756,7 @@ static int dispatch_exit(sd_event *e) {
return 0;
}
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
e->iteration++;
e->state = SD_EVENT_EXITING;
r = source_dispatch(p);
@ -3827,11 +3827,11 @@ static void event_close_inode_data_fds(sd_event *e) {
* for the inode). Hence, let's close them when entering the first iteration after they were added, as a
* compromise. */
while ((d = e->inode_data_to_close)) {
while ((d = e->inode_data_to_close_list)) {
assert(d->fd >= 0);
d->fd = safe_close(d->fd);
LIST_REMOVE(to_close, e->inode_data_to_close, d);
LIST_REMOVE(to_close, e->inode_data_to_close_list, d);
}
}
@ -3850,7 +3850,7 @@ _public_ int sd_event_prepare(sd_event *e) {
assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO);
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
if (e->exit_requested)
goto pending;
@ -3885,7 +3885,7 @@ _public_ int sd_event_prepare(sd_event *e) {
event_close_inode_data_fds(e);
if (event_next_pending(e) || e->need_process_child || !LIST_IS_EMPTY(e->inotify_data_buffered))
if (event_next_pending(e) || e->need_process_child || e->buffered_inotify_data_list)
goto pending;
e->state = SD_EVENT_ARMED;
@ -3965,7 +3965,7 @@ static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t
n_event_max = MALLOC_ELEMENTSOF(e->event_queue);
/* If we still have inotify data buffered, then query the other fds, but don't wait on it */
if (!LIST_IS_EMPTY(e->inotify_data_buffered))
if (e->buffered_inotify_data_list)
timeout = 0;
for (;;) {
@ -4180,7 +4180,7 @@ _public_ int sd_event_dispatch(sd_event *e) {
p = event_next_pending(e);
if (p) {
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
e->state = SD_EVENT_RUNNING;
r = source_dispatch(p);
@ -4232,7 +4232,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
}
/* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
r = sd_event_prepare(e);
if (r == 0)
@ -4262,7 +4262,7 @@ _public_ int sd_event_loop(sd_event *e) {
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
_unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
PROTECT_EVENT(e);
while (e->state != SD_EVENT_FINISHED) {
r = sd_event_run(e, UINT64_MAX);

View file

@ -85,7 +85,7 @@ typedef void (*_sd_destroy_t)(void *userdata);
#endif
#ifndef _SD_ARRAY_STATIC
# if __STDC_VERSION__ >= 199901L
# if __STDC_VERSION__ >= 199901L && !defined(__cplusplus)
# define _SD_ARRAY_STATIC static
# else
# define _SD_ARRAY_STATIC

View file

@ -262,6 +262,7 @@ int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
int request);
int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client,
sd_dhcp6_option *v);
int sd_dhcp6_client_set_rapid_commit(sd_dhcp6_client *client, int enable);
int sd_dhcp6_client_get_lease(
sd_dhcp6_client *client,

View file

@ -50,16 +50,30 @@ typedef void* (*mfree_func_t)(void *p);
#define malloc0(n) (calloc(1, (n) ?: 1))
#define free_and_replace(a, b) \
#define free_and_replace_full(a, b, free_func) \
({ \
typeof(a)* _a = &(a); \
typeof(b)* _b = &(b); \
free(*_a); \
free_func(*_a); \
*_a = *_b; \
*_b = NULL; \
0; \
})
#define free_and_replace(a, b) \
free_and_replace_full(a, b, free)
/* This is similar to free_and_replace_full(), but NULL is not assigned to 'b', and its reference counter is
* increased. */
#define unref_and_replace_full(a, b, ref_func, unref_func) \
({ \
typeof(a)* _a = &(a); \
typeof(b) _b = ref_func(b); \
unref_func(*_a); \
*_a = _b; \
0; \
})
void* memdup(const void *p, size_t l) _alloc_(2);
void* memdup_suffix0(const void *p, size_t l); /* We can't use _alloc_() here, since we return a buffer one byte larger than the specified size */

View file

@ -33,6 +33,15 @@ char *hw_addr_to_string_full(
return buffer;
}
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length) {
assert(addr);
assert(length <= HW_ADDR_MAX_SIZE);
addr->length = length;
memcpy_safe(addr->bytes, bytes, length);
return addr;
}
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b) {
int r;

View file

@ -52,6 +52,8 @@ static inline char *hw_addr_to_string(const struct hw_addr_data *addr, char buff
#define HW_ADDR_NULL ((const struct hw_addr_data){})
struct hw_addr_data *hw_addr_set(struct hw_addr_data *addr, const uint8_t *bytes, size_t length);
void hw_addr_hash_func(const struct hw_addr_data *p, struct siphash *state);
int hw_addr_compare(const struct hw_addr_data *a, const struct hw_addr_data *b);
static inline bool hw_addr_equal(const struct hw_addr_data *a, const struct hw_addr_data *b) {

View file

@ -3,7 +3,9 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/btrfs.h>
#if WANT_LINUX_FS_H
#include <linux/fs.h>
#endif
#include <linux/magic.h>
#include <sys/ioctl.h>
#include <sys/resource.h>

View file

@ -4,6 +4,7 @@
#include "hash-funcs.h"
#include "path-util.h"
#include "strv.h"
void string_hash_func(const char *p, struct siphash *state) {
siphash24_compress(p, strlen(p) + 1, state);
@ -15,6 +16,9 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(string_hash_ops_free,
DEFINE_HASH_OPS_FULL(string_hash_ops_free_free,
char, string_hash_func, string_compare_func, free,
void, free);
DEFINE_HASH_OPS_FULL(string_hash_ops_free_strv_free,
char, string_hash_func, string_compare_func, free,
char*, strv_free);
void path_hash_func(const char *q, struct siphash *state) {
bool add_slash = false;

View file

@ -78,6 +78,7 @@ void string_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops string_hash_ops;
extern const struct hash_ops string_hash_ops_free;
extern const struct hash_ops string_hash_ops_free_free;
extern const struct hash_ops string_hash_ops_free_strv_free;
void path_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops path_hash_ops;

View file

@ -90,12 +90,7 @@ OrderedHashmap* _ordered_hashmap_new(const struct hash_ops *hash_ops HASHMAP_DE
#define ordered_hashmap_new(ops) _ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
#define hashmap_free_and_replace(a, b) \
({ \
hashmap_free(a); \
(a) = (b); \
(b) = NULL; \
0; \
})
free_and_replace_full(a, b, hashmap_free)
HashmapBase* _hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
static inline Hashmap* hashmap_free(Hashmap *h) {

View file

@ -49,6 +49,20 @@ bool in4_addr_is_link_local(const struct in_addr *a) {
return (be32toh(a->s_addr) & UINT32_C(0xFFFF0000)) == (UINT32_C(169) << 24 | UINT32_C(254) << 16);
}
bool in4_addr_is_link_local_dynamic(const struct in_addr *a) {
assert(a);
if (!in4_addr_is_link_local(a))
return false;
/* 169.254.0.0/24 and 169.254.255.0/24 must not be used for the dynamic IPv4LL assignment.
* See RFC 3927 Section 2.1:
* The IPv4 prefix 169.254/16 is registered with the IANA for this purpose. The first 256 and last
* 256 addresses in the 169.254/16 prefix are reserved for future use and MUST NOT be selected by a
* host using this dynamic configuration mechanism. */
return !IN_SET(be32toh(a->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
}
bool in6_addr_is_link_local(const struct in6_addr *a) {
assert(a);

View file

@ -44,6 +44,7 @@ static inline bool in_addr_data_is_set(const struct in_addr_data *a) {
int in_addr_is_multicast(int family, const union in_addr_union *u);
bool in4_addr_is_link_local(const struct in_addr *a);
bool in4_addr_is_link_local_dynamic(const struct in_addr *a);
bool in6_addr_is_link_local(const struct in6_addr *a);
int in_addr_is_link_local(int family, const union in_addr_union *u);
bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);

View file

@ -170,9 +170,6 @@
i != (p); \
i = i->name##_next ? i->name##_next : (head))
#define LIST_IS_EMPTY(head) \
(!(head))
/* Join two lists tail to head: a->b, c->d to a->b->c->d and de-initialise second list */
#define LIST_JOIN(name,a,b) \
do { \

View file

@ -87,10 +87,6 @@
_Pragma("GCC diagnostic push")
#endif
#define DISABLE_WARNING_FLOAT_EQUAL \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wfloat-equal\"")
#define DISABLE_WARNING_TYPE_LIMITS \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wtype-limits\"")

View file

@ -1055,7 +1055,7 @@ int path_extract_filename(const char *path, char **ret) {
return -ENOMEM;
*ret = TAKE_PTR(a);
return strlen(c) > (size_t)r ? O_DIRECTORY : 0;
return strlen(c) > (size_t) r ? O_DIRECTORY : 0;
}
int path_extract_directory(const char *path, char **ret) {
@ -1109,7 +1109,7 @@ bool filename_is_valid(const char *p) {
if (isempty(p))
return false;
if (dot_or_dot_dot(p))
if (dot_or_dot_dot(p)) /* Yes, in this context we consider "." and ".." invalid */
return false;
e = strchrnul(p, '/');

View file

@ -43,12 +43,16 @@
#endif
static inline bool is_path(const char *p) {
assert(p);
if (!p) /* A NULL pointer is definitely not a path */
return false;
return strchr(p, '/');
}
static inline bool path_is_absolute(const char *p) {
assert(p);
if (!p) /* A NULL pointer is definitely not an absolute path */
return false;
return p[0] == '/';
}
@ -157,10 +161,10 @@ int path_extract_directory(const char *path, char **ret);
bool filename_is_valid(const char *p) _pure_;
bool path_is_valid_full(const char *p, bool accept_dot_dot) _pure_;
static inline bool path_is_valid(const char *p) {
return path_is_valid_full(p, true);
return path_is_valid_full(p, /* accept_dot_dot= */ true);
}
static inline bool path_is_safe(const char *p) {
return path_is_valid_full(p, false);
return path_is_valid_full(p, /* accept_dot_dot= */ false);
}
bool path_is_normalized(const char *p) _pure_;

View file

@ -1147,7 +1147,7 @@ void reset_cached_pid(void) {
pid_t getpid_cached(void) {
static bool installed = false;
pid_t current_value;
pid_t current_value = CACHED_PID_UNSET;
/* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a
* system call each time. This restores glibc behaviour from before 2.24, when getpid() was unconditionally
@ -1158,7 +1158,13 @@ pid_t getpid_cached(void) {
* https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c579f48edba88380635ab98cb612030e3ed8691e
*/
current_value = __sync_val_compare_and_swap(&cached_pid, CACHED_PID_UNSET, CACHED_PID_BUSY);
__atomic_compare_exchange_n(
&cached_pid,
&current_value,
CACHED_PID_BUSY,
false,
__ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
switch (current_value) {
@ -1579,6 +1585,30 @@ bool invoked_as(char *argv[], const char *token) {
return strstr(last_path_component(argv[0]), token);
}
bool invoked_by_systemd(void) {
int r;
/* If the process is directly executed by PID1 (e.g. ExecStart= or generator), systemd-importd,
* or systemd-homed, then $SYSTEMD_EXEC_PID= is set, and read the command line. */
const char *e = getenv("SYSTEMD_EXEC_PID");
if (!e)
return false;
if (streq(e, "*"))
/* For testing. */
return true;
pid_t p;
r = parse_pid(e, &p);
if (r < 0) {
/* We know that systemd sets the variable correctly. Something else must have set it. */
log_debug_errno(r, "Failed to parse \"SYSTEMD_EXEC_PID=%s\", ignoring: %m", e);
return false;
}
return getpid_cached() == p;
}
_noreturn_ void freeze(void) {
log_close();

View file

@ -190,6 +190,8 @@ int setpriority_closest(int priority);
bool invoked_as(char *argv[], const char *token);
bool invoked_by_systemd(void);
_noreturn_ void freeze(void);
bool argv_looks_like_help(int argc, char **argv);

View file

@ -6,12 +6,7 @@
#include "macro.h"
#define set_free_and_replace(a, b) \
({ \
set_free(a); \
(a) = (b); \
(b) = NULL; \
0; \
})
free_and_replace_full(a, b, set_free)
Set* _set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) _set_new(ops HASHMAP_DEBUG_SRC_ARGS)

View file

@ -35,31 +35,23 @@ int is_symlink(const char *path) {
return !!S_ISLNK(info.st_mode);
}
int is_dir(const char* path, bool follow) {
int is_dir_full(int atfd, const char* path, bool follow) {
struct stat st;
int r;
assert(path);
assert(atfd >= 0 || atfd == AT_FDCWD);
assert(atfd >= 0 || path);
if (follow)
r = stat(path, &st);
if (path)
r = fstatat(atfd, path, &st, follow ? 0 : AT_SYMLINK_NOFOLLOW);
else
r = lstat(path, &st);
r = fstat(atfd, &st);
if (r < 0)
return -errno;
return !!S_ISDIR(st.st_mode);
}
int is_dir_fd(int fd) {
struct stat st;
if (fstat(fd, &st) < 0)
return -errno;
return !!S_ISDIR(st.st_mode);
}
int is_device_node(const char *path) {
struct stat info;

View file

@ -13,8 +13,13 @@
#include "missing_stat.h"
int is_symlink(const char *path);
int is_dir(const char *path, bool follow);
int is_dir_fd(int fd);
int is_dir_full(int atfd, const char *fname, bool follow);
static inline int is_dir(const char *path, bool follow) {
return is_dir_full(AT_FDCWD, path, follow);
}
static inline int is_dir_fd(int fd) {
return is_dir_full(fd, NULL, false);
}
int is_device_node(const char *path);
int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup);

View file

@ -258,14 +258,7 @@ int strv_extend_n(char ***l, const char *value, size_t n);
int fputstrv(FILE *f, char * const *l, const char *separator, bool *space);
#define strv_free_and_replace(a, b) \
({ \
char ***_a = &(a); \
char ***_b = &(b); \
strv_free(*_a); \
(*_a) = (*_b); \
(*_b) = NULL; \
0; \
})
free_and_replace_full(a, b, strv_free)
extern const struct hash_ops string_strv_hash_ops;
int _string_strv_hashmap_put(Hashmap **h, const char *key, const char *value HASHMAP_DEBUG_PARAMS);

View file

@ -591,7 +591,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
t = b;
}
n = MIN((size_t) k, l);
n = MIN((size_t) k, l-1);
l -= n;
p += n;

View file

@ -42,7 +42,7 @@
# define _alloc_(...) __attribute__((__alloc_size__(__VA_ARGS__)))
#endif
#if __GNUC__ >= 7 || __clang__
#if __GNUC__ >= 7 || (defined(__clang__) && __clang_major__ >= 10)
# define _fallthrough_ __attribute__((__fallthrough__))
#else
# define _fallthrough_
@ -95,6 +95,20 @@
_expr_; \
})
#define ASSERT_NONNEG(expr) \
({ \
typeof(expr) _expr_ = (expr), _zero = 0; \
assert(_expr_ >= _zero); \
_expr_; \
})
#define ASSERT_SE_NONNEG(expr) \
({ \
typeof(expr) _expr_ = (expr), _zero = 0; \
assert_se(_expr_ >= _zero); \
_expr_; \
})
#define assert_cc(expr) static_assert(expr, #expr)
@ -106,10 +120,10 @@
* on this macro will run concurrently to all other code conditionalized
* the same way, there's no ordering or completion enforced. */
#define ONCE __ONCE(UNIQ_T(_once_, UNIQ))
#define __ONCE(o) \
({ \
static bool (o) = false; \
__sync_bool_compare_and_swap(&(o), false, true); \
#define __ONCE(o) \
({ \
static bool (o) = false; \
__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
})
#undef MAX
@ -186,6 +200,19 @@
MIN(_c, z); \
})
/* Returns true if the passed integer is a positive power of two */
#define CONST_ISPOWEROF2(x) \
((x) > 0 && ((x) & ((x) - 1)) == 0)
#define ISPOWEROF2(x) \
__builtin_choose_expr( \
__builtin_constant_p(x), \
CONST_ISPOWEROF2(x), \
({ \
const typeof(x) _x = (x); \
CONST_ISPOWEROF2(_x); \
}))
#define LESS_BY(a, b) __LESS_BY(UNIQ, (a), UNIQ, (b))
#define __LESS_BY(aq, a, bq, b) \
({ \
@ -300,16 +327,7 @@
})
static inline size_t ALIGN_TO(size_t l, size_t ali) {
/* Check that alignment is exponent of 2 */
#if SIZE_MAX == UINT_MAX
assert(__builtin_popcount(ali) == 1);
#elif SIZE_MAX == ULONG_MAX
assert(__builtin_popcountl(ali) == 1);
#elif SIZE_MAX == ULLONG_MAX
assert(__builtin_popcountll(ali) == 1);
#else
#error "Unexpected size_t"
#endif
assert(ISPOWEROF2(ali));
if (l > SIZE_MAX - (ali - 1))
return SIZE_MAX; /* indicate overflow */
@ -330,7 +348,7 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
__builtin_choose_expr( \
__builtin_constant_p(l) && \
__builtin_constant_p(ali) && \
__builtin_popcountll(ali) == 1 && /* is power of 2? */ \
CONST_ISPOWEROF2(ali) && \
(l <= SIZE_MAX - (ali - 1)), /* overflow? */ \
((l) + (ali) - 1) & ~((ali) - 1), \
VOID_0)