1
0
mirror of https://github.com/systemd/systemd synced 2026-04-17 12:34:51 +02:00

Compare commits

..

No commits in common. "b0f83c2d82df97c67c3eecc1b18c2eded2d0cdf9" and "e5b90b30c2bb5eb37249655ec12f114d4e23db44" have entirely different histories.

25 changed files with 323 additions and 424 deletions

View File

@ -171,19 +171,11 @@
<para><varname>KERNEL_INSTALL_BOOT_ROOT=</varname> is set for the plugins to the root directory (mount point, usually) of the hierarchy
where boot-loader entries, kernel images, and associated resources should be placed. Can be overridden by setting <varname>BOOT_ROOT=</varname>.</para>
<para><varname>KERNEL_INSTALL_LAYOUT=bls|other|...</varname> is set for the plugins to specify the installation layout.
<para><varname>KERNEL_INSTALL_LAYOUT=bls|other|...</varname> specifies the installation layout.
Defaults to <option>bls</option> if <filename>$BOOT/<replaceable>MACHINE-ID</replaceable></filename> exists, or <option>other</option> otherwise.
Additional layout names may be defined by convention. If a plugin uses a special layout,
it's encouraged to declare its own layout name and configure <varname>layout=</varname> in <filename>install.conf</filename> upon initial installation.</para>
<para><varname>KERNEL_INSTALL_INITRD_GENERATOR=...</varname> is set for plugins to select the initrd generator.
This should be configured as <varname>initrd_generator=</varname> in <filename>install.conf</filename>.
</para>
<para><varname>KERNEL_INSTALL_STAGING_AREA=...</varname> is set for plugins to a path to a directory.
Plugins may drop files in that directory, and they will be installed as part of the loader entry, based
on the file name and extension.</para>
<variablelist>
<varlistentry>
<term>bls</term>

View File

@ -121,19 +121,6 @@ int in_addr_is_localhost(int family, const union in_addr_union *u) {
return -EAFNOSUPPORT;
}
int in_addr_is_localhost_one(int family, const union in_addr_union *u) {
assert(u);
if (family == AF_INET)
/* 127.0.0.1 */
return be32toh(u->in.s_addr) == UINT32_C(0x7F000001);
if (family == AF_INET6)
return IN6_IS_ADDR_LOOPBACK(&u->in6); /* lgtm [cpp/potentially-dangerous-function] */
return -EAFNOSUPPORT;
}
bool in6_addr_is_ipv4_mapped_address(const struct in6_addr *a) {
return a->s6_addr32[0] == 0 &&
a->s6_addr32[1] == 0 &&

View File

@ -49,7 +49,6 @@ bool in6_addr_is_link_local_all_nodes(const struct in6_addr *a);
bool in4_addr_is_localhost(const struct in_addr *a);
int in_addr_is_localhost(int family, const union in_addr_union *u);
int in_addr_is_localhost_one(int family, const union in_addr_union *u);
bool in4_addr_is_local_multicast(const struct in_addr *a);
bool in4_addr_is_non_local(const struct in_addr *a);

View File

@ -68,8 +68,8 @@ bpf_o_unstripped_cmd += [
if bpftool_strip
bpf_o_cmd = [
bpftool,
'gen',
'object',
'g',
'o',
'@OUTPUT@',
'@INPUT@'
]
@ -85,7 +85,7 @@ endif
skel_h_cmd = [
bpftool,
'gen',
'skeleton',
'g',
's',
'@INPUT@'
]

View File

@ -4058,10 +4058,6 @@ static int exec_child(
assert(params);
assert(exit_status);
/* Explicitly test for CVE-2021-4034 inspired invocations */
assert(command->path);
assert(!strv_isempty(command->argv));
rename_process_from_path(command->path);
/* We reset exactly these signals, since they are the only ones we set to SIG_IGN in the main

View File

@ -18,8 +18,6 @@
# You should have received a copy of the GNU Lesser General Public License
# along with systemd; If not, see <http://www.gnu.org/licenses/>.
shopt -s nullglob
COMMAND="$1"
KERNEL_VERSION="$2"
ENTRY_DIR_ABS="$3"
@ -40,8 +38,6 @@ fi
case "$COMMAND" in
remove)
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \
echo "Removing $BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION*.conf"
exec rm -f \
"$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION.conf" \
"$BOOT_ROOT/loader/entries/$MACHINE_ID-$KERNEL_VERSION+"*".conf"
@ -82,33 +78,36 @@ else
fi
if ! [ -d "$ENTRY_DIR_ABS" ]; then
echo "Error: entry directory '$ENTRY_DIR_ABS' does not exist" >&2
exit 1
if [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ]; then
echo "+mkdir -v -p $ENTRY_DIR_ABS"
mkdir -v -p "$ENTRY_DIR_ABS"
else
mkdir -p "$ENTRY_DIR_ABS"
fi
fi
install -g root -o root -m 0644 "$KERNEL_IMAGE" "$ENTRY_DIR_ABS/linux" || {
echo "Error: could not copy '$KERNEL_IMAGE' to '$ENTRY_DIR_ABS/linux'." >&2
echo "Could not copy '$KERNEL_IMAGE' to '$ENTRY_DIR_ABS/linux'." >&2
exit 1
}
shift "$INITRD_OPTIONS_SHIFT"
# All files listed as arguments, and staged files called "initrd*" are installed as initrds.
for initrd in "$@" "${KERNEL_INSTALL_STAGING_AREA}"/initrd*; do
for initrd; do
[ -f "$initrd" ] || {
echo "Error: initrd '$initrd' not a file." >&2
echo "Initrd '$initrd' not a file." >&2
exit 1
}
initrd_basename="${initrd##*/}"
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "Installing $ENTRY_DIR_ABS/$initrd_basename"
install -g root -o root -m 0644 "$initrd" "$ENTRY_DIR_ABS/$initrd_basename" || {
echo "Error: could not copy '$initrd' to '$ENTRY_DIR_ABS/$initrd_basename'." >&2
echo "Could not copy '$initrd' to '$ENTRY_DIR_ABS/$initrd_basename'." >&2
exit 1
}
done
mkdir -p "${LOADER_ENTRY%/*}" || {
echo "Error: could not create loader entry directory '${LOADER_ENTRY%/*}'." >&2
echo "Could not create loader entry directory '${LOADER_ENTRY%/*}'." >&2
exit 1
}
@ -119,18 +118,14 @@ mkdir -p "${LOADER_ENTRY%/*}" || {
echo "machine-id $MACHINE_ID"
echo "options $BOOT_OPTIONS"
echo "linux $ENTRY_DIR/linux"
have_initrd=
for initrd in "${@}" "${KERNEL_INSTALL_STAGING_AREA}"/initrd*; do
for initrd; do
echo "initrd $ENTRY_DIR/${initrd##*/}"
have_initrd=yes
done
# Try "initrd", generated by dracut in its kernel-install hook, if no initrds were supplied
[ -z "$have_initrd" ] && [ -f "$ENTRY_DIR_ABS/initrd" ] && echo "initrd $ENTRY_DIR/initrd"
[ $# -eq 0 ] && [ -f "$ENTRY_DIR_ABS/initrd" ] && echo "initrd $ENTRY_DIR/initrd"
:
} >"$LOADER_ENTRY" || {
echo "Error: could not create loader entry '$LOADER_ENTRY'." >&2
echo "Could not create loader entry '$LOADER_ENTRY'." >&2
exit 1
}
exit 0

View File

@ -8,4 +8,3 @@
# See kernel-install(8) for details.
#layout=bls|other|...
#initrd_generator=dracut|...

View File

@ -73,16 +73,13 @@ else
fi
if [ $# -lt 1 ]; then
echo "Error: not enough arguments" >&2
echo "Not enough arguments" >&2
exit 1
fi
KERNEL_VERSION="$1"
shift
layout=
initrd_generator=
if [ -r "/etc/kernel/install.conf" ]; then
. /etc/kernel/install.conf
elif [ -r "/usr/lib/kernel/install.conf" ]; then
@ -126,22 +123,12 @@ if [ -z "$layout" ]; then
fi
fi
ENTRY_DIR_ABS="$BOOT_ROOT/$MACHINE_ID/$KERNEL_VERSION"
# Provide a directory where to store generated initrds
cleanup() {
[ -n "$KERNEL_INSTALL_STAGING_AREA" ] && rm -rf "$KERNEL_INSTALL_STAGING_AREA"
}
trap cleanup EXIT
KERNEL_INSTALL_STAGING_AREA="$(mktemp -d -t -p /tmp kernel-install.staging.XXXXXXX)"
export KERNEL_INSTALL_MACHINE_ID="$MACHINE_ID"
export KERNEL_INSTALL_BOOT_ROOT="$BOOT_ROOT"
export KERNEL_INSTALL_LAYOUT="$layout"
export KERNEL_INSTALL_INITRD_GENERATOR="$initrd_generator"
export KERNEL_INSTALL_STAGING_AREA
[ "$layout" = "bls" ]
MAKE_ENTRY_DIR_ABS=$?
@ -160,12 +147,12 @@ IFS="
case "$COMMAND" in
add)
if [ $# -lt 1 ]; then
echo "Error: command 'add' requires a kernel image" >&2
echo "Command 'add' requires a kernel image" >&2
exit 1
fi
if ! [ -f "$1" ]; then
echo "Error: kernel image argument $1 not a file" >&2
echo "Kernel image argument $1 not a file" >&2
exit 1
fi
@ -175,9 +162,9 @@ case "$COMMAND" in
# to serve as the indication to use or to not use the BLS
if [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ]; then
echo "+mkdir -v -p $ENTRY_DIR_ABS"
mkdir -v -p "$ENTRY_DIR_ABS" || exit 1
mkdir -v -p "$ENTRY_DIR_ABS"
else
mkdir -p "$ENTRY_DIR_ABS" || exit 1
mkdir -p "$ENTRY_DIR_ABS"
fi
fi
@ -206,7 +193,7 @@ case "$COMMAND" in
;;
*)
echo "Error: unknown command '$COMMAND'" >&2
echo "Unknown command '$COMMAND'" >&2
exit 1
;;
esac

View File

@ -17,42 +17,13 @@ ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
return 0;
}
static void add_lease(sd_dhcp_server *server, const struct in_addr *server_address, uint8_t i) {
static const uint8_t chaddr[] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
DHCPLease *lease;
assert(server);
assert_se(lease = new0(DHCPLease, 1));
lease->client_id.length = 2;
assert_se(lease->client_id.data = malloc(2));
lease->client_id.data[0] = 2;
lease->client_id.data[1] = i;
lease->address = htobe32(UINT32_C(10) << 24 | i);
lease->gateway = server_address->s_addr;
lease->expiration = UINT64_MAX;
lease->htype = ARPHRD_ETHER;
lease->hlen = ETH_ALEN;
memcpy(lease->chaddr, chaddr, ETH_ALEN);
assert_se(hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease) >= 0);
assert_se(hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease) >= 0);
lease->server = server;
}
static void add_static_lease(sd_dhcp_server *server, uint8_t i) {
uint8_t id[2] = { 2, i };
assert(server);
assert_se(sd_dhcp_server_set_static_lease(server,
&(struct in_addr) { .s_addr = htobe32(UINT32_C(10) << 24 | i)},
id, ELEMENTSOF(id)) >= 0);
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
_cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
struct in_addr address = { .s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))};
struct in_addr address = {.s_addr = htobe32(UINT32_C(10) << 24 | UINT32_C(1))};
static const uint8_t chaddr[] = {3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
_cleanup_free_ uint8_t *duped = NULL;
uint8_t *client_id;
DHCPLease *lease;
if (size < sizeof(DHCPMessage))
return 0;
@ -65,13 +36,24 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
assert_se(server->fd >= 0);
assert_se(sd_dhcp_server_configure_pool(server, &address, 24, 0, 0) >= 0);
/* add leases to the pool to expose additional code paths */
add_lease(server, &address, 2);
add_lease(server, &address, 3);
/* add static leases */
add_static_lease(server, 3);
add_static_lease(server, 4);
/* add a lease to the pool to expose additional code paths */
client_id = malloc(2);
assert_se(client_id);
client_id[0] = 2;
client_id[1] = 2;
lease = new0(DHCPLease, 1);
assert_se(lease);
lease->client_id.length = 2;
lease->client_id.data = client_id;
lease->address = htobe32(UINT32_C(10) << 24 | UINT32_C(2));
lease->gateway = htobe32(UINT32_C(10) << 24 | UINT32_C(1));
lease->expiration = UINT64_MAX;
lease->htype = ARPHRD_ETHER;
lease->hlen = ETH_ALEN;
memcpy(lease->chaddr, chaddr, ETH_ALEN);
assert_se(hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease) >= 0);
assert_se(hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease) >= 0);
lease->server = server;
(void) dhcp_server_handle_message(server, (DHCPMessage*) duped, size);

View File

@ -30,10 +30,19 @@ static DHCPLease *dhcp_lease_free(DHCPLease *lease) {
return NULL;
if (lease->server) {
hashmap_remove_value(lease->server->bound_leases_by_address, UINT32_TO_PTR(lease->address), lease);
hashmap_remove_value(lease->server->bound_leases_by_client_id, &lease->client_id, lease);
hashmap_remove_value(lease->server->static_leases_by_address, UINT32_TO_PTR(lease->address), lease);
hashmap_remove_value(lease->server->static_leases_by_client_id, &lease->client_id, lease);
DHCPLease *e;
e = hashmap_get(lease->server->bound_leases_by_client_id, &lease->client_id);
if (e == lease) {
hashmap_remove(lease->server->bound_leases_by_address, UINT32_TO_PTR(lease->address));
hashmap_remove(lease->server->bound_leases_by_client_id, &lease->client_id);
}
e = hashmap_get(lease->server->static_leases_by_client_id, &lease->client_id);
if (e == lease) {
hashmap_remove(lease->server->static_leases_by_address, UINT32_TO_PTR(lease->address));
hashmap_remove(lease->server->static_leases_by_client_id, &lease->client_id);
}
}
free(lease->client_id.data);
@ -125,7 +134,7 @@ int sd_dhcp_server_is_in_relay_mode(sd_dhcp_server *server) {
void client_id_hash_func(const DHCPClientId *id, struct siphash *state) {
assert(id);
assert(id->length > 0);
assert(id->length);
assert(id->data);
siphash24_compress(&id->length, sizeof(id->length), state);
@ -135,10 +144,8 @@ void client_id_hash_func(const DHCPClientId *id, struct siphash *state) {
int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b) {
int r;
assert(a->length > 0);
assert(a->data);
assert(b->length > 0);
assert(b->data);
assert(!a->length || a->data);
assert(!b->length || b->data);
r = CMP(a->length, b->length);
if (r != 0)
@ -158,6 +165,8 @@ DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
assert(server);
log_dhcp_server(server, "UNREF");
sd_dhcp_server_stop(server);
sd_event_unref(server->event);
@ -271,13 +280,9 @@ sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) {
}
int sd_dhcp_server_stop(sd_dhcp_server *server) {
bool running;
if (!server)
return 0;
running = sd_dhcp_server_is_running(server);
server->receive_message = sd_event_source_disable_unref(server->receive_message);
server->receive_broadcast = sd_event_source_disable_unref(server->receive_broadcast);
@ -285,7 +290,6 @@ int sd_dhcp_server_stop(sd_dhcp_server *server) {
server->fd = safe_close(server->fd);
server->fd_broadcast = safe_close(server->fd_broadcast);
if (running)
log_dhcp_server(server, "STOPPED");
return 0;
@ -307,7 +311,7 @@ static int dhcp_server_send_unicast_raw(
assert(server);
assert(server->ifindex > 0);
assert(server->address != 0);
assert(server->address);
assert(hlen > 0);
assert(chaddr);
assert(packet);
@ -420,7 +424,7 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
assert(server);
assert(req);
assert(req->max_optlen > 0);
assert(req->max_optlen);
assert(req->message);
assert(optoffset <= req->max_optlen);
assert(packet);
@ -468,12 +472,12 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
client, because the client may not have a correct network address
or subnet mask, and the client may not be answering ARP requests.
*/
if (req->message->giaddr != 0) {
if (req->message->giaddr) {
destination = req->message->giaddr;
destination_port = DHCP_PORT_SERVER;
if (type == DHCP_NAK)
packet->dhcp.flags = htobe16(0x8000);
} else if (req->message->ciaddr != 0 && type != DHCP_NAK)
} else if (req->message->ciaddr && type != DHCP_NAK)
destination = req->message->ciaddr;
bool l2_broadcast = requested_broadcast(req->message) || type == DHCP_NAK;
@ -481,22 +485,17 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
destination, destination_port, packet, optoffset, l2_broadcast);
}
static int server_message_init(
sd_dhcp_server *server,
DHCPPacket **ret,
uint8_t type,
size_t *ret_optoffset,
static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
uint8_t type, size_t *_optoffset,
DHCPRequest *req) {
_cleanup_free_ DHCPPacket *packet = NULL;
size_t optoffset = 0;
int r;
assert(server);
assert(ret);
assert(ret_optoffset);
assert(_optoffset);
assert(IN_SET(type, DHCP_OFFER, DHCP_ACK, DHCP_NAK));
assert(req);
packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
if (!packet)
@ -512,7 +511,7 @@ static int server_message_init(
packet->dhcp.flags = req->message->flags;
packet->dhcp.giaddr = req->message->giaddr;
*ret_optoffset = optoffset;
*_optoffset = optoffset;
*ret = TAKE_PTR(packet);
return 0;
@ -615,28 +614,16 @@ static int server_send_offer_or_ack(
return dhcp_server_send_packet(server, req, packet, type, offset);
}
static int server_send_nak_or_ignore(sd_dhcp_server *server, bool init_reboot, DHCPRequest *req) {
static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) {
_cleanup_free_ DHCPPacket *packet = NULL;
size_t offset;
int r;
/* When a request is refused, RFC 2131, section 4.3.2 mentioned we should send NAK when the
* client is in INITREBOOT. If the client is in other state, there is nothing mentioned in the
* RFC whether we should send NAK or not. Hence, let's silently ignore the request. */
if (!init_reboot)
return 0;
r = server_message_init(server, &packet, DHCP_NAK, &offset, req);
if (r < 0)
return log_dhcp_server_errno(server, r, "Failed to create NAK message: %m");
return r;
r = dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not send NAK message: %m");
log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid));
return DHCP_NAK;
return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset);
}
static int server_send_forcerenew(
@ -791,20 +778,17 @@ static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMes
return 0;
}
static bool address_is_in_pool(sd_dhcp_server *server, be32_t address) {
static int get_pool_offset(sd_dhcp_server *server, be32_t requested_ip) {
assert(server);
if (server->pool_size == 0)
return false;
if (!server->pool_size)
return -EINVAL;
if (be32toh(address) < (be32toh(server->subnet) | server->pool_offset) ||
be32toh(address) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size)))
return false;
if (be32toh(requested_ip) < (be32toh(server->subnet) | server->pool_offset) ||
be32toh(requested_ip) >= (be32toh(server->subnet) | (server->pool_offset + server->pool_size)))
return -ERANGE;
if (hashmap_contains(server->static_leases_by_address, UINT32_TO_PTR(address)))
return false;
return true;
return be32toh(requested_ip & ~server->netmask) - server->pool_offset;
}
static int append_agent_information_option(sd_dhcp_server *server, DHCPMessage *message, size_t opt_length, size_t size) {
@ -919,59 +903,6 @@ static int prepare_new_lease(
return 0;
}
static int server_ack_request(sd_dhcp_server *server, DHCPRequest *req, DHCPLease *existing_lease, be32_t address) {
usec_t time_now, expiration;
int r;
assert(server);
assert(req);
assert(address != 0);
r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
return r;
expiration = usec_add(req->lifetime * USEC_PER_SEC, time_now);
if (existing_lease) {
assert(existing_lease->server);
assert(existing_lease->address == address);
existing_lease->expiration = expiration;
} else {
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
r = prepare_new_lease(&lease, address, &req->client_id,
req->message->htype, req->message->hlen,
req->message->chaddr, req->message->giaddr, expiration);
if (r < 0)
return log_dhcp_server_errno(server, r, "Failed to create new lease: %m");
lease->server = server; /* This must be set just before hashmap_put(). */
r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
TAKE_PTR(lease);
}
r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not send ACK: %m");
log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid));
if (server->callback)
server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
return DHCP_ACK;
}
static int dhcp_server_cleanup_expired_leases(sd_dhcp_server *server) {
DHCPLease *lease;
usec_t time_now;
@ -1043,7 +974,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
log_dhcp_server(server, "DISCOVER (0x%x)", be32toh(req->message->xid));
if (server->pool_size == 0)
if (!server->pool_size)
/* no pool allocated */
return 0;
@ -1095,12 +1026,14 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
return 1;
case DHCP_REQUEST: {
DHCPLease *existing_lease_by_address;
be32_t address;
bool init_reboot = false;
int pool_offset;
/* see RFC 2131, section 4.3.2 */
if (req->server_id != 0) {
if (req->server_id) {
log_dhcp_server(server, "REQUEST (selecting) (0x%x)",
be32toh(req->message->xid));
@ -1109,22 +1042,22 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
/* client did not pick us */
return 0;
if (req->message->ciaddr != 0)
if (req->message->ciaddr)
/* this MUST be zero */
return 0;
if (req->requested_ip == 0)
if (!req->requested_ip)
/* this must be filled in with the yiaddr
from the chosen OFFER */
return 0;
address = req->requested_ip;
} else if (req->requested_ip != 0) {
} else if (req->requested_ip) {
log_dhcp_server(server, "REQUEST (init-reboot) (0x%x)",
be32toh(req->message->xid));
/* INIT-REBOOT */
if (req->message->ciaddr != 0)
if (req->message->ciaddr)
/* this MUST be zero */
return 0;
@ -1136,7 +1069,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
be32toh(req->message->xid));
/* REBINDING / RENEWING */
if (req->message->ciaddr == 0)
if (!req->message->ciaddr)
/* this MUST be filled in with clients IP address */
return 0;
@ -1147,27 +1080,110 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
if (address == server->address)
return 0;
if (static_lease) {
/* Found a static lease for the client ID. */
pool_offset = get_pool_offset(server, address);
existing_lease_by_address = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(address));
if (static_lease->address != address)
/* The client requested an address which is different from the static lease. Refuse. */
return server_send_nak_or_ignore(server, init_reboot, req);
/* verify that the requested address is from the pool, and either
owned by the current client or free */
if (static_lease && static_lease->address == address) {
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
usec_t time_now, expiration;
return server_ack_request(server, req, existing_lease, address);
r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
return r;
expiration = usec_add(req->lifetime * USEC_PER_SEC, time_now);
r = prepare_new_lease(&lease, static_lease->address, &req->client_id,
req->message->htype, req->message->hlen,
req->message->chaddr, req->message->giaddr, expiration);
if (r < 0)
return r;
r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
if (r < 0)
/* this only fails on critical errors */
return log_dhcp_server_errno(server, r, "Could not send ack: %m");
log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid));
dhcp_lease_free(hashmap_remove(server->bound_leases_by_client_id, &lease->client_id));
r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
lease->server = server;
TAKE_PTR(lease);
if (server->callback)
server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
return DHCP_ACK;
} else if (pool_offset >= 0 && existing_lease_by_address == existing_lease) {
_cleanup_(dhcp_lease_freep) DHCPLease *new_lease = NULL;
usec_t time_now, expiration;
DHCPLease *lease;
/* Note that in the above condition we accept the case that both leases are NULL. */
r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
return r;
expiration = usec_add(req->lifetime * USEC_PER_SEC, time_now);
if (!existing_lease) {
r = prepare_new_lease(&new_lease, address, &req->client_id,
req->message->htype, req->message->hlen,
req->message->chaddr, req->message->giaddr, expiration);
if (r < 0)
return r;
lease = new_lease;
} else {
existing_lease->expiration = expiration;
lease = existing_lease;
}
if (address_is_in_pool(server, address)) {
/* The requested address is in the pool. */
r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
if (r < 0)
/* this only fails on critical errors */
return log_dhcp_server_errno(server, r, "Could not send ack: %m");
if (existing_lease && existing_lease->address != address)
/* We previously assigned an address, but the client requested another one. Refuse. */
return server_send_nak_or_ignore(server, init_reboot, req);
log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid));
return server_ack_request(server, req, existing_lease, address);
r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
lease->server = server;
TAKE_PTR(new_lease);
if (server->callback)
server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
return DHCP_ACK;
} else if (init_reboot) {
r = server_send_nak(server, req);
if (r < 0)
/* this only fails on critical errors */
return log_dhcp_server_errno(server, r, "Could not send nak: %m");
log_dhcp_server(server, "NAK (0x%x)", be32toh(req->message->xid));
return DHCP_NAK;
}
return server_send_nak_or_ignore(server, init_reboot, req);
break;
}
case DHCP_RELEASE: {
@ -1560,7 +1576,6 @@ int sd_dhcp_server_set_static_lease(
assert_return(server, -EINVAL);
assert_return(client_id, -EINVAL);
assert_return(client_id_size > 0, -EINVAL);
assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
/* Static lease with an empty or omitted address is a valid entry,
@ -1573,10 +1588,13 @@ int sd_dhcp_server_set_static_lease(
.data = client_id,
};
dhcp_lease_free(hashmap_get(server->static_leases_by_client_id, &c));
dhcp_lease_free(hashmap_remove(server->static_leases_by_client_id, &c));
return 0;
}
if (hashmap_contains(server->static_leases_by_address, UINT32_TO_PTR(address->s_addr)))
return -EEXIST;
lease = new(DHCPLease, 1);
if (!lease)
return -ENOMEM;
@ -1584,13 +1602,13 @@ int sd_dhcp_server_set_static_lease(
*lease = (DHCPLease) {
.address = address->s_addr,
.client_id.length = client_id_size,
.gateway = 0,
.expiration = 0,
};
lease->client_id.data = memdup(client_id, client_id_size);
if (!lease->client_id.data)
return -ENOMEM;
lease->server = server; /* This must be set just before hashmap_put(). */
r = hashmap_ensure_put(&server->static_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease);
if (r < 0)
return r;
@ -1598,6 +1616,7 @@ int sd_dhcp_server_set_static_lease(
if (r < 0)
return r;
lease->server = server;
TAKE_PTR(lease);
return 0;
}

View File

@ -20,9 +20,8 @@ static void test_pool(struct in_addr *address, unsigned size, int ret) {
assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret);
}
static int test_basic(bool bind_to_interface) {
static int test_basic(sd_event *event, bool bind_to_interface) {
_cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
struct in_addr address_lo = {
.s_addr = htobe32(INADDR_LOOPBACK),
};
@ -31,10 +30,6 @@ static int test_basic(bool bind_to_interface) {
};
int r;
log_debug("/* %s(bind_to_interface=%s) */", __func__, yes_no(bind_to_interface));
assert_se(sd_event_new(&event) >= 0);
/* attach to loopback interface */
assert_se(sd_dhcp_server_new(&server, 1) >= 0);
assert_se(server);
@ -63,7 +58,7 @@ static int test_basic(bool bind_to_interface) {
r = sd_dhcp_server_start(server);
if (r == -EPERM)
return r;
return log_info_errno(r, "sd_dhcp_server_start failed: %m");
assert_se(r >= 0);
assert_se(sd_dhcp_server_start(server) >= 0);
@ -113,17 +108,9 @@ static void test_message_handler(void) {
struct in_addr address_lo = {
.s_addr = htobe32(INADDR_LOOPBACK),
};
struct in_addr static_lease_address = {
.s_addr = htobe32(INADDR_LOOPBACK + 42),
};
static uint8_t static_lease_client_id[7] = {0x01, 'A', 'B', 'C', 'D', 'E', 'G' };
log_debug("/* %s */", __func__);
assert_se(sd_dhcp_server_new(&server, 1) >= 0);
assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
assert_se(sd_dhcp_server_set_static_lease(server, &static_lease_address, static_lease_client_id,
ELEMENTSOF(static_lease_client_id)) >= 0);
assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
assert_se(sd_dhcp_server_start(server) >= 0);
@ -193,26 +180,6 @@ static void test_message_handler(void) {
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
/* request address reserved for static lease (unmatching client ID) */
test.option_client_id.id[6] = 'H';
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
/* request unmatching address */
test.option_client_id.id[6] = 'G';
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 41);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
/* request matching address */
test.option_client_id.id[6] = 'G';
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
/* try again */
test.option_client_id.id[6] = 'G';
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42);
assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
}
static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) {
@ -235,8 +202,6 @@ static void test_client_id_hash(void) {
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
};
log_debug("/* %s */", __func__);
a.data = (uint8_t*)strdup("abcd");
b.data = (uint8_t*)strdup("abcd");
@ -262,61 +227,24 @@ static void test_client_id_hash(void) {
free(b.data);
}
static void test_static_lease(void) {
_cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
log_debug("/* %s */", __func__);
assert_se(sd_dhcp_server_new(&server, 1) >= 0);
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 },
(uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)) >= 0);
/* Duplicated entry. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 },
(uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)) == -EEXIST);
/* Address is conflicted. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 },
(uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) == -EEXIST);
/* Client ID is conflicted. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020305 },
(uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)) == -EEXIST);
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020305 },
(uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0);
/* Remove the previous entry. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 },
(uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0);
/* Then, set a different address. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020306 },
(uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0);
/* Remove again. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 },
(uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0);
/* Try to remove non-existent entry. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 },
(uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)) >= 0);
/* Try to remove non-existent entry. */
assert_se(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 },
(uint8_t*) &(uint32_t) { 0x01020306 }, sizeof(uint32_t)) >= 0);
}
int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e;
int r;
test_setup_logging(LOG_DEBUG);
test_client_id_hash();
test_static_lease();
assert_se(sd_event_new(&e) >= 0);
r = test_basic(true);
if (r < 0)
return log_tests_skipped_errno(r, "cannot start dhcp server(bound to interface)");
r = test_basic(e, true);
if (r != 0)
return log_tests_skipped("cannot start dhcp server(bound to interface)");
r = test_basic(false);
if (r < 0)
return log_tests_skipped_errno(r, "cannot start dhcp server(non-bound to interface)");
r = test_basic(e, false);
if (r != 0)
return log_tests_skipped("cannot start dhcp server(non-bound to interface)");
test_message_handler();
test_client_id_hash();
return 0;
}

