mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-04 22:20:27 +01:00
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:
parent
3a603c8764
commit
7c0de1517c
34 changed files with 273 additions and 2888 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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__)
|
||||
|
|
@ -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(ð_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(ð_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(ð_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,
|
||||
ð_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;
|
||||
}
|
||||
|
|
@ -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),
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 { \
|
||||
|
|
|
|||
|
|
@ -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\"")
|
||||
|
|
|
|||
|
|
@ -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, '/');
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
¤t_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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue