1
0
mirror of https://github.com/systemd/systemd synced 2026-03-17 02:24:48 +01:00

Compare commits

..

No commits in common. "38dd7673b352896ea7561e7e431ce0ebbe867ca6" and "997c2d5625c99ece6049539e0809804ca67940d6" have entirely different histories.

27 changed files with 110 additions and 747 deletions

View File

@ -241,7 +241,7 @@
<term><option>--make-machine-id-directory=yes|no|auto</option></term> <term><option>--make-machine-id-directory=yes|no|auto</option></term>
<listitem><para>Control creation and deletion of the top-level machine ID directory on the file <listitem><para>Control creation and deletion of the top-level machine ID directory on the file
system containing boot loader entries (i.e. beneath the file system returned by system containing boot loader entries (i.e. beneath the file system returned by
<option>--print-boot-path</option> above) during <option>install</option> and <command>--print-boot-path</command> above) during <option>install</option> and
<option>remove</option>, respectively. <literal>auto</literal> is equivalent to <option>remove</option>, respectively. <literal>auto</literal> is equivalent to
<literal>yes</literal> if <filename>/etc/machine-id</filename> resides on a filesystem other than <literal>yes</literal> if <filename>/etc/machine-id</filename> resides on a filesystem other than
tmpfs and <literal>no</literal> otherwise (in the latter case the machine ID is likely transient and tmpfs and <literal>no</literal> otherwise (in the latter case the machine ID is likely transient and

View File

@ -99,16 +99,12 @@
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details. The <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details. The
ID is cached internally. In future a different mechanism to determine the invocation ID may be added.</para> ID is cached internally. In future a different mechanism to determine the invocation ID may be added.</para>
<para>Note that <function>sd_id128_get_machine_app_specific()</function>, <para>Note that <function>sd_id128_get_machine_app_specific()</function>, <function>sd_id128_get_boot()</function>,
<function>sd_id128_get_boot()</function>, <function>sd_id128_get_boot_app_specific()</function>, and <function>sd_id128_get_boot_app_specific()</function>, and <function>sd_id128_get_invocation()</function> always
<function>sd_id128_get_invocation()</function> always return UUID v4 compatible IDs. return UUID v4 compatible IDs. <function>sd_id128_get_machine()</function> will also return a UUID v4-compatible
<function>sd_id128_get_machine()</function> will also return a UUID v4-compatible ID on new installations ID on new installations but might not on older. It is possible to convert the machine ID into a UUID v4-compatible
but might not on older. It is possible to convert the machine ID into a UUID v4-compatible one. For more one. For more information, see
information, see <citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>. It is
hence guaranteed that thes functions will never return the ID consisting of all zero or all one bits
(<constant>SD_ID128_NULL</constant>, <constant>SD_ID128_ALLF</constant>) — with the possible exception of
<function>sd_id128_get_machine()</function>, as mentioned.</para>
<para>For more information about the <literal>sd_id128_t</literal> <para>For more information about the <literal>sd_id128_t</literal>
type see type see

View File

@ -42,9 +42,8 @@
<filename>/dev/urandom</filename> kernel random number <filename>/dev/urandom</filename> kernel random number
generator.</para> generator.</para>
<para>Note that <function>sd_id128_randomize()</function> always returns a UUID v4-compatible ID. It is <para>Note that <function>sd_id128_randomize()</function> always
hence guaranteed that this function will never return the ID consisting of all zero or all one bits returns a UUID v4-compatible ID.</para>
(<constant>SD_ID128_NULL</constant>, <constant>SD_ID128_ALLF</constant>).</para>
<para>For more information about the <literal>sd_id128_t</literal> <para>For more information about the <literal>sd_id128_t</literal>
type, see type, see

View File

@ -2535,29 +2535,6 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
</variablelist> </variablelist>
</refsect1> </refsect1>
<refsect1>
<title>[DHCPServerStaticLease] Section Options</title>
<para>The <literal>[DHCPServerStaticLease]</literal> section configures a static DHCP lease to
assign a pre-set IPv4 address to a specific device based on its MAC address. This section can be
specified multiple times.</para>
<variablelist class='network-directives'>
<varlistentry>
<term><varname>MACAddress=</varname></term>
<listitem><para>The hardware address of a device which should be assigned IPv4 address
specified in <varname>Address=</varname>. This key is mandatory.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Address=</varname></term>
<listitem><para>IPv4 address that should be assigned to a device with a hardware address
specified in <varname>MACAddress=</varname>. This key is mandatory.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1> <refsect1>
<title>[IPv6SendRA] Section Options</title> <title>[IPv6SendRA] Section Options</title>
<para>The [IPv6SendRA] section contains settings for sending IPv6 Router Advertisements and whether <para>The [IPv6SendRA] section contains settings for sending IPv6 Router Advertisements and whether

View File

@ -375,15 +375,6 @@
the same command to finish.</para> the same command to finish.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--uuid</option></term>
<listitem>
<para>Trigger the synthetic device events, and associate a randomized UUID with each. These UUIDs
are printed to standard output, one line for each event. These UUIDs are included in the uevent
environment block (in the <literal>SYNTH_UUID=</literal> property) and may be used to track
delivery of the generated events.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--wait-daemon[=<replaceable>SECONDS</replaceable>]</option></term> <term><option>--wait-daemon[=<replaceable>SECONDS</replaceable>]</option></term>
<listitem> <listitem>

View File

@ -14,7 +14,7 @@ DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(string_hash_ops_free,
char, string_hash_func, string_compare_func, free); char, string_hash_func, string_compare_func, free);
DEFINE_HASH_OPS_FULL(string_hash_ops_free_free, DEFINE_HASH_OPS_FULL(string_hash_ops_free_free,
char, string_hash_func, string_compare_func, free, char, string_hash_func, string_compare_func, free,
void, free); char, free);
void path_hash_func(const char *q, struct siphash *state) { void path_hash_func(const char *q, struct siphash *state) {
size_t n; size_t n;
@ -57,9 +57,6 @@ void path_hash_func(const char *q, struct siphash *state) {
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare); DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(path_hash_ops_free, DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(path_hash_ops_free,
char, path_hash_func, path_compare, free); char, path_hash_func, path_compare, free);
DEFINE_HASH_OPS_FULL(path_hash_ops_free_free,
char, path_hash_func, path_compare, free,
void, free);
void trivial_hash_func(const void *p, struct siphash *state) { void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state); siphash24_compress(&p, sizeof(p), state);

View File

@ -82,7 +82,6 @@ extern const struct hash_ops string_hash_ops_free_free;
void path_hash_func(const char *p, struct siphash *state); void path_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops path_hash_ops; extern const struct hash_ops path_hash_ops;
extern const struct hash_ops path_hash_ops_free; extern const struct hash_ops path_hash_ops_free;
extern const struct hash_ops path_hash_ops_free_free;
/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings /* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings
* or suchlike. */ * or suchlike. */

View File

@ -68,7 +68,6 @@ struct sd_dhcp_server {
bool emit_router; bool emit_router;
Hashmap *leases_by_client_id; Hashmap *leases_by_client_id;
Hashmap *static_leases_by_client_id;
DHCPLease **bound_leases; DHCPLease **bound_leases;
DHCPLease invalid_lease; DHCPLease invalid_lease;

View File

@ -32,8 +32,6 @@ static DHCPLease *dhcp_lease_free(DHCPLease *lease) {
return mfree(lease); return mfree(lease);
} }
DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPLease*, dhcp_lease_free);
/* configures the server's address and subnet, and optionally the pool's size and offset into the subnet /* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
* the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address * the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
* moreover, the server's own address may be in the pool, and is in that case reserved in order not to * moreover, the server's own address may be in the pool, and is in that case reserved in order not to
@ -162,7 +160,6 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
free(server->servers[i].addr); free(server->servers[i].addr);
hashmap_free(server->leases_by_client_id); hashmap_free(server->leases_by_client_id);
hashmap_free(server->static_leases_by_client_id);
ordered_set_free(server->extra_options); ordered_set_free(server->extra_options);
ordered_set_free(server->vendor_options); ordered_set_free(server->vendor_options);
@ -204,9 +201,6 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
server->leases_by_client_id = hashmap_new(&dhcp_lease_hash_ops); server->leases_by_client_id = hashmap_new(&dhcp_lease_hash_ops);
if (!server->leases_by_client_id) if (!server->leases_by_client_id)
return -ENOMEM; return -ENOMEM;
server->static_leases_by_client_id = hashmap_new(&dhcp_lease_hash_ops);
if (!server->static_leases_by_client_id)
return -ENOMEM;
*ret = TAKE_PTR(server); *ret = TAKE_PTR(server);
@ -808,55 +802,13 @@ static int dhcp_server_relay_message(sd_dhcp_server *server, DHCPMessage *messag
return -EBADMSG; return -EBADMSG;
} }
static int prepare_new_lease(
DHCPLease **ret_lease,
be32_t address,
const DHCPClientId *client_id,
const uint8_t chaddr[static ETH_ALEN],
be32_t gateway,
usec_t expiration) {
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL;
lease = new(DHCPLease, 1);
if (!lease)
return -ENOMEM;
*lease = (DHCPLease) {
.address = address,
.client_id.length = client_id->length,
.gateway = gateway,
.expiration = expiration,
};
lease->client_id.data = memdup(client_id->data, client_id->length);
if (!lease->client_id.data)
return -ENOMEM;
memcpy(&lease->chaddr, chaddr, ETH_ALEN);
*ret_lease = TAKE_PTR(lease);
return 0;
}
static bool static_leases_have_address(sd_dhcp_server *server, be32_t address) {
DHCPLease *s;
assert(server);
HASHMAP_FOREACH(s, server->static_leases_by_client_id)
if (s->address == address)
return true;
return false;
}
#define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30) #define HASH_KEY SD_ID128_MAKE(0d,1d,fe,bd,f1,24,bd,b3,47,f1,dd,6e,73,21,93,30)
int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, size_t length) { int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
size_t length) {
_cleanup_(dhcp_request_freep) DHCPRequest *req = NULL; _cleanup_(dhcp_request_freep) DHCPRequest *req = NULL;
_cleanup_free_ char *error_message = NULL; _cleanup_free_ char *error_message = NULL;
DHCPLease *existing_lease, *static_lease; DHCPLease *existing_lease;
int type, r; int type, r;
assert(server); assert(server);
@ -880,8 +832,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
/* this only fails on critical errors */ /* this only fails on critical errors */
return r; return r;
existing_lease = hashmap_get(server->leases_by_client_id, &req->client_id); existing_lease = hashmap_get(server->leases_by_client_id,
static_lease = hashmap_get(server->static_leases_by_client_id, &req->client_id); &req->client_id);
switch(type) { switch(type) {
@ -889,16 +841,15 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
be32_t address = INADDR_ANY; be32_t address = INADDR_ANY;
unsigned i; unsigned i;
log_dhcp_server(server, "DISCOVER (0x%x)", be32toh(req->message->xid)); log_dhcp_server(server, "DISCOVER (0x%x)",
be32toh(req->message->xid));
if (!server->pool_size) if (!server->pool_size)
/* no pool allocated */ /* no pool allocated */
return 0; return 0;
/* for now pick a random free address from the pool */ /* for now pick a random free address from the pool */
if (static_lease) if (existing_lease)
address = static_lease->address;
else if (existing_lease)
address = existing_lease->address; address = existing_lease->address;
else { else {
struct siphash state; struct siphash state;
@ -916,12 +867,9 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
for (i = 0; i < server->pool_size; i++) { for (i = 0; i < server->pool_size; i++) {
if (!server->bound_leases[next_offer]) { if (!server->bound_leases[next_offer]) {
be32_t tmp = server->subnet | htobe32(server->pool_offset + next_offer); address = server->subnet | htobe32(server->pool_offset + next_offer);
if (!static_leases_have_address(server, tmp)) {
address = tmp;
break; break;
} }
}
next_offer = (next_offer + 1) % server->pool_size; next_offer = (next_offer + 1) % server->pool_size;
} }
@ -1000,81 +948,62 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
/* verify that the requested address is from the pool, and either /* verify that the requested address is from the pool, and either
owned by the current client or free */ owned by the current client or free */
if (pool_offset >= 0 && static_lease) { if (pool_offset >= 0 &&
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL, *old_lease = NULL; server->bound_leases[pool_offset] == existing_lease) {
usec_t time_now, expiration;
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->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));
server->bound_leases[pool_offset] = lease;
old_lease = hashmap_remove(server->leases_by_client_id, &lease->client_id);
r = hashmap_put(server->leases_by_client_id, &lease->client_id, lease);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
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 && server->bound_leases[pool_offset] == existing_lease) {
_cleanup_(dhcp_lease_freep) DHCPLease *new_lease = NULL;
usec_t time_now, expiration;
DHCPLease *lease; DHCPLease *lease;
usec_t time_now = 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) { if (!existing_lease) {
r = prepare_new_lease(&new_lease, address, &req->client_id, lease = new0(DHCPLease, 1);
req->message->chaddr, req->message->giaddr, expiration); if (!lease)
if (r < 0) return -ENOMEM;
return r; lease->address = address;
lease->client_id.data = memdup(req->client_id.data,
lease = new_lease; req->client_id.length);
} else { if (!lease->client_id.data) {
existing_lease->expiration = expiration; free(lease);
return -ENOMEM;
}
lease->client_id.length = req->client_id.length;
memcpy(&lease->chaddr, &req->message->chaddr,
ETH_ALEN);
lease->gateway = req->message->giaddr;
} else
lease = existing_lease; lease = existing_lease;
r = sd_event_now(server->event,
clock_boottime_or_monotonic(),
&time_now);
if (r < 0) {
if (!existing_lease)
dhcp_lease_free(lease);
return r;
} }
r = server_send_offer_or_ack(server, req, address, DHCP_ACK); lease->expiration = req->lifetime * USEC_PER_SEC + time_now;
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)); r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
if (r < 0) {
/* this only fails on critical errors */
log_dhcp_server_errno(server, r, "Could not send ack: %m");
if (!existing_lease)
dhcp_lease_free(lease);
return r;
} else {
log_dhcp_server(server, "ACK (0x%x)",
be32toh(req->message->xid));
server->bound_leases[pool_offset] = lease; server->bound_leases[pool_offset] = lease;
r = hashmap_put(server->leases_by_client_id, &lease->client_id, lease); hashmap_put(server->leases_by_client_id,
if (r < 0) &lease->client_id, lease);
return log_dhcp_server_errno(server, r, "Could not save lease: %m");
TAKE_PTR(new_lease);
if (server->callback) if (server->callback)
server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata); server->callback(server, SD_DHCP_SERVER_EVENT_LEASE_CHANGED, server->callback_userdata);
return DHCP_ACK; return DHCP_ACK;
}
} else if (init_reboot) { } else if (init_reboot) {
r = server_send_nak(server, req); r = server_send_nak(server, req);
@ -1468,61 +1397,3 @@ int sd_dhcp_server_set_relay_agent_information(
free_and_replace(server->agent_remote_id, remote_id_dup); free_and_replace(server->agent_remote_id, remote_id_dup);
return 0; return 0;
} }
int sd_dhcp_server_set_static_lease(
sd_dhcp_server *server,
const struct in_addr *address,
uint8_t *client_id,
size_t client_id_size) {
_cleanup_(dhcp_lease_freep) DHCPLease *lease = NULL, *old = NULL;
DHCPClientId c;
int r;
assert_return(server, -EINVAL);
assert_return(client_id, -EINVAL);
assert_return(client_id_size == ETH_ALEN + 1, -EINVAL);
assert_return(!sd_dhcp_server_is_running(server), -EBUSY);
/* Static lease with an empty or omitted address is a valid entry,
* the server removes any static lease with the specified mac address. */
if (!address || address->s_addr == 0) {
_cleanup_free_ void *data = NULL;
data = memdup(client_id, client_id_size);
if (!data)
return -ENOMEM;
c = (DHCPClientId) {
.length = client_id_size,
.data = data,
};
old = hashmap_remove(server->static_leases_by_client_id, &c);
return 0;
}
if (static_leases_have_address(server, address->s_addr))
return -EEXIST;
lease = new(DHCPLease, 1);
if (!lease)
return -ENOMEM;
*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;
r = hashmap_ensure_put(&server->static_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease);
if (r < 0)
return r;
TAKE_PTR(lease);
return 0;
}

View File

@ -757,6 +757,4 @@ global:
sd_device_monitor_filter_add_match_sysattr; sd_device_monitor_filter_add_match_sysattr;
sd_device_monitor_filter_add_match_parent; sd_device_monitor_filter_add_match_parent;
sd_device_get_usec_initialized; sd_device_get_usec_initialized;
sd_device_trigger_with_uuid;
sd_device_get_trigger_uuid;
} LIBSYSTEMD_248; } LIBSYSTEMD_248;

View File

@ -16,7 +16,6 @@
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "hashmap.h" #include "hashmap.h"
#include "id128-util.h"
#include "macro.h" #include "macro.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
@ -1870,34 +1869,6 @@ _public_ int sd_device_get_property_value(sd_device *device, const char *key, co
return 0; return 0;
} }
_public_ int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret) {
const char *s;
sd_id128_t id;
int r;
assert_return(device, -EINVAL);
/* Retrieves the UUID attached to a uevent when triggering it from userspace via
* sd_device_trigger_with_uuid() or an equivalent interface. Returns -ENOENT if the record is not
* caused by a synthetic event and -ENODATA if it was but no UUID was specified */
r = sd_device_get_property_value(device, "SYNTH_UUID", &s);
if (r < 0)
return r;
if (streq(s, "0")) /* SYNTH_UUID=0 is set whenever a device is triggered by userspace without specifying a UUID */
return -ENODATA;
r = sd_id128_from_string(s, &id);
if (r < 0)
return r;
if (ret)
*ret = id;
return 0;
}
static int device_cache_sysattr_value(sd_device *device, const char *key, char *value) { static int device_cache_sysattr_value(sd_device *device, const char *key, char *value) {
_cleanup_free_ char *new_key = NULL, *old_value = NULL; _cleanup_free_ char *new_key = NULL, *old_value = NULL;
int r; int r;
@ -2125,41 +2096,5 @@ _public_ int sd_device_trigger(sd_device *device, sd_device_action_t action) {
if (!s) if (!s)
return -EINVAL; return -EINVAL;
/* This uses the simple no-UUID interface of kernel < 4.13 */
return sd_device_set_sysattr_value(device, "uevent", s); return sd_device_set_sysattr_value(device, "uevent", s);
} }
_public_ int sd_device_trigger_with_uuid(
sd_device *device,
sd_device_action_t action,
sd_id128_t *ret_uuid) {
char buf[ID128_UUID_STRING_MAX];
const char *s, *j;
sd_id128_t u;
int r;
assert_return(device, -EINVAL);
/* If noone wants to know the UUID, use the simple interface from pre-4.13 times */
if (!ret_uuid)
return sd_device_trigger(device, action);
s = device_action_to_string(action);
if (!s)
return -EINVAL;
r = sd_id128_randomize(&u);
if (r < 0)
return r;
id128_to_uuid_string(u, buf);
j = strjoina(s, " ", buf);
r = sd_device_set_sysattr_value(device, "uevent", j);
if (r < 0)
return r;
*ret_uuid = u;
return 0;
}

View File

@ -69,8 +69,6 @@ sources = files('''
networkd-dhcp-common.h networkd-dhcp-common.h
networkd-dhcp-server-bus.c networkd-dhcp-server-bus.c
networkd-dhcp-server-bus.h networkd-dhcp-server-bus.h
networkd-dhcp-server-static-lease.c
networkd-dhcp-server-static-lease.h
networkd-dhcp-server.c networkd-dhcp-server.c
networkd-dhcp-server.h networkd-dhcp-server.h
networkd-dhcp4.c networkd-dhcp4.c

View File

@ -1,212 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h"
#include "ether-addr-util.h"
#include "hashmap.h"
#include "networkd-dhcp-server-static-lease.h"
#include "networkd-network.h"
#include "networkd-util.h"
DEFINE_NETWORK_SECTION_FUNCTIONS(DHCPStaticLease, dhcp_static_lease_free);
DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *static_lease) {
if (!static_lease)
return NULL;
if (static_lease->network && static_lease->section)
hashmap_remove(static_lease->network->dhcp_static_leases_by_section, static_lease->section);
network_config_section_free(static_lease->section);
free(static_lease->client_id);
return mfree(static_lease);
}
static int dhcp_static_lease_new(DHCPStaticLease **ret) {
DHCPStaticLease *p;
assert(ret);
p = new0(DHCPStaticLease, 1);
if (!p)
return -ENOMEM;
*ret = TAKE_PTR(p);
return 0;
}
static int lease_new_static(Network *network, const char *filename, unsigned section_line, DHCPStaticLease **ret) {
_cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
_cleanup_(dhcp_static_lease_freep) DHCPStaticLease *static_lease = NULL;
int r;
assert(network);
assert(filename);
assert(section_line > 0);
assert(ret);
r = network_config_section_new(filename, section_line, &n);
if (r < 0)
return r;
static_lease = hashmap_get(network->dhcp_static_leases_by_section, n);
if (static_lease) {
*ret = TAKE_PTR(static_lease);
return 0;
}
r = dhcp_static_lease_new(&static_lease);
if (r < 0)
return r;
static_lease->network = network;
static_lease->section = TAKE_PTR(n);
r = hashmap_ensure_put(&network->dhcp_static_leases_by_section, &network_config_hash_ops, static_lease->section, static_lease);
if (r < 0)
return r;
*ret = TAKE_PTR(static_lease);
return 0;
}
static int static_lease_verify(DHCPStaticLease *static_lease) {
if (section_is_invalid(static_lease->section))
return -EINVAL;
if (in4_addr_is_null(&static_lease->address))
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: DHCP static lease without Address= field configured. "
"Ignoring [DHCPServerStaticLease] section from line %u.",
static_lease->section->filename, static_lease->section->line);
/* TODO: check that the address is in the pool. */
if (static_lease->client_id_size == 0 || !static_lease->client_id)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"%s: DHCP static lease without MACAddress= field configured. "
"Ignoring [DHCPServerStaticLease] section from line %u.",
static_lease->section->filename, static_lease->section->line);
assert(static_lease->client_id_size == ETH_ALEN + 1);
return 0;
}
void network_drop_invalid_static_leases(Network *network) {
DHCPStaticLease *static_lease;
assert(network);
HASHMAP_FOREACH(static_lease, network->dhcp_static_leases_by_section)
if (static_lease_verify(static_lease) < 0)
dhcp_static_lease_free(static_lease);
}
int config_parse_dhcp_static_lease_address(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
_cleanup_(dhcp_static_lease_free_or_set_invalidp) DHCPStaticLease *lease = NULL;
Network *network = userdata;
union in_addr_union addr;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(network);
r = lease_new_static(network, filename, section_line, &lease);
if (r < 0)
return log_oom();
if (isempty(rvalue)) {
lease->address.s_addr = 0;
TAKE_PTR(lease);
return 0;
}
r = in_addr_from_string(AF_INET, rvalue, &addr);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse IPv4 address for DHCPv4 static lease, ignoring assignment: %s", rvalue);
return 0;
}
if (in4_addr_is_null(&addr.in)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"IPv4 address for DHCPv4 static lease cannot be the ANY address, ignoring assignment: %s", rvalue);
return 0;
}
lease->address = addr.in;
TAKE_PTR(lease);
return 0;
}
int config_parse_dhcp_static_lease_hwaddr(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
_cleanup_(dhcp_static_lease_free_or_set_invalidp) DHCPStaticLease *lease = NULL;
Network *network = userdata;
struct ether_addr hwaddr;
uint8_t *c;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(network);
r = lease_new_static(network, filename, section_line, &lease);
if (r < 0)
return log_oom();
if (isempty(rvalue)) {
lease->client_id = mfree(lease->client_id);
lease->client_id_size = 0;
return 0;
}
r = ether_addr_from_string(rvalue, &hwaddr);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse MAC address for DHCPv4 static lease, ignoring assignment: %s", rvalue);
return 0;
}
if (ether_addr_is_null(&hwaddr) || (hwaddr.ether_addr_octet[0] & 0x01)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"MAC address for DHCPv4 static lease cannot be null or multicast, ignoring assignment: %s", rvalue);
return 0;
}
c = new(uint8_t, ETH_ALEN + 1);
if (!c)
return log_oom();
/* set client id type to 1: Ethernet Link-Layer (RFC 2132) */
c[0] = 0x01;
memcpy(c + 1, &hwaddr, ETH_ALEN);
free_and_replace(lease->client_id, c);
lease->client_id_size = ETH_ALEN + 1;
TAKE_PTR(lease);
return 0;
}

View File

@ -1,26 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <inttypes.h>
#include "conf-parser.h"
#include "in-addr-util.h"
typedef struct Network Network;
typedef struct NetworkConfigSection NetworkConfigSection;
typedef struct DHCPStaticLease {
Network *network;
NetworkConfigSection *section;
struct in_addr address;
uint8_t *client_id;
size_t client_id_size;
} DHCPStaticLease;
DHCPStaticLease *dhcp_static_lease_free(DHCPStaticLease *lease);
void network_drop_invalid_static_leases(Network *network);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_static_lease_address);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_static_lease_hwaddr);

View File

@ -9,9 +9,8 @@
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "networkd-address.h" #include "networkd-address.h"
#include "networkd-dhcp-server-bus.h"
#include "networkd-dhcp-server-static-lease.h"
#include "networkd-dhcp-server.h" #include "networkd-dhcp-server.h"
#include "networkd-dhcp-server-bus.h"
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-network.h" #include "networkd-network.h"
@ -292,7 +291,6 @@ static int dhcp4_server_set_dns_from_resolve_conf(Link *link) {
int dhcp4_server_configure(Link *link) { int dhcp4_server_configure(Link *link) {
bool acquired_uplink = false; bool acquired_uplink = false;
sd_dhcp_option *p; sd_dhcp_option *p;
DHCPStaticLease *static_lease;
Link *uplink = NULL; Link *uplink = NULL;
Address *address; Address *address;
bool bind_to_interface; bool bind_to_interface;
@ -441,12 +439,6 @@ int dhcp4_server_configure(Link *link) {
return log_link_error_errno(link, r, "Failed to set DHCPv4 option: %m"); return log_link_error_errno(link, r, "Failed to set DHCPv4 option: %m");
} }
HASHMAP_FOREACH(static_lease, link->network->dhcp_static_leases_by_section) {
r = sd_dhcp_server_set_static_lease(link->dhcp_server, &static_lease->address, static_lease->client_id, static_lease->client_id_size);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv4 static lease for DHCP server: %m");
}
if (!sd_dhcp_server_is_running(link->dhcp_server)) { if (!sd_dhcp_server_is_running(link->dhcp_server)) {
r = sd_dhcp_server_start(link->dhcp_server); r = sd_dhcp_server_start(link->dhcp_server);
if (r < 0) if (r < 0)

View File

@ -23,6 +23,7 @@
#define NDISC_DNSSL_MAX 64U #define NDISC_DNSSL_MAX 64U
#define NDISC_RDNSS_MAX 64U #define NDISC_RDNSS_MAX 64U
#define NDISC_PREFIX_LFT_MIN 7200U
#define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3 #define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
@ -754,7 +755,7 @@ static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address,
} }
static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
uint32_t lifetime_valid, lifetime_preferred; uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
_cleanup_set_free_free_ Set *addresses = NULL; _cleanup_set_free_free_ Set *addresses = NULL;
struct in6_addr addr, *a; struct in6_addr addr, *a;
unsigned prefixlen; unsigned prefixlen;
@ -776,11 +777,6 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m"); return log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
if (lifetime_valid == 0) {
log_link_debug(link, "Ignoring prefix as its valid lifetime is zero.");
return 0;
}
r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred); r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m"); return log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
@ -799,29 +795,35 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
SET_FOREACH(a, addresses) { SET_FOREACH(a, addresses) {
_cleanup_(address_freep) Address *address = NULL; _cleanup_(address_freep) Address *address = NULL;
Address *e; Address *existing_address;
r = address_new(&address); r = address_new(&address);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
address->family = AF_INET6; address->family = AF_INET6;
address->in_addr.in6 = *a;
address->prefixlen = prefixlen; address->prefixlen = prefixlen;
address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
address->cinfo.ifa_valid = lifetime_valid;
address->cinfo.ifa_prefered = lifetime_preferred; address->cinfo.ifa_prefered = lifetime_preferred;
address->in_addr.in6 = *a;
/* See RFC4862, section 5.5.3.e. But the following logic is deviated from RFC4862 by /* see RFC4862 section 5.5.3.e */
* honoring all valid lifetimes to improve the reaction of SLAAC to renumbering events. r = address_get(link, address, &existing_address);
* See draft-ietf-6man-slaac-renum-02, section 4.2. */
r = address_get(link, address, &e);
if (r > 0) { if (r > 0) {
/* If the address is already assigned, but not valid anymore, then refuse to lifetime_remaining = existing_address->cinfo.tstamp / 100 + existing_address->cinfo.ifa_valid - time_now / USEC_PER_SEC;
* update the address. */ if (lifetime_valid > NDISC_PREFIX_LFT_MIN || lifetime_valid > lifetime_remaining)
if (e->cinfo.tstamp / 100 + e->cinfo.ifa_valid < time_now / USEC_PER_SEC) address->cinfo.ifa_valid = lifetime_valid;
else if (lifetime_remaining <= NDISC_PREFIX_LFT_MIN)
address->cinfo.ifa_valid = lifetime_remaining;
else
address->cinfo.ifa_valid = NDISC_PREFIX_LFT_MIN;
} else if (lifetime_valid > 0)
address->cinfo.ifa_valid = lifetime_valid;
else
continue; /* see RFC4862 section 5.5.3.d */
if (address->cinfo.ifa_valid == 0)
continue; continue;
}
r = ndisc_request_address(TAKE_PTR(address), link, rt); r = ndisc_request_address(TAKE_PTR(address), link, rt);
if (r < 0) if (r < 0)
@ -888,14 +890,14 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
r = sd_ndisc_router_route_get_lifetime(rt, &lifetime); r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get route lifetime from RA: %m"); return log_link_error_errno(link, r, "Failed to get gateway lifetime from RA: %m");
if (lifetime == 0) if (lifetime == 0)
return 0; return 0;
r = sd_ndisc_router_route_get_address(rt, &dst); r = sd_ndisc_router_route_get_address(rt, &dst);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get route destination address: %m"); return log_link_error_errno(link, r, "Failed to get route address: %m");
if ((!set_isempty(link->network->ndisc_allow_listed_route_prefix) && if ((!set_isempty(link->network->ndisc_allow_listed_route_prefix) &&
!set_contains(link->network->ndisc_allow_listed_route_prefix, &dst)) || !set_contains(link->network->ndisc_allow_listed_route_prefix, &dst)) ||

View File

@ -12,7 +12,6 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "networkd-bridge-fdb.h" #include "networkd-bridge-fdb.h"
#include "networkd-can.h" #include "networkd-can.h"
#include "networkd-dhcp-common.h" #include "networkd-dhcp-common.h"
#include "networkd-dhcp-server-static-lease.h"
#include "networkd-dhcp-server.h" #include "networkd-dhcp-server.h"
#include "networkd-dhcp4.h" #include "networkd-dhcp4.h"
#include "networkd-dhcp6.h" #include "networkd-dhcp6.h"
@ -289,8 +288,6 @@ DHCPServer.PoolSize, config_parse_uint32,
DHCPServer.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_vendor_options) DHCPServer.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_vendor_options)
DHCPServer.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_options) DHCPServer.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_options)
DHCPServer.BindToInterface, config_parse_bool, 0, offsetof(Network, dhcp_server_bind_to_interface) DHCPServer.BindToInterface, config_parse_bool, 0, offsetof(Network, dhcp_server_bind_to_interface)
DHCPServerStaticLease.Address, config_parse_dhcp_static_lease_address, 0, 0
DHCPServerStaticLease.MACAddress, config_parse_dhcp_static_lease_hwaddr, 0, 0
Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost) Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost)
Bridge.UseBPDU, config_parse_tristate, 0, offsetof(Network, use_bpdu) Bridge.UseBPDU, config_parse_tristate, 0, offsetof(Network, use_bpdu)
Bridge.HairPin, config_parse_tristate, 0, offsetof(Network, hairpin) Bridge.HairPin, config_parse_tristate, 0, offsetof(Network, hairpin)

View File

@ -17,7 +17,6 @@
#include "networkd-address.h" #include "networkd-address.h"
#include "networkd-bridge-fdb.h" #include "networkd-bridge-fdb.h"
#include "networkd-dhcp-common.h" #include "networkd-dhcp-common.h"
#include "networkd-dhcp-server-static-lease.h"
#include "networkd-dhcp-server.h" #include "networkd-dhcp-server.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-mdb.h" #include "networkd-mdb.h"
@ -242,7 +241,6 @@ int network_verify(Network *network) {
network_drop_invalid_routing_policy_rules(network); network_drop_invalid_routing_policy_rules(network);
network_drop_invalid_traffic_control(network); network_drop_invalid_traffic_control(network);
network_drop_invalid_sr_iov(network); network_drop_invalid_sr_iov(network);
network_drop_invalid_static_leases(network);
network_adjust_dhcp_server(network); network_adjust_dhcp_server(network);
@ -416,7 +414,6 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
"DHCPv6\0" "DHCPv6\0"
"DHCPv6PrefixDelegation\0" "DHCPv6PrefixDelegation\0"
"DHCPServer\0" "DHCPServer\0"
"DHCPServerStaticLease\0"
"IPv6AcceptRA\0" "IPv6AcceptRA\0"
"IPv6NDPProxyAddress\0" "IPv6NDPProxyAddress\0"
"Bridge\0" "Bridge\0"
@ -610,7 +607,6 @@ static Network *network_free(Network *network) {
hashmap_free_with_destructor(network->prefixes_by_section, prefix_free); hashmap_free_with_destructor(network->prefixes_by_section, prefix_free);
hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free); hashmap_free_with_destructor(network->route_prefixes_by_section, route_prefix_free);
hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free); hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free); ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free); ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);

View File

@ -315,7 +315,6 @@ struct Network {
Hashmap *prefixes_by_section; Hashmap *prefixes_by_section;
Hashmap *route_prefixes_by_section; Hashmap *route_prefixes_by_section;
Hashmap *rules_by_section; Hashmap *rules_by_section;
Hashmap *dhcp_static_leases_by_section;
OrderedHashmap *tc_by_section; OrderedHashmap *tc_by_section;
OrderedHashmap *sr_iov_by_section; OrderedHashmap *sr_iov_by_section;

View File

@ -24,7 +24,6 @@
#include <sys/types.h> #include <sys/types.h>
#include "sd-event.h" #include "sd-event.h"
#include "sd-id128.h"
#include "_sd-common.h" #include "_sd-common.h"
@ -97,13 +96,11 @@ const char *sd_device_get_sysattr_next(sd_device *device);
int sd_device_has_tag(sd_device *device, const char *tag); int sd_device_has_tag(sd_device *device, const char *tag);
int sd_device_has_current_tag(sd_device *device, const char *tag); int sd_device_has_current_tag(sd_device *device, const char *tag);
int sd_device_get_property_value(sd_device *device, const char *key, const char **value); int sd_device_get_property_value(sd_device *device, const char *key, const char **value);
int sd_device_get_trigger_uuid(sd_device *device, sd_id128_t *ret);
int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value); int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value);
int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *value); int sd_device_set_sysattr_value(sd_device *device, const char *sysattr, const char *value);
int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) _sd_printf_(3, 4); int sd_device_set_sysattr_valuef(sd_device *device, const char *sysattr, const char *format, ...) _sd_printf_(3, 4);
int sd_device_trigger(sd_device *device, sd_device_action_t action); int sd_device_trigger(sd_device *device, sd_device_action_t action);
int sd_device_trigger_with_uuid(sd_device *device, sd_device_action_t action, sd_id128_t *ret_uuid);
/* device enumerator */ /* device enumerator */

View File

@ -77,7 +77,6 @@ int sd_dhcp_server_set_smtp(sd_dhcp_server *server, const struct in_addr smtp[],
int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v); int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v);
int sd_dhcp_server_add_vendor_option(sd_dhcp_server *server, sd_dhcp_option *v); int sd_dhcp_server_add_vendor_option(sd_dhcp_server *server, sd_dhcp_option *v);
int sd_dhcp_server_set_static_lease(sd_dhcp_server *server, const struct in_addr *address, uint8_t *client_id, size_t client_id_size);
int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t); int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t);
int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t); int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);

View File

@ -24,14 +24,8 @@
static bool arg_verbose = false; static bool arg_verbose = false;
static bool arg_dry_run = false; static bool arg_dry_run = false;
static bool arg_quiet = false; static bool arg_quiet = false;
static bool arg_uuid = false;
static int exec_list( static int exec_list(sd_device_enumerator *e, sd_device_action_t action, Set **settle_set) {
sd_device_enumerator *e,
sd_device_action_t action,
Hashmap *settle_hashmap) {
bool skip_uuid_logic = false;
const char *action_str; const char *action_str;
sd_device *d; sd_device *d;
int r, ret = 0; int r, ret = 0;
@ -39,33 +33,18 @@ static int exec_list(
action_str = device_action_to_string(action); action_str = device_action_to_string(action);
FOREACH_DEVICE_AND_SUBSYSTEM(e, d) { FOREACH_DEVICE_AND_SUBSYSTEM(e, d) {
sd_id128_t id = SD_ID128_NULL;
const char *syspath; const char *syspath;
r = sd_device_get_syspath(d, &syspath); if (sd_device_get_syspath(d, &syspath) < 0)
if (r < 0) {
log_debug_errno(r, "Failed to get syspath of enumerated devices, ignoring: %m");
continue; continue;
}
if (arg_verbose) if (arg_verbose)
printf("%s\n", syspath); printf("%s\n", strna(syspath));
if (arg_dry_run) if (arg_dry_run)
continue; continue;
/* Use the UUID mode if the user explicitly asked for it, or if --settle has been specified,
* so that we can recognize our own uevent. */
r = sd_device_trigger_with_uuid(d, action, (arg_uuid || settle_hashmap) && !skip_uuid_logic ? &id : NULL);
if (r == -EINVAL && !arg_uuid && settle_hashmap && !skip_uuid_logic) {
/* If we specified a UUID because of the settling logic, and we got EINVAL this might
* be caused by an old kernel which doesn't know the UUID logic (pre-4.13). Let's try
* if it works without the UUID logic then. */
r = sd_device_trigger(d, action); r = sd_device_trigger(d, action);
if (r != -EINVAL)
skip_uuid_logic = true; /* dropping the uuid stuff changed the return code,
* hence don't bother next time */
}
if (r < 0) { if (r < 0) {
/* ENOENT may be returned when a device does not have /uevent or is already /* ENOENT may be returned when a device does not have /uevent or is already
* removed. Hence, this is logged at debug level and ignored. * removed. Hence, this is logged at debug level and ignored.
@ -107,28 +86,10 @@ static int exec_list(
continue; continue;
} }
/* If the user asked for it, write event UUID to stdout */ if (settle_set) {
if (arg_uuid) r = set_put_strdup(settle_set, syspath);
printf(SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id));
if (settle_hashmap) {
_cleanup_free_ sd_id128_t *mid = NULL;
_cleanup_free_ char *sp = NULL;
sp = strdup(syspath);
if (!sp)
return log_oom();
mid = newdup(sd_id128_t, &id, 1);
if (!d)
return log_oom();
r = hashmap_put(settle_hashmap, sp, mid);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
TAKE_PTR(sp);
TAKE_PTR(mid);
} }
} }
@ -136,51 +97,24 @@ static int exec_list(
} }
static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *userdata) { static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *userdata) {
Hashmap *settle_hashmap = userdata; _cleanup_free_ char *val = NULL;
sd_id128_t *settle_id; Set *settle_set = userdata;
const char *syspath; const char *syspath;
char *k;
int r;
assert(dev); assert(dev);
assert(settle_hashmap); assert(settle_set);
r = sd_device_get_syspath(dev, &syspath); if (sd_device_get_syspath(dev, &syspath) < 0)
if (r < 0) {
log_debug_errno(r, "Failed to get syspath of device event, ignoring: %m");
return 0; return 0;
}
settle_id = hashmap_get2(settle_hashmap, syspath, (void**) &k);
if (!settle_id) {
log_debug("Got uevent for unexpected device '%s', ignoring.", syspath);
return 0;
}
if (!sd_id128_is_null(*settle_id)) { /* If this is SD_ID128_NULL then we are on pre-4.13 and have no UUID to check, hence don't */
sd_id128_t event_id;
r = sd_device_get_trigger_uuid(dev, &event_id);
if (r < 0) {
log_debug_errno(r, "Got uevent without synthetic UUID for device '%s', ignoring: %m", syspath);
return 0;
}
if (!sd_id128_equal(event_id, *settle_id)) {
log_debug("Got uevent not matching expected UUID for device '%s', ignoring.", syspath);
return 0;
}
}
if (arg_verbose) if (arg_verbose)
printf("settle %s\n", syspath); printf("settle %s\n", syspath);
if (arg_uuid) val = set_remove(settle_set, syspath);
printf("settle " SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(*settle_id)); if (!val)
log_debug("Got epoll event on syspath %s not present in syspath set", syspath);
free(hashmap_remove(settle_hashmap, syspath)); if (set_isempty(settle_set))
free(k);
if (hashmap_isempty(settle_hashmap))
return sd_event_exit(sd_device_monitor_get_event(m), 0); return sd_event_exit(sd_device_monitor_get_event(m), 0);
return 0; return 0;
@ -228,8 +162,7 @@ static int help(void) {
" -b --parent-match=NAME Trigger devices with that parent device\n" " -b --parent-match=NAME Trigger devices with that parent device\n"
" -w --settle Wait for the triggered events to complete\n" " -w --settle Wait for the triggered events to complete\n"
" --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n" " --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n"
" before triggering uevents\n" " before triggering uevents\n",
" --uuid Print synthetic uevent UUID\n",
program_invocation_short_name); program_invocation_short_name);
return 0; return 0;
@ -239,7 +172,6 @@ int trigger_main(int argc, char *argv[], void *userdata) {
enum { enum {
ARG_NAME = 0x100, ARG_NAME = 0x100,
ARG_PING, ARG_PING,
ARG_UUID,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -261,7 +193,6 @@ int trigger_main(int argc, char *argv[], void *userdata) {
{ "wait-daemon", optional_argument, NULL, ARG_PING }, { "wait-daemon", optional_argument, NULL, ARG_PING },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "uuid", no_argument, NULL, ARG_UUID },
{} {}
}; };
enum { enum {
@ -272,7 +203,7 @@ int trigger_main(int argc, char *argv[], void *userdata) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL; _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_hashmap_free_ Hashmap *settle_hashmap = NULL; _cleanup_set_free_ Set *settle_set = NULL;
usec_t ping_timeout_usec = 5 * USEC_PER_SEC; usec_t ping_timeout_usec = 5 * USEC_PER_SEC;
bool settle = false, ping = false; bool settle = false, ping = false;
int c, r; int c, r;
@ -396,7 +327,7 @@ int trigger_main(int argc, char *argv[], void *userdata) {
break; break;
} }
case ARG_PING: case ARG_PING: {
ping = true; ping = true;
if (optarg) { if (optarg) {
r = parse_sec(optarg, &ping_timeout_usec); r = parse_sec(optarg, &ping_timeout_usec);
@ -404,10 +335,7 @@ int trigger_main(int argc, char *argv[], void *userdata) {
log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg); log_error_errno(r, "Failed to parse timeout value '%s', ignoring: %m", optarg);
} }
break; break;
}
case ARG_UUID:
arg_uuid = true;
break;
case 'V': case 'V':
return print_version(); return print_version();
@ -449,8 +377,8 @@ int trigger_main(int argc, char *argv[], void *userdata) {
} }
if (settle) { if (settle) {
settle_hashmap = hashmap_new(&path_hash_ops_free_free); settle_set = set_new(&string_hash_ops_free);
if (!settle_hashmap) if (!settle_set)
return log_oom(); return log_oom();
r = sd_event_default(&event); r = sd_event_default(&event);
@ -465,7 +393,7 @@ int trigger_main(int argc, char *argv[], void *userdata) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to attach event to device monitor: %m"); return log_error_errno(r, "Failed to attach event to device monitor: %m");
r = sd_device_monitor_start(m, device_monitor_handler, settle_hashmap); r = sd_device_monitor_start(m, device_monitor_handler, settle_set);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to start device monitor: %m"); return log_error_errno(r, "Failed to start device monitor: %m");
} }
@ -485,11 +413,11 @@ int trigger_main(int argc, char *argv[], void *userdata) {
assert_not_reached("Unknown device type"); assert_not_reached("Unknown device type");
} }
r = exec_list(e, action, settle_hashmap); r = exec_list(e, action, settle ? &settle_set : NULL);
if (r < 0) if (r < 0)
return r; return r;
if (event && !hashmap_isempty(settle_hashmap)) { if (event && !set_isempty(settle_set)) {
r = sd_event_loop(event); r = sd_event_loop(event);
if (r < 0) if (r < 0)
return log_error_errno(r, "Event loop failed: %m"); return log_error_errno(r, "Event loop failed: %m");

View File

@ -1,29 +0,0 @@
[Match]
Name=veth-peer
[Network]
Address=10.1.1.1/24
DHCPServer=true
IPMasquerade=true
IPForward=true
[DHCPServer]
PoolOffset=0
PoolSize=20
EmitDNS=yes
DNS=9.9.9.9
[DHCPServerStaticLease]
MACAddress=12:34:56:78:9a:bc
Address=10.1.1.2
[DHCPServerStaticLease]
MACAddress=12:34:56:78:9a:bc
Address=10.1.1.3
[DHCPServerStaticLease]
Address=10.1.1.4
[DHCPServerStaticLease]
MACAddress=12:34:56:78:9a:bf
Address=10.1.1.5

View File

@ -366,9 +366,6 @@ RelayTarget=
RelayAgentCircuitId= RelayAgentCircuitId=
RelayAgentRemoteId= RelayAgentRemoteId=
ServerAddress= ServerAddress=
[DHCPServerStaticLease]
MACAddress=
Address=
[NextHop] [NextHop]
Id= Id=
Gateway= Gateway=

View File

@ -1,9 +0,0 @@
[Match]
Name=veth99
[Network]
IPv6AcceptRA=no
DHCP=ipv4
[DHCPv4]
ClientIdentifier=mac

View File

@ -1,17 +0,0 @@
[Match]
Name=veth-peer
[Network]
IPv6AcceptRA=no
Address=10.1.1.1/24
DHCPServer=yes
[DHCPServer]
PoolOffset=0
PoolSize=20
EmitDNS=yes
DNS=9.9.9.9
[DHCPServerStaticLease]
MACAddress=12:34:56:78:9a:bc
Address=10.1.1.3

View File

@ -3673,10 +3673,8 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
units = [ units = [
'25-veth.netdev', '25-veth.netdev',
'dhcp-client.network', 'dhcp-client.network',
'dhcp-client-static-lease.network',
'dhcp-client-timezone-router.network', 'dhcp-client-timezone-router.network',
'dhcp-server.network', 'dhcp-server.network',
'dhcp-server-static-lease.network',
'dhcp-server-timezone-router.network'] 'dhcp-server-timezone-router.network']
def setUp(self): def setUp(self):
@ -3711,15 +3709,6 @@ class NetworkdDHCPServerTests(unittest.TestCase, Utilities):
self.assertRegex(output, '192.168.5.*') self.assertRegex(output, '192.168.5.*')
self.assertRegex(output, 'Europe/Berlin') self.assertRegex(output, 'Europe/Berlin')
def test_dhcp_server_static_lease(self):
copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-client-static-lease.network', 'dhcp-server-static-lease.network')
start_networkd()
self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'veth99', env=env)
print(output)
self.assertIn('10.1.1.3 (DHCP4 via 10.1.1.1)', output)
class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities): class NetworkdDHCPServerRelayAgentTests(unittest.TestCase, Utilities):
links = [ links = [
'client', 'client',