View File

@ -854,10 +854,6 @@ int link_drop_foreign_addresses(Link *link) {
if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6))
continue;
/* Do not remove localhost address (127.0.0.1 and ::1) */
if (link->flags & IFF_LOOPBACK && in_addr_is_localhost_one(address->family, &address->in_addr) > 0)
continue;
/* Ignore addresses we configured. */
if (address->source != NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
@ -895,21 +891,24 @@ int link_drop_foreign_addresses(Link *link) {
return r;
}
int link_drop_managed_addresses(Link *link) {
int link_drop_addresses(Link *link) {
Address *address;
int k, r = 0;
assert(link);
SET_FOREACH(address, link->addresses) {
/* Do not touch addresses managed by kernel or other tools. */
if (address->source == NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
/* Ignore addresses not assigned yet or already removing. */
if (!address_exists(address))
continue;
/* Do not drop IPv6LL addresses assigned by the kernel here. They will be dropped in
* link_drop_ipv6ll_addresses() if IPv6LL addressing is disabled. */
if (address->source == NETWORK_CONFIG_SOURCE_FOREIGN &&
address->family == AF_INET6 &&
in6_addr_is_link_local(&address->in_addr.in6))
continue;
k = address_remove(address);
if (k < 0 && r >= 0) {
r = k;

View File

@ -74,7 +74,7 @@ void address_set_broadcast(Address *a);
DEFINE_SECTION_CLEANUP_FUNCTIONS(Address, address_free);
int link_drop_managed_addresses(Link *link);
int link_drop_addresses(Link *link);
int link_drop_foreign_addresses(Link *link);
int link_drop_ipv6ll_addresses(Link *link);
void link_foreignize_addresses(Link *link);

View File

@ -430,8 +430,6 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) {
if (k < 0)
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
ndisc_flush(link);
k = sd_radv_stop(link->radv);
if (k < 0)
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
@ -894,6 +892,24 @@ static int link_new_bound_to_list(Link *link) {
return 0;
}
static int link_new_carrier_maps(Link *link) {
int r;
r = link_new_bound_by_list(link);
if (r < 0)
return r;
r = link_handle_bound_by_list(link);
if (r < 0)
return r;
r = link_new_bound_to_list(link);
if (r < 0)
return r;
return link_handle_bound_to_list(link);
}
static void link_free_bound_to_list(Link *link) {
bool updated = false;
Link *bound_to;
@ -930,6 +946,13 @@ static void link_free_bound_by_list(Link *link) {
link_dirty(link);
}
static void link_free_carrier_maps(Link *link) {
assert(link);
link_free_bound_to_list(link);
link_free_bound_by_list(link);
}
static int link_append_to_master(Link *link) {
Link *master;
int r;
@ -989,8 +1012,7 @@ static Link *link_drop(Link *link) {
link_drop_requests(link);
link_free_bound_to_list(link);
link_free_bound_by_list(link);
link_free_carrier_maps(link);
link_drop_from_master(link);
@ -1048,30 +1070,32 @@ static int link_drop_foreign_config(Link *link) {
return r;
}
static int link_drop_managed_config(Link *link) {
static int link_drop_config(Link *link) {
int k, r;
assert(link);
assert(link->manager);
r = link_drop_managed_routes(link);
r = link_drop_routes(link);
k = link_drop_managed_nexthops(link);
k = link_drop_nexthops(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_managed_addresses(link);
k = link_drop_addresses(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_managed_neighbors(link);
k = link_drop_neighbors(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_managed_routing_policy_rules(link);
k = link_drop_routing_policy_rules(link);
if (k < 0 && r >= 0)
r = k;
ndisc_flush(link);
return r;
}
@ -1095,10 +1119,6 @@ static int link_configure(Link *link) {
link_set_state(link, LINK_STATE_CONFIGURING);
r = link_new_bound_to_list(link);
if (r < 0)
return r;
r = link_configure_traffic_control(link);
if (r < 0)
return r;
@ -1273,28 +1293,17 @@ static int link_reconfigure_impl(Link *link, bool force) {
assert(link);
if (!IN_SET(link->state, LINK_STATE_INITIALIZED, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED))
return 0;
r = link_get_network(link, &network);
if (r < 0 && r != -ENOENT)
return r;
if (link->state != LINK_STATE_UNMANAGED && !network)
/* If link is in initialized state, then link->network is also NULL. */
force = true;
if (link->network == network && !force)
return 0;
if (network) {
if (link->state == LINK_STATE_INITIALIZED)
log_link_info(link, "Configuring with %s.", network->filename);
else
if (network)
log_link_info(link, "Reconfiguring with %s.", network->filename);
} else
log_link_full(link, link->state == LINK_STATE_INITIALIZED ? LOG_DEBUG : LOG_INFO,
"Unmanaging interface.");
else
log_link_info(link, "Unmanaging interface.");
/* Dropping old .network file */
r = link_stop_engines(link, false);
@ -1309,19 +1318,12 @@ static int link_reconfigure_impl(Link *link, bool force) {
* link_drop_foreign_config() in link_configure(). */
link_foreignize_config(link);
else {
/* Remove all managed configs. Note, foreign configs are removed in later by
* link_configure() -> link_drop_foreign_config() if the link is managed by us. */
r = link_drop_managed_config(link);
r = link_drop_config(link);
if (r < 0)
return r;
}
/* The bound_to map depends on .network file, hence it needs to be freed. But, do not free the
* bound_by map. Otherwise, if a link enters unmanaged state below, then its carrier state will
* not propagated to other interfaces anymore. Moreover, it is not necessary to recreate the
* map here, as it depends on .network files assigned to other links. */
link_free_bound_to_list(link);
link_free_carrier_maps(link);
link_free_engines(link);
link->network = network_unref(link->network);
@ -1335,6 +1337,10 @@ static int link_reconfigure_impl(Link *link, bool force) {
link_update_operstate(link, true);
link_dirty(link);
r = link_new_carrier_maps(link);
if (r < 0)
return r;
link_set_state(link, LINK_STATE_INITIALIZED);
link->activated = false;
@ -1434,9 +1440,11 @@ int link_reconfigure_after_sleep(Link *link) {
}
static int link_initialized_and_synced(Link *link) {
Network *network;
int r;
assert(link);
assert(link->ifname);
assert(link->manager);
if (link->manager->test_mode) {
@ -1445,7 +1453,7 @@ static int link_initialized_and_synced(Link *link) {
return 0;
}
/* This may get called either from the asynchronous netlink callback,
/* We may get called either from the asynchronous netlink callback,
* or directly from link_check_initialized() if running in a container. */
if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED))
return 0;
@ -1461,7 +1469,36 @@ static int link_initialized_and_synced(Link *link) {
if (r < 0)
return r;
return link_reconfigure_impl(link, /* force = */ false);
if (!link->network) {
r = link_get_network(link, &network);
if (r == -ENOENT) {
link_set_state(link, LINK_STATE_UNMANAGED);
return 0;
}
if (r < 0)
return r;
if (link->flags & IFF_LOOPBACK) {
if (network->link_local != ADDRESS_FAMILY_NO)
log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
if (network->dhcp != ADDRESS_FAMILY_NO)
log_link_debug(link, "Ignoring DHCP clients for loopback link");
if (network->dhcp_server)
log_link_debug(link, "Ignoring DHCP server for loopback link");
}
link->network = network_ref(network);
link_update_operstate(link, false);
link_dirty(link);
}
r = link_new_bound_to_list(link);
if (r < 0)
return r;
return link_configure(link);
}
static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@ -1669,7 +1706,7 @@ static int link_carrier_lost_impl(Link *link) {
if (r < 0)
ret = r;
r = link_drop_managed_config(link);
r = link_drop_config(link);
if (r < 0 && ret >= 0)
ret = r;

View File

@ -416,17 +416,13 @@ int link_drop_foreign_neighbors(Link *link) {
return r;
}
int link_drop_managed_neighbors(Link *link) {
int link_drop_neighbors(Link *link) {
Neighbor *neighbor;
int k, r = 0;
assert(link);
SET_FOREACH(neighbor, link->neighbors) {
/* Do not touch nexthops managed by kernel or other tools. */
if (neighbor->source == NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
/* Ignore neighbors not assigned yet or already removing. */
if (!neighbor_exists(neighbor))
continue;

View File

@ -34,7 +34,7 @@ int neighbor_compare_func(const Neighbor *a, const Neighbor *b);
void network_drop_invalid_neighbors(Network *network);
int link_drop_managed_neighbors(Link *link);
int link_drop_neighbors(Link *link);
int link_drop_foreign_neighbors(Link *link);
void link_foreignize_neighbors(Link *link);

View File

@ -613,8 +613,8 @@ static void manager_mark_nexthops(Manager *manager, bool foreign, const Link *ex
if (nexthop->protocol == RTPROT_KERNEL)
continue;
/* When 'foreign' is true, mark only foreign nexthops, and vice versa. */
if (foreign != (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN))
/* When 'foreign' is true, do not remove nexthops we configured. */
if (foreign && nexthop->source != NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
/* Ignore nexthops not assigned yet or already removed. */
@ -641,7 +641,7 @@ static void manager_mark_nexthops(Manager *manager, bool foreign, const Link *ex
}
}
static int manager_drop_marked_nexthops(Manager *manager) {
static int manager_drop_nexthops(Manager *manager) {
NextHop *nexthop;
int k, r = 0;
@ -704,14 +704,14 @@ int link_drop_foreign_nexthops(Link *link) {
manager_mark_nexthops(link->manager, /* foreign = */ true, NULL);
k = manager_drop_marked_nexthops(link->manager);
k = manager_drop_nexthops(link->manager);
if (k < 0 && r >= 0)
r = k;
return r;
}
int link_drop_managed_nexthops(Link *link) {
int link_drop_nexthops(Link *link) {
NextHop *nexthop;
int k, r = 0;
@ -723,10 +723,6 @@ int link_drop_managed_nexthops(Link *link) {
if (nexthop->protocol == RTPROT_KERNEL)
continue;
/* Do not touch addresses managed by kernel or other tools. */
if (nexthop->source == NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
/* Ignore nexthops not assigned yet or already removing. */
if (!nexthop_exists(nexthop))
continue;
@ -738,7 +734,7 @@ int link_drop_managed_nexthops(Link *link) {
manager_mark_nexthops(link->manager, /* foreign = */ false, link);
k = manager_drop_marked_nexthops(link->manager);
k = manager_drop_nexthops(link->manager);
if (k < 0 && r >= 0)
r = k;

View File

@ -44,7 +44,7 @@ int nexthop_compare_func(const NextHop *a, const NextHop *b);
void network_drop_invalid_nexthops(Network *network);
int link_drop_managed_nexthops(Link *link);
int link_drop_nexthops(Link *link);
int link_drop_foreign_nexthops(Link *link);
void link_foreignize_nexthops(Link *link);

View File

@ -788,8 +788,8 @@ static void manager_mark_routes(Manager *manager, bool foreign, const Link *exce
if (route->protocol == RTPROT_KERNEL)
continue;
/* When 'foreign' is true, mark only foreign routes, and vice versa. */
if (foreign != (route->source == NETWORK_CONFIG_SOURCE_FOREIGN))
/* When 'foreign' is true, do not remove routes we configured. */
if (foreign && route->source != NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
/* Do not touch dynamic routes. They will removed by dhcp_pd_prefix_lost() */
@ -834,7 +834,7 @@ static void manager_mark_routes(Manager *manager, bool foreign, const Link *exce
}
}
static int manager_drop_marked_routes(Manager *manager) {
static int manager_drop_routes(Manager *manager) {
Route *route;
int k, r = 0;
@ -955,14 +955,14 @@ int link_drop_foreign_routes(Link *link) {
manager_mark_routes(link->manager, /* foreign = */ true, NULL);
k = manager_drop_marked_routes(link->manager);
k = manager_drop_routes(link->manager);
if (k < 0 && r >= 0)
r = k;
return r;
}
int link_drop_managed_routes(Link *link) {
int link_drop_routes(Link *link) {
Route *route;
int k, r = 0;
@ -973,10 +973,6 @@ int link_drop_managed_routes(Link *link) {
if (route_by_kernel(route))
continue;
/* Do not touch routes managed by kernel or other tools. */
if (route->source == NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
if (!route_exists(route))
continue;
@ -987,7 +983,7 @@ int link_drop_managed_routes(Link *link) {
manager_mark_routes(link->manager, /* foreign = */ false, link);
k = manager_drop_marked_routes(link->manager);
k = manager_drop_routes(link->manager);
if (k < 0 && r >= 0)
r = k;

View File

@ -82,7 +82,7 @@ int route_remove(Route *route);
int route_get(Manager *manager, Link *link, const Route *in, Route **ret);
int link_drop_managed_routes(Link *link);
int link_drop_routes(Link *link);
int link_drop_foreign_routes(Link *link);
void link_foreignize_routes(Link *link);

View File

@ -653,8 +653,8 @@ static void manager_mark_routing_policy_rules(Manager *m, bool foreign, const Li
if (rule->protocol == RTPROT_KERNEL)
continue;
/* When 'foreign' is true, mark only foreign rules, and vice versa. */
if (foreign != (rule->source == NETWORK_CONFIG_SOURCE_FOREIGN))
/* When 'foreign' is true, do not remove rules we configured. */
if (foreign && rule->source != NETWORK_CONFIG_SOURCE_FOREIGN)
continue;
/* Ignore rules not assigned yet or already removing. */

View File

@ -71,7 +71,7 @@ int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const L
static inline int manager_drop_foreign_routing_policy_rules(Manager *m) {
return manager_drop_routing_policy_rules_internal(m, true, NULL);
}
static inline int link_drop_managed_routing_policy_rules(Link *link) {
static inline int link_drop_routing_policy_rules(Link *link) {
assert(link);
return manager_drop_routing_policy_rules_internal(link->manager, false, link);
}

View File

@ -110,7 +110,7 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
}
}
log_link_debug(l, "link is configured by networkd and online.");
log_link_debug(l, "link is confiured by networkd and online.");
return 1;
}

View File

@ -449,16 +449,7 @@ ExecCommandFlags exec_command_flags_from_string(const char *s) {
}
int fexecve_or_execve(int executable_fd, const char *executable, char *const argv[], char *const envp[]) {
/* Refuse invalid fds, regardless if fexecve() use is enabled or not */
if (executable_fd < 0)
return -EBADF;
/* Block any attempts on exploiting Linux' liberal argv[] handling, i.e. CVE-2021-4034 and suchlike */
if (isempty(executable) || strv_isempty(argv))
return -EINVAL;
#if ENABLE_FEXECVE
execveat(executable_fd, "", argv, envp, AT_EMPTY_PATH);
if (IN_SET(errno, ENOSYS, ENOENT) || ERRNO_IS_PRIVILEGE(errno))

View File

@ -3893,7 +3893,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
print(output)
self.assertRegex(output, 'NO-CARRIER')
self.assertNotRegex(output, '192.168.0.15/24')
self.assertRegex(output, '192.168.0.16/24') # foreign address is kept
self.assertNotRegex(output, '192.168.0.16/24')
print('### ip -6 route list table all dev bridge99')
output = check_output('ip -6 route list table all dev bridge99')