]> git.proxmox.com Git - systemd.git/commitdiff
New upstream version 249.4
authorMichael Biebl <biebl@debian.org>
Mon, 30 Aug 2021 08:27:49 +0000 (10:27 +0200)
committerMichael Biebl <biebl@debian.org>
Mon, 30 Aug 2021 08:27:49 +0000 (10:27 +0200)
43 files changed:
man/org.freedesktop.systemd1.xml
man/systemd.link.xml
man/systemd.network.xml
shell-completion/zsh/_udevadm
src/analyze/analyze-security.c
src/boot/efi/boot.c
src/boot/efi/linux.c
src/boot/efi/linux.h
src/boot/efi/random-seed.c
src/core/cgroup.c
src/core/cgroup.h
src/core/dbus-unit.c
src/core/manager.c
src/core/unit.c
src/fstab-generator/fstab-generator.c
src/import/curl-util.c
src/journal/journald-server.c
src/libsystemd-network/sd-dhcp-server.c
src/libsystemd-network/sd-dhcp6-client.c
src/network/netdev/macvlan.c
src/network/networkd-address.c
src/network/networkd-link.c
src/network/networkd-ndisc.c
src/network/networkd-nexthop.c
src/network/networkd-route.c
src/network/networkd-route.h
src/network/networkd-routing-policy-rule.c
src/network/networkd-routing-policy-rule.h
src/network/networkd-setlink.c
src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-stub.c
src/resolve/resolved-dns-transaction.c
src/shared/discover-image.c
src/shared/hostname-setup.c
src/shared/utmp-wtmp.c
src/test/test-sizeof.c
src/timesync/timesyncd-manager.c
src/udev/udev-builtin-net_setup_link.c
test/test-functions
test/test-network/conf/25-nexthop.network
test/test-network/conf/25-route-static.network
test/test-network/conf/networkd-manage-foreign-routes-no.conf [new file with mode: 0644]
test/test-network/systemd-networkd-tests.py

index 74a920273afbbf9b64a818215c6e8592505c0ba1..c14c5b6601810df2504b188819219d7abba6029a 100644 (file)
@@ -1706,7 +1706,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly b DefaultDependencies = ...;
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
-      readonly s OnSuccesJobMode = '...';
+      readonly s OnSuccessJobMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s OnFailureJobMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -1815,7 +1815,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property CanFreeze is not documented!-->
 
-    <!--property OnSuccesJobMode is not documented!-->
+    <!--property OnSuccessJobMode is not documented!-->
 
     <!--property OnFailureJobMode is not documented!-->
 
@@ -2019,7 +2019,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="DefaultDependencies"/>
 
-    <variablelist class="dbus-property" generated="True" extra-ref="OnSuccesJobMode"/>
+    <variablelist class="dbus-property" generated="True" extra-ref="OnSuccessJobMode"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="OnFailureJobMode"/>
 
index ee4356ac3d66b6f14e021eb49168db1b70dd9059..1c18f35fc858826504529a3ebceaaebe4ff9059c 100644 (file)
       <varlistentry>
         <term><varname>ReceiveChecksumOffload=</varname></term>
         <listitem>
-          <para>Takes a boolean. If set to true, the hardware offload for checksumming of ingress
+          <para>Takes a boolean. If set to true, hardware offload for checksumming of ingress
           network packets is enabled. When unset, the kernel's default will be used.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term><varname>TransmitChecksumOffload=</varname></term>
         <listitem>
-          <para>Takes a boolean. If set to true, the hardware offload for checksumming of egress
+          <para>Takes a boolean. If set to true, hardware offload for checksumming of egress
           network packets is enabled. When unset, the kernel's default will be used.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term><varname>TCPSegmentationOffload=</varname></term>
         <listitem>
-          <para>Takes a boolean. If set to true, the TCP Segmentation Offload (TSO) is enabled.
+          <para>Takes a boolean. If set to true, TCP Segmentation Offload (TSO) is enabled.
           When unset, the kernel's default will be used.</para>
         </listitem>
       </varlistentry>
        <varlistentry>
       <term><varname>TCP6SegmentationOffload=</varname></term>
         <listitem>
-          <para>Takes a boolean. If set to true, the TCP6 Segmentation Offload (tx-tcp6-segmentation) is enabled.
+          <para>Takes a boolean. If set to true, TCP6 Segmentation Offload (tx-tcp6-segmentation) is enabled.
           When unset, the kernel's default will be used.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term><varname>GenericSegmentationOffload=</varname></term>
         <listitem>
-          <para>Takes a boolean. If set to true, the Generic Segmentation Offload (GSO) is enabled.
+          <para>Takes a boolean. If set to true, Generic Segmentation Offload (GSO) is enabled.
           When unset, the kernel's default will be used.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term><varname>GenericReceiveOffload=</varname></term>
         <listitem>
-          <para>Takes a boolean. If set to true, the Generic Receive Offload (GRO) is enabled.
+          <para>Takes a boolean. If set to true, Generic Receive Offload (GRO) is enabled.
           When unset, the kernel's default will be used.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term><varname>LargeReceiveOffload=</varname></term>
         <listitem>
-          <para>Takes a boolean. If set to true, the Large Receive Offload (LRO) is enabled.
+          <para>Takes a boolean. If set to true, Large Receive Offload (LRO) is enabled.
           When unset, the kernel's default will be used.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term><varname>RxFlowControl=</varname></term>
         <listitem>
-          <para>Takes a boolean. When set, enables the receive flow control, also known as the ethernet
+          <para>Takes a boolean. When set, enables receive flow control, also known as the ethernet
           receive PAUSE message (generate and send ethernet PAUSE frames). When unset, the kernel's
           default will be used.</para>
         </listitem>
       <varlistentry>
         <term><varname>TxFlowControl=</varname></term>
         <listitem>
-          <para>Takes a boolean. When set, enables the transmit flow control, also known as the ethernet
+          <para>Takes a boolean. When set, enables transmit flow control, also known as the ethernet
           transmit PAUSE message (respond to received ethernet PAUSE frames). When unset, the kernel's
           default will be used.</para>
         </listitem>
       <varlistentry>
         <term><varname>AutoNegotiationFlowControl=</varname></term>
         <listitem>
-          <para>Takes a boolean. When set, the auto negotiation enables the interface to exchange state
+          <para>Takes a boolean. When set, auto negotiation enables the interface to exchange state
           advertisements with the connected peer so that the two devices can agree on the ethernet
           PAUSE configuration. When unset, the kernel's default will be used.</para>
         </listitem>
index 3b7680eb8b32110a2ea7ff499e7e35f2f250d0e0..9de9816ceddaaa2348a17fb0fed41e56305f851e 100644 (file)
@@ -1238,7 +1238,9 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
           <term><varname>Priority=</varname></term>
           <listitem>
             <para>Specifies the priority of this rule. <varname>Priority=</varname> is an unsigned
-            integer. Higher number means lower priority, and rules get processed in order of increasing number.</para>
+            integer in the range 0…4294967295. Higher number means lower priority, and rules get
+            processed in order of increasing number. Defaults to unset, and the kernel will pick
+            a value dynamically.</para>
           </listitem>
         </varlistentry>
         <varlistentry>
index a19829c1dee2fa12e0b38d76248166199659a90a..87fdb5e42ce49f560e4fe9e072329faaa5b0221e 100644 (file)
@@ -23,7 +23,7 @@ _udevadm_trigger(){
         '--dry-run[Do not actually trigger the event.]' \
         '--quiet[Suppress error logging in triggering events.]' \
         '--type=[Trigger a specific type of devices.]:types:(devices subsystems failed)' \
-        '--action=[Type of event to be triggered.]:actions:(add change remove)' \
+        '--action=[Type of event to be triggered.]:actions:(add change remove move online offline bind unbind)' \
         '--subsystem-match=[Trigger events for devices which belong to a matching subsystem.]' \
         '--subsystem-nomatch=[Do not trigger events for devices which belong to a matching subsystem.]' \
         '--attr-match=attribute=[Trigger events for devices with a matching sysfs attribute.]' \
@@ -74,7 +74,7 @@ _udevadm_monitor(){
 (( $+functions[_udevadm_test] )) ||
 _udevadm_test(){
     _arguments \
-        '--action=[The action string.]:actions:(add change remove)' \
+        '--action=[The action string.]:actions:(add change remove move online offline bind unbind)' \
         '--subsystem=[The subsystem string.]' \
         '--help[Print help text.]' \
         '*::devpath:_files -P /sys/ -W /sys'
index f20606c17ca4fc01110ba9a14d4b3d463cd77b80..309e9a81b5c2af12493bdd93e64cac54c7a8ce47 100644 (file)
@@ -1910,7 +1910,7 @@ static int property_read_ip_filters(
         if (streq(member, "IPIngressFilterPath"))
                 info->ip_filters_custom_ingress = !strv_isempty(l);
         else if (streq(member, "IPEgressFilterPath"))
-                info->ip_filters_custom_ingress = !strv_isempty(l);
+                info->ip_filters_custom_egress = !strv_isempty(l);
 
         return 0;
 }
index 3249171ec127ea8230a37fbbbc69a6cfcbc2ce20..13940a6df75dde1386c0599515ce976f78c9abf3 100644 (file)
@@ -1724,7 +1724,7 @@ static ConfigEntry *config_entry_add_loader(
         *entry = (ConfigEntry) {
                 .type = type,
                 .title = StrDuplicate(title),
-                .version = StrDuplicate(version),
+                .version = version ? StrDuplicate(version) : NULL,
                 .device = device,
                 .loader = StrDuplicate(loader),
                 .id = StrDuplicate(id),
index 4d44671315f858adbd6a45ce425b309defaf16ec..b5d6120493d92f62dd9b556f5ef341c6336dbfad 100644 (file)
@@ -25,7 +25,7 @@ static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) {
         handover(image, ST, params);
 }
 
-EFI_STATUS linux_exec(EFI_HANDLE *image,
+EFI_STATUS linux_exec(EFI_HANDLE image,
                       CHAR8 *cmdline, UINTN cmdline_len,
                       UINTN linux_addr,
                       UINTN initrd_addr, UINTN initrd_size) {
index 09be2de27b36a9a4cc7655d748dbe7bbe48eab18..53270e16b30b3fda1ecabe38409412fde04be3a9 100644 (file)
@@ -83,7 +83,7 @@ struct boot_params {
         UINT8  _pad9[276];
 } __attribute__((packed));
 
-EFI_STATUS linux_exec(EFI_HANDLE *image,
+EFI_STATUS linux_exec(EFI_HANDLE image,
                       CHAR8 *cmdline, UINTN cmdline_size,
                       UINTN linux_addr,
                       UINTN initrd_addr, UINTN initrd_size);
index ff364695f352982871e37bda4480b6b89f893c76..3e179851b0805cd8ddd0f90dbf6576da9d19baf6 100644 (file)
@@ -245,7 +245,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
 
         err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, (CHAR16*) L"\\loader\\random-seed", EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0ULL);
         if (EFI_ERROR(err)) {
-                if (err != EFI_NOT_FOUND)
+                if (err != EFI_NOT_FOUND && err != EFI_WRITE_PROTECTED)
                         Print(L"Failed to open random seed file: %r\n", err);
                 return err;
         }
index 3a6f768c608b109077a151c466869b440b3104e9..5c07aa71d14720adf26c84831d897f90226a63d6 100644 (file)
@@ -3039,6 +3039,9 @@ static int unit_check_cgroup_events(Unit *u) {
 
         assert(u);
 
+        if (!u->cgroup_path)
+                return 0;
+
         r = cg_get_keyed_attribute_graceful(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events",
                                             STRV_MAKE("populated", "frozen"), values);
         if (r < 0)
@@ -3871,6 +3874,21 @@ void unit_invalidate_cgroup_bpf(Unit *u) {
         }
 }
 
+void unit_cgroup_catchup(Unit *u) {
+        assert(u);
+
+        if (!UNIT_HAS_CGROUP_CONTEXT(u))
+                return;
+
+        /* We dropped the inotify watch during reexec/reload, so we need to
+         * check these as they may have changed.
+         * Note that (currently) the kernel doesn't actually update cgroup
+         * file modification times, so we can't just serialize and then check
+         * the mtime for file(s) we are interested in. */
+        (void) unit_check_cgroup_events(u);
+        unit_add_to_cgroup_oom_queue(u);
+}
+
 bool unit_cgroup_delegate(Unit *u) {
         CGroupContext *c;
 
index ea929368cbd4d409a6dae3136ddc8d5d5d612a6c..3f8cad899de56ff398a2684c4e3952a21778793d 100644 (file)
@@ -313,6 +313,8 @@ void manager_invalidate_startup_units(Manager *m);
 const char* cgroup_device_policy_to_string(CGroupDevicePolicy i) _const_;
 CGroupDevicePolicy cgroup_device_policy_from_string(const char *s) _pure_;
 
+void unit_cgroup_catchup(Unit *u);
+
 bool unit_cgroup_delegate(Unit *u);
 
 int compare_job_priority(const void *a, const void *b);
index aa10939a041eaa4ac7ac3129e7a16dd32ce30a28..124b9e496b26d1975fb4309c89bf4b5452e28cc4 100644 (file)
@@ -905,7 +905,8 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("OnSuccesJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("OnSuccesJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* deprecated */
+        SD_BUS_PROPERTY("OnSuccessJobMode", "s", property_get_job_mode, offsetof(Unit, on_success_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
index 888443734701eb3291387746c132785efe8df78f..34891a875465aafee15dec642a2bdc7b740b1ea2 100644 (file)
@@ -1410,6 +1410,10 @@ static void manager_clear_jobs_and_units(Manager *m) {
         assert(!m->cleanup_queue);
         assert(!m->gc_unit_queue);
         assert(!m->gc_job_queue);
+        assert(!m->cgroup_realize_queue);
+        assert(!m->cgroup_empty_queue);
+        assert(!m->cgroup_oom_queue);
+        assert(!m->target_deps_queue);
         assert(!m->stop_when_unneeded_queue);
         assert(!m->start_when_upheld_queue);
         assert(!m->stop_when_bound_queue);
index 47966bcf0de042aa993b59f4ffe8e987273c9e84..38d3eb703f88d6eb0988b4a3c9e57ad0788b8379 100644 (file)
@@ -733,6 +733,9 @@ Unit* unit_free(Unit *u) {
         if (u->in_dbus_queue)
                 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
 
+        if (u->in_cleanup_queue)
+                LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u);
+
         if (u->in_gc_queue)
                 LIST_REMOVE(gc_queue, u->manager->gc_unit_queue, u);
 
@@ -742,8 +745,8 @@ Unit* unit_free(Unit *u) {
         if (u->in_cgroup_empty_queue)
                 LIST_REMOVE(cgroup_empty_queue, u->manager->cgroup_empty_queue, u);
 
-        if (u->in_cleanup_queue)
-                LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u);
+        if (u->in_cgroup_oom_queue)
+                LIST_REMOVE(cgroup_oom_queue, u->manager->cgroup_oom_queue, u);
 
         if (u->in_target_deps_queue)
                 LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u);
@@ -3578,7 +3581,6 @@ int unit_add_blockdev_dependency(Unit *u, const char *what, UnitDependencyMask m
 int unit_coldplug(Unit *u) {
         int r = 0, q;
         char **i;
-        Job *uj;
 
         assert(u);
 
@@ -3601,9 +3603,13 @@ int unit_coldplug(Unit *u) {
                         r = q;
         }
 
-        uj = u->job ?: u->nop_job;
-        if (uj) {
-                q = job_coldplug(uj);
+        if (u->job) {
+                q = job_coldplug(u->job);
+                if (q < 0 && r >= 0)
+                        r = q;
+        }
+        if (u->nop_job) {
+                q = job_coldplug(u->nop_job);
                 if (q < 0 && r >= 0)
                         r = q;
         }
@@ -3616,6 +3622,8 @@ void unit_catchup(Unit *u) {
 
         if (UNIT_VTABLE(u)->catchup)
                 UNIT_VTABLE(u)->catchup(u);
+
+        unit_cgroup_catchup(u);
 }
 
 static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_masked) {
index a4e3ea531101a485d4f14c589de0be830274a443..b6582c9538ac15077a4791c08b8139db1c1b1b60 100644 (file)
@@ -435,7 +435,8 @@ static int add_mount(
 
         /* Order the mount unit we generate relative to the post unit, so that DefaultDependencies= on the
          * target unit won't affect us. */
-        if (post && !FLAGS_SET(flags, MOUNT_AUTOMOUNT) && !FLAGS_SET(flags, MOUNT_NOAUTO))
+        if (post && !FLAGS_SET(flags, MOUNT_AUTOMOUNT) && !FLAGS_SET(flags, MOUNT_NOAUTO) &&
+            !FLAGS_SET(flags, MOUNT_NOFAIL))
                 fprintf(f, "Before=%s\n", post);
 
         if (passno != 0) {
index ed2ac0a654a69c3a832ee15bf34a5e775f63b9c0..d6a16b4f57cf8c38962c766ed73bcea672cd1023 100644 (file)
@@ -256,6 +256,9 @@ int curl_glue_make(CURL **ret, const char *url, void *userdata) {
         if (curl_easy_setopt(c, CURLOPT_LOW_SPEED_LIMIT, 30L) != CURLE_OK)
                 return -EIO;
 
+        if (curl_easy_setopt(c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_FILE) != CURLE_OK)
+                return -EIO;
+
         *ret = TAKE_PTR(c);
         return 0;
 }
index 30f04f5383451e1043a916831cb47ac36ba2e4c4..a0695ec519558079390aedd00ae0b5ddf72c91e8 100644 (file)
@@ -415,6 +415,13 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
         if (s->runtime_journal)
                 return s->runtime_journal;
 
+        /* If we are not in persistent mode, then we need return NULL immediately rather than opening a
+         * persistent journal of any sort.
+         *
+         * Fixes https://github.com/systemd/systemd/issues/20390 */
+        if (!IN_SET(s->storage, STORAGE_AUTO, STORAGE_PERSISTENT))
+                return NULL;
+
         if (uid_for_system_journal(uid))
                 return s->system_journal;
 
index e2ea79f58414b31dae29084d3583b25cfb0b540c..9ae884b0fca5237983406a2a16f56a4c0f69ba35 100644 (file)
@@ -1107,7 +1107,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
 
                 if (server->bound_leases[pool_offset] == existing_lease) {
                         server->bound_leases[pool_offset] = NULL;
-                        hashmap_remove(server->leases_by_client_id, existing_lease);
+                        hashmap_remove(server->leases_by_client_id, &existing_lease->client_id);
                         dhcp_lease_free(existing_lease);
 
                         if (server->callback)
index e8c47f429a57d9919a35d49ede69854d7452a9a0..f99c12620bb73497a2632587eec4d469de28afc6 100644 (file)
@@ -1219,7 +1219,7 @@ static int client_parse_message(
 
                         if (lease->ia.addresses) {
                                 lt_t1 = MIN(lt_t1, be32toh(lease->ia.ia_na.lifetime_t1));
-                                lt_t2 = MIN(lt_t2, be32toh(lease->ia.ia_na.lifetime_t1));
+                                lt_t2 = MIN(lt_t2, be32toh(lease->ia.ia_na.lifetime_t2));
                         }
 
                         break;
@@ -1328,17 +1328,16 @@ static int client_parse_message(
                                          dhcp6_message_type_to_string(message->type));
                         return -EINVAL;
                 }
+        }
 
-        } else {
-                if (lease->ia.addresses) {
-                        lease->ia.ia_na.lifetime_t1 = htobe32(lt_t1);
-                        lease->ia.ia_na.lifetime_t2 = htobe32(lt_t2);
-                }
+        if (lease->ia.addresses) {
+                lease->ia.ia_na.lifetime_t1 = htobe32(lt_t1);
+                lease->ia.ia_na.lifetime_t2 = htobe32(lt_t2);
+        }
 
-                if (lease->pd.addresses) {
-                        lease->pd.ia_pd.lifetime_t1 = htobe32(lt_t1);
-                        lease->pd.ia_pd.lifetime_t2 = htobe32(lt_t2);
-                }
+        if (lease->pd.addresses) {
+                lease->pd.ia_pd.lifetime_t1 = htobe32(lt_t1);
+                lease->pd.ia_pd.lifetime_t2 = htobe32(lt_t2);
         }
 
         client->information_refresh_time_usec = MAX(irt, IRT_MINIMUM);
index 46b08261482831ae2bfda6d65cdef2d613d8f20e..9d037c2f3683a5ab6dc45e9491c6d32853bc8f8d 100644 (file)
@@ -5,6 +5,7 @@
 #include "conf-parser.h"
 #include "macvlan.h"
 #include "macvlan-util.h"
+#include "networkd-network.h"
 #include "parse-util.h"
 
 DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode");
@@ -16,6 +17,7 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net
         assert(netdev);
         assert(link);
         assert(netdev->ifname);
+        assert(link->network);
 
         if (netdev->kind == NETDEV_KIND_MACVLAN)
                 m = MACVLAN(netdev);
@@ -52,6 +54,13 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MODE attribute: %m");
         }
 
+        /* set the nopromisc flag if Promiscuous= of the link is explicitly set to false */
+        if (m->mode == NETDEV_MACVLAN_MODE_PASSTHRU && link->network->promiscuous == 0) {
+                r = sd_netlink_message_append_u16(req, IFLA_MACVLAN_FLAGS, MACVLAN_FLAG_NOPROMISC);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_FLAGS attribute: %m");
+        }
+
         if (m->bc_queue_length != UINT32_MAX) {
                 r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_BC_QUEUE_LEN, m->bc_queue_length);
                 if (r < 0)
index 6b2230b7256c55ee81f8255666e3303333bd6178..7b221516d752d7158aeac2431279da771cd3467e 100644 (file)
@@ -1272,17 +1272,17 @@ int request_process_address(Request *req) {
         if (r <= 0)
                 return r;
 
-        r = address_get(link, req->address, &a);
-        if (r < 0)
-                return r;
-
-        r = address_configure(a, link, req->netlink_handler);
+        r = address_configure(req->address, link, req->netlink_handler);
         if (r < 0)
                 return r;
 
         /* To prevent a double decrement on failure in after_configure(). */
         req->message_counter = NULL;
 
+        r = address_get(link, req->address, &a);
+        if (r < 0)
+                return r;
+
         if (req->after_configure) {
                 r = req->after_configure(req, a);
                 if (r < 0)
index 9421ce1aa61d8f980a8652dd1c7c8aeec0250335..d58b700050d4f6f6eaf8cdcad9c8412f08610d06 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include <net/if.h>
 #include <netinet/in.h>
 #include <linux/if.h>
 #include <linux/if_arp.h>
@@ -21,6 +22,7 @@
 #include "ethtool-util.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "format-util.h"
 #include "fs-util.h"
 #include "ipvlan.h"
 #include "missing_network.h"
@@ -2161,6 +2163,7 @@ static int link_update_alternative_names(Link *link, sd_netlink_message *message
 }
 
 static int link_update_name(Link *link, sd_netlink_message *message) {
+        char ifname_from_index[IF_NAMESIZE + 1];
         const char *ifname;
         int r;
 
@@ -2177,6 +2180,16 @@ static int link_update_name(Link *link, sd_netlink_message *message) {
         if (streq(ifname, link->ifname))
                 return 0;
 
+        if (!format_ifname(link->ifindex, ifname_from_index))
+                return log_link_debug_errno(link, SYNTHETIC_ERRNO(ENXIO), "Could not get interface name for index %i.", link->ifindex);
+
+        if (!streq(ifname, ifname_from_index)) {
+                log_link_debug(link, "New interface name '%s' received from the kernel does not correspond "
+                               "with the name currently configured on the actual interface '%s'. Ignoring.",
+                               ifname, ifname_from_index);
+                return 0;
+        }
+
         log_link_info(link, "Interface name change detected, renamed to %s.", ifname);
 
         hashmap_remove(link->manager->links_by_name, link->ifname);
index efc47078550847c7695012c261d30fd6b44a6521..e3705bfed5fd03beef26cf91440b4d7c65bf86e7 100644 (file)
@@ -765,7 +765,9 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
         assert(link);
         assert(rt);
 
-        r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
+        /* Do not use clock_boottime_or_monotonic() here, as the kernel internally manages cstamp and
+         * tstamp with jiffies, and it is not increased while the system is suspended. */
+        r = sd_ndisc_router_get_timestamp(rt, CLOCK_MONOTONIC, &time_now);
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
 
index a52e5dcb16c8bb5c2a11d9920f3b40f5659eb080..c5cba88f46e4d24da67a67ca368ae76dd766f362 100644 (file)
@@ -791,12 +791,7 @@ static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
                 }
         }
 
-        if (nexthop->onlink <= 0 &&
-            in_addr_is_set(nexthop->family, &nexthop->gw) &&
-            !manager_address_is_reachable(link->manager, nexthop->family, &nexthop->gw))
-                return false;
-
-        return true;
+        return gateway_is_ready(link, nexthop->onlink, nexthop->family, &nexthop->gw);
 }
 
 int request_process_nexthop(Request *req) {
index 77a93beca934b210fbb3bcd97ffbec2c8c215ed1..b7852f6eec8bd8868fc2086ce71125857e4f7ab3 100644 (file)
@@ -746,21 +746,54 @@ static bool route_address_is_reachable(const Route *route, int family, const uni
                         FAMILY_ADDRESS_SIZE(family) * 8) > 0;
 }
 
-bool manager_address_is_reachable(Manager *manager, int family, const union in_addr_union *address) {
-        Link *link;
+static bool prefix_route_address_is_reachable(const Address *a, int family, const union in_addr_union *address) {
+        assert(a);
+        assert(IN_SET(family, AF_INET, AF_INET6));
+        assert(address);
 
-        assert(manager);
+        if (a->family != family)
+                return false;
+        if (!address_is_ready(a))
+                return false;
+        if (FLAGS_SET(a->flags, IFA_F_NOPREFIXROUTE))
+                return false;
+        if (in_addr_is_set(a->family, &a->in_addr_peer))
+                return false;
+
+        return in_addr_prefix_intersect(
+                        family,
+                        &a->in_addr,
+                        a->prefixlen,
+                        address,
+                        FAMILY_ADDRESS_SIZE(family) * 8) > 0;
+}
+
+static bool link_address_is_reachable(Link *link, int family, const union in_addr_union *address) {
+        Route *route;
+
+        assert(link);
+        assert(link->manager);
         assert(IN_SET(family, AF_INET, AF_INET6));
         assert(address);
 
-        HASHMAP_FOREACH(link, manager->links_by_index) {
-                Route *route;
 
-                SET_FOREACH(route, link->routes)
-                        if (route_address_is_reachable(route, family, address))
+        SET_FOREACH(route, link->routes)
+                if (route_address_is_reachable(route, family, address))
+                        return true;
+        SET_FOREACH(route, link->routes_foreign)
+                if (route_address_is_reachable(route, family, address))
+                        return true;
+
+        /* If we do not manage foreign routes, then there may exist a prefix route we do not know,
+         * which was created on configuring an address. Hence, also check the addresses. */
+        if (!link->manager->manage_foreign_routes) {
+                Address *a;
+
+                SET_FOREACH(a, link->addresses)
+                        if (prefix_route_address_is_reachable(a, family, address))
                                 return true;
-                SET_FOREACH(route, link->routes_foreign)
-                        if (route_address_is_reachable(route, family, address))
+                SET_FOREACH(a, link->addresses_foreign)
+                        if (prefix_route_address_is_reachable(a, family, address))
                                 return true;
         }
 
@@ -1658,6 +1691,22 @@ int link_request_static_routes(Link *link, bool only_ipv4) {
         return 0;
 }
 
+bool gateway_is_ready(Link *link, int onlink, int family, const union in_addr_union *gw) {
+        assert(link);
+        assert(gw);
+
+        if (onlink > 0)
+                return true;
+
+        if (!in_addr_is_set(family, gw))
+                return true;
+
+        if (family == AF_INET6 && in6_addr_is_link_local(&gw->in6))
+                return true;
+
+        return link_address_is_reachable(link, family, gw);
+}
+
 static int route_is_ready_to_configure(const Route *route, Link *link) {
         MultipathRoute *m;
         NextHop *nh = NULL;
@@ -1701,19 +1750,13 @@ static int route_is_ready_to_configure(const Route *route, Link *link) {
                         return r;
         }
 
-        if (route->gateway_onlink <= 0 &&
-            in_addr_is_set(route->gw_family, &route->gw) > 0 &&
-            !manager_address_is_reachable(link->manager, route->gw_family, &route->gw))
+        if (!gateway_is_ready(link, route->gateway_onlink, route->gw_family, &route->gw))
                 return false;
 
         ORDERED_SET_FOREACH(m, route->multipath_routes) {
                 union in_addr_union a = m->gateway.address;
                 Link *l = NULL;
 
-                if (route->gateway_onlink <= 0 &&
-                    !manager_address_is_reachable(link->manager, m->gateway.family, &a))
-                        return false;
-
                 if (m->ifname) {
                         if (link_get_by_name(link->manager, m->ifname, &l) < 0)
                                 return false;
@@ -1725,6 +1768,9 @@ static int route_is_ready_to_configure(const Route *route, Link *link) {
                 }
                 if (l && !link_is_ready_to_configure(l, true))
                         return false;
+
+                if (!gateway_is_ready(l ?: link, route->gateway_onlink, m->gateway.family, &a))
+                        return false;
         }
 
         return true;
index 2d262819add0f3877d10aece97b1afbbd4dd369d..235a91f08d59c41ce2f966474976f6001781793e 100644 (file)
@@ -78,8 +78,8 @@ int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Li
 int route_remove(const Route *route, Manager *manager, Link *link);
 
 int link_has_route(Link *link, const Route *route);
-bool manager_address_is_reachable(Manager *manager, int family, const union in_addr_union *address);
 int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret);
+bool gateway_is_ready(Link *link, int onlink, int family, const union in_addr_union *gw);
 
 int link_drop_routes(Link *link);
 int link_drop_foreign_routes(Link *link);
index af7e8a973cf47087be9e5b65f1af1a5acff40bb4..03ccbd8e8562c7530c651c45241359d888923499 100644 (file)
@@ -163,7 +163,9 @@ void routing_policy_rule_hash_func(const RoutingPolicyRule *rule, struct siphash
                 siphash24_compress(&rule->type, sizeof(rule->type), state);
                 siphash24_compress(&rule->fwmark, sizeof(rule->fwmark), state);
                 siphash24_compress(&rule->fwmask, sizeof(rule->fwmask), state);
-                siphash24_compress(&rule->priority, sizeof(rule->priority), state);
+                siphash24_compress_boolean(rule->priority_set, state);
+                if (rule->priority_set)
+                        siphash24_compress(&rule->priority, sizeof(rule->priority), state);
                 siphash24_compress(&rule->table, sizeof(rule->table), state);
                 siphash24_compress(&rule->suppress_prefixlen, sizeof(rule->suppress_prefixlen), state);
 
@@ -229,10 +231,16 @@ int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const RoutingPo
                 if (r != 0)
                         return r;
 
-                r = CMP(a->priority, b->priority);
+                r = CMP(a->priority_set, b->priority_set);
                 if (r != 0)
                         return r;
 
+                if (a->priority_set) {
+                        r = CMP(a->priority, b->priority);
+                        if (r != 0)
+                                return r;
+                }
+
                 r = CMP(a->table, b->table);
                 if (r != 0)
                         return r;
@@ -293,8 +301,9 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
                 routing_policy_rule_compare_func,
                 routing_policy_rule_free);
 
-static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *rule, RoutingPolicyRule **ret) {
+static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *rule, bool require_priority, RoutingPolicyRule **ret) {
         RoutingPolicyRule *existing;
+        int r;
 
         assert(m);
 
@@ -312,6 +321,23 @@ static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *rule, Ro
                 return 0;
         }
 
+        if (!require_priority && rule->priority_set) {
+                _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
+
+                r = routing_policy_rule_dup(rule, &tmp);
+                if (r < 0)
+                        return r;
+
+                tmp->priority_set = false;
+
+                existing = set_get(m->rules, tmp);
+                if (existing) {
+                        if (ret)
+                                *ret = existing;
+                        return 1;
+                }
+        }
+
         return -ENOENT;
 }
 
@@ -328,7 +354,7 @@ static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, Rout
         if (r < 0)
                 return r;
 
-        r = routing_policy_rule_get(m, rule, &existing);
+        r = routing_policy_rule_get(m, rule, true, &existing);
         if (r == -ENOENT) {
                 /* Rule does not exist, use a new one. */
                 r = set_ensure_put(&m->rules, &routing_policy_rule_hash_ops, rule);
@@ -371,6 +397,32 @@ static int routing_policy_rule_consume_foreign(Manager *m, RoutingPolicyRule *ru
         return 1;
 }
 
+static int routing_policy_rule_update_priority(RoutingPolicyRule *rule, uint32_t priority) {
+        int r;
+
+        assert(rule);
+        assert(rule->manager);
+
+        if (rule->priority_set)
+                return 0;
+
+        if (!set_remove(rule->manager->rules, rule))
+                return -ENOENT;
+
+        rule->priority = priority;
+        rule->priority_set = true;
+
+        r = set_put(rule->manager->rules, rule);
+        if (r <= 0) {
+                /* Undo */
+                rule->priority_set = false;
+                assert_se(set_put(rule->manager->rules, rule) > 0);
+                return r == 0 ? -EEXIST : r;
+        }
+
+        return 1;
+}
+
 static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, const char *str, const Link *link, const Manager *m) {
         _cleanup_free_ char *from = NULL, *to = NULL, *table = NULL;
 
@@ -422,9 +474,11 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule
                         return log_link_error_errno(link, r, "Could not set destination prefix length: %m");
         }
 
-        r = sd_netlink_message_append_u32(m, FRA_PRIORITY, rule->priority);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append FRA_PRIORITY attribute: %m");
+        if (rule->priority_set) {
+                r = sd_netlink_message_append_u32(m, FRA_PRIORITY, rule->priority);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append FRA_PRIORITY attribute: %m");
+        }
 
         if (rule->tos > 0) {
                 r = sd_rtnl_message_routing_policy_rule_set_tos(m, rule->tos);
@@ -662,6 +716,28 @@ int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const L
                         continue;
                 }
 
+                if (!foreign) {
+                        _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
+
+                        /* The rule may be configured without priority. Try to find without priority. */
+
+                        k = routing_policy_rule_dup(rule, &tmp);
+                        if (k < 0) {
+                                if (r >= 0)
+                                        r = k;
+                                continue;
+                        }
+
+                        tmp->priority_set = false;
+
+                        k = links_have_routing_policy_rule(m, tmp, except);
+                        if (k != 0) {
+                                if (k < 0 && r >= 0)
+                                        r = k;
+                                continue;
+                        }
+                }
+
                 k = routing_policy_rule_remove(rule, m);
                 if (k < 0 && r >= 0)
                         r = k;
@@ -821,11 +897,11 @@ int request_process_routing_policy_rule(Request *req) {
 }
 
 static const RoutingPolicyRule kernel_rules[] = {
-        { .family = AF_INET,  .priority = 0,     .table = RT_TABLE_LOCAL,   .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
-        { .family = AF_INET,  .priority = 32766, .table = RT_TABLE_MAIN,    .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
-        { .family = AF_INET,  .priority = 32767, .table = RT_TABLE_DEFAULT, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
-        { .family = AF_INET6, .priority = 0,     .table = RT_TABLE_LOCAL,   .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
-        { .family = AF_INET6, .priority = 32766, .table = RT_TABLE_MAIN,    .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
+        { .family = AF_INET,  .priority_set = true, .priority = 0,     .table = RT_TABLE_LOCAL,   .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
+        { .family = AF_INET,  .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN,    .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
+        { .family = AF_INET,  .priority_set = true, .priority = 32767, .table = RT_TABLE_DEFAULT, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
+        { .family = AF_INET6, .priority_set = true, .priority = 0,     .table = RT_TABLE_LOCAL,   .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
+        { .family = AF_INET6, .priority_set = true, .priority = 32766, .table = RT_TABLE_MAIN,    .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
 };
 
 static bool routing_policy_rule_is_created_by_kernel(const RoutingPolicyRule *rule) {
@@ -936,6 +1012,9 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
                 log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
                 return 0;
         }
+        /* The kernel does not send priority if priority is zero. So, the flag below must be always set
+         * even if the message does not contain FRA_PRIORITY. */
+        tmp->priority_set = true;
 
         r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table);
         if (r < 0 && r != -ENODATA) {
@@ -1027,13 +1106,16 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
                  * protocol of the received rule is RTPROT_KERNEL or RTPROT_STATIC. */
                 tmp->protocol = routing_policy_rule_is_created_by_kernel(tmp) ? RTPROT_KERNEL : RTPROT_STATIC;
 
-        (void) routing_policy_rule_get(m, tmp, &rule);
+        (void) routing_policy_rule_get(m, tmp, false, &rule);
 
         switch (type) {
         case RTM_NEWRULE:
-                if (rule)
+                if (rule) {
                         log_routing_policy_rule_debug(tmp, "Received remembered", NULL, m);
-                else if (!m->manage_foreign_routes)
+                        r = routing_policy_rule_update_priority(rule, tmp->priority);
+                        if (r < 0)
+                                log_warning_errno(r, "Failed to update priority of remembered routing policy rule, ignoring: %m");
+                } else if (!m->manage_foreign_routes)
                         log_routing_policy_rule_debug(tmp, "Ignoring received foreign", NULL, m);
                 else {
                         log_routing_policy_rule_debug(tmp, "Remembering foreign", NULL, m);
@@ -1155,11 +1237,19 @@ int config_parse_routing_policy_rule_priority(
         if (r < 0)
                 return log_oom();
 
+        if (isempty(rvalue)) {
+                n->priority = 0;
+                n->priority_set = false;
+                TAKE_PTR(n);
+                return 0;
+        }
+
         r = safe_atou32(rvalue, &n->priority);
         if (r < 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse RPDB rule priority, ignoring: %s", rvalue);
                 return 0;
         }
+        n->priority_set = true;
 
         TAKE_PTR(n);
         return 0;
index aed37b00d21d7689c92f7b1efd257beb0df4048c..557048c3f48e3c0570d3f960dfb74191fa4ac677 100644 (file)
@@ -20,6 +20,7 @@ typedef struct RoutingPolicyRule {
         NetworkConfigSection *section;
 
         bool invert_rule;
+        bool priority_set;
 
         uint8_t tos;
         uint8_t type;
index 10c312c480866d0a399f5467e1385ea2f0613e19..13c4cedd104176bed7f6c48d3cc654f19b44acf9 100644 (file)
@@ -229,10 +229,14 @@ static int link_configure(
 
         log_link_debug(link, "Setting %s", set_link_operation_to_string(op));
 
-        if (IN_SET(op, SET_LINK_BOND, SET_LINK_CAN)) {
+        if (op == SET_LINK_BOND) {
                 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->master_ifindex);
                 if (r < 0)
                         return log_link_debug_errno(link, r, "Could not allocate RTM_NEWLINK message: %m");
+        } else if (op == SET_LINK_CAN) {
+                r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->ifindex);
+                if (r < 0)
+                        return log_link_debug_errno(link, r, "Could not allocate RTM_NEWLINK message: %m");
         } else {
                 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
                 if (r < 0)
index e7a4bce71a4a196f960a775e0bdac983ed9ae5eb..58a1376708257a72e7dc5572e70d1d85c309e3d5 100644 (file)
@@ -362,9 +362,8 @@ void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level
         if (s->possible_feature_level > level) {
                 s->possible_feature_level = level;
                 dns_server_reset_counters(s);
+                log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
         }
-
-        log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
 }
 
 void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) {
index 5b9d32f0013085758eb228541f089c8bc7232e85..49da916576b304e835e6723582391727a225221d 100644 (file)
@@ -585,7 +585,7 @@ static int dns_stub_send_reply(
                         DNS_PACKET_RD(q->request_packet),
                         !!q->request_packet->opt,
                         edns0_do,
-                        DNS_PACKET_AD(q->request_packet) && dns_query_fully_authenticated(q),
+                        (DNS_PACKET_AD(q->request_packet) || DNS_PACKET_DO(q->request_packet)) && dns_query_fully_authenticated(q),
                         DNS_PACKET_CD(q->request_packet),
                         q->stub_listener_extra ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX,
                         dns_packet_has_nsid_request(q->request_packet) > 0 && !q->stub_listener_extra);
@@ -627,7 +627,7 @@ static int dns_stub_send_failure(
                         DNS_PACKET_RD(p),
                         !!p->opt,
                         DNS_PACKET_DO(p),
-                        DNS_PACKET_AD(p) && authenticated,
+                        (DNS_PACKET_AD(p) || DNS_PACKET_DO(p)) && authenticated,
                         DNS_PACKET_CD(p),
                         l ? ADVERTISE_EXTRA_DATAGRAM_SIZE_MAX : ADVERTISE_DATAGRAM_SIZE_MAX,
                         dns_packet_has_nsid_request(p) > 0 && !l);
index 9535a7ba4c69021046dcfbd2f7f4025f677570a5..cf10c5c359d3e9215962b2bf8d62ae8dd60a4aa6 100644 (file)
@@ -1142,22 +1142,35 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypt
                                 break;
                         }
 
-                        /* Reduce this feature level by one and try again. */
-                        switch (t->current_feature_level) {
-                        case DNS_SERVER_FEATURE_LEVEL_TLS_DO:
-                                t->clamp_feature_level_servfail = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN;
-                                break;
-                        case DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN + 1:
-                                /* Skip plain TLS when TLS is not supported */
-                                t->clamp_feature_level_servfail = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN - 1;
-                                break;
-                        default:
-                                t->clamp_feature_level_servfail = t->current_feature_level - 1;
-                        }
+                        /* SERVFAIL can happen for many reasons and may be transient.
+                         * To avoid unnecessary downgrades retry once with the initial level.
+                         * Check for clamp_feature_level_servfail having an invalid value as a sign that this is the
+                         * first attempt to downgrade. If so, clamp to the current value so that the transaction
+                         * is retried without actually downgrading. If the next try also fails we will downgrade by
+                         * hitting the else branch below. */
+                        if (DNS_PACKET_RCODE(p) == DNS_RCODE_SERVFAIL &&
+                            t->clamp_feature_level_servfail < 0) {
+                                t->clamp_feature_level_servfail = t->current_feature_level;
+                                log_debug("Server returned error %s, retrying transaction.",
+                                          dns_rcode_to_string(DNS_PACKET_RCODE(p)));
+                        } else {
+                                /* Reduce this feature level by one and try again. */
+                                switch (t->current_feature_level) {
+                                case DNS_SERVER_FEATURE_LEVEL_TLS_DO:
+                                        t->clamp_feature_level_servfail = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN;
+                                        break;
+                                case DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN + 1:
+                                        /* Skip plain TLS when TLS is not supported */
+                                        t->clamp_feature_level_servfail = DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN - 1;
+                                        break;
+                                default:
+                                        t->clamp_feature_level_servfail = t->current_feature_level - 1;
+                                }
 
-                        log_debug("Server returned error %s, retrying transaction with reduced feature level %s.",
-                                  dns_rcode_to_string(DNS_PACKET_RCODE(p)),
-                                  dns_server_feature_level_to_string(t->clamp_feature_level_servfail));
+                                log_debug("Server returned error %s, retrying transaction with reduced feature level %s.",
+                                          dns_rcode_to_string(DNS_PACKET_RCODE(p)),
+                                          dns_server_feature_level_to_string(t->clamp_feature_level_servfail));
+                        }
 
                         dns_transaction_retry(t, false /* use the same server */);
                         return;
index 521264ec29b3b194a8f636fe76157004746b6c5e..5f8bf4377640dfd4af396347bb9265bbba132159 100644 (file)
@@ -305,7 +305,7 @@ static int image_make(
                 }
 
                 /* Get directory creation time (not available everywhere, but that's OK */
-                (void) fd_getcrtime(dfd, &crtime);
+                (void) fd_getcrtime(fd, &crtime);
 
                 /* If the IMMUTABLE bit is set, we consider the directory read-only. Since the ioctl is not
                  * supported everywhere we ignore failures. */
index 511aa7d0313cb40e37cc6c23f5a8a21972fd71f6..742174d6c8907c1602e04b6c203e51f3d86dddbd 100644 (file)
 #include "util.h"
 
 static int sethostname_idempotent_full(const char *s, bool really) {
-        char buf[HOST_NAME_MAX + 1] = {};
+        char buf[HOST_NAME_MAX + 1];
 
         assert(s);
 
-        if (gethostname(buf, sizeof(buf) - 1) < 0)
+        if (gethostname(buf, sizeof(buf)) < 0)
                 return -errno;
 
         if (streq(buf, s))
@@ -42,11 +42,11 @@ int sethostname_idempotent(const char *s) {
 }
 
 bool get_hostname_filtered(char ret[static HOST_NAME_MAX + 1]) {
-        char buf[HOST_NAME_MAX + 1] = {};
+        char buf[HOST_NAME_MAX + 1];
 
         /* Returns true if we got a good hostname, false otherwise. */
 
-        if (gethostname(buf, sizeof(buf) - 1) < 0)
+        if (gethostname(buf, sizeof(buf)) < 0)
                 return false;  /* This can realistically only fail with ENAMETOOLONG.
                                 * Let's treat that case the same as an invalid hostname. */
 
index 3eeee24693ff3d87637df0bf1560e67bdafbfab2..784aad2943fc7a9e9126c2168865342192a0a493 100644 (file)
@@ -215,13 +215,14 @@ int utmp_put_init_process(const char *id, pid_t pid, pid_t sid, const char *line
 }
 
 int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) {
+        _cleanup_(utxent_cleanup) bool utmpx = false;
         struct utmpx lookup = {
                 .ut_type = INIT_PROCESS /* looks for DEAD_PROCESS, LOGIN_PROCESS, USER_PROCESS, too */
         }, store, store_wtmp, *found;
 
         assert(id);
 
-        setutxent();
+        utmpx = utxent_start();
 
         /* Copy the whole string if it fits, or just the suffix without the terminating NUL. */
         copy_suffix(store.ut_id, sizeof(store.ut_id), id);
@@ -339,6 +340,7 @@ int utmp_wall(
         bool (*match_tty)(const char *tty, void *userdata),
         void *userdata) {
 
+        _cleanup_(utxent_cleanup) bool utmpx = false;
         _cleanup_free_ char *text = NULL, *hn = NULL, *un = NULL, *stdin_tty = NULL;
         char date[FORMAT_TIMESTAMP_MAX];
         struct utmpx *u;
@@ -368,7 +370,7 @@ int utmp_wall(
                      message) < 0)
                 return -ENOMEM;
 
-        setutxent();
+        utmpx = utxent_start();
 
         r = 0;
 
index 3c9dc180fa455281486d57d555b7cd8eb3fc3a32..e36bee4e8f97dbe5294956dce887d3e16cb99ca2 100644 (file)
@@ -89,5 +89,7 @@ int main(void) {
         printf("big_enum2_pos → %zu\n", sizeof(big_enum2_pos));
         printf("big_enum2_neg → %zu\n", sizeof(big_enum2_neg));
 
+        printf("timeval: %zu\n", sizeof(struct timeval));
+        printf("timespec: %zu\n", sizeof(struct timespec));
         return 0;
 }
index cb5d42b1d3ff1c7e1fdc34fcbe021e403c31bf3c..9d874cfc8ae0180caa9791ea21d7ee7c0a85a929 100644 (file)
@@ -412,7 +412,7 @@ static int manager_receive_response(sd_event_source *source, int fd, uint32_t re
                 .iov_base = &ntpmsg,
                 .iov_len = sizeof(ntpmsg),
         };
-        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct timeval))) control;
+        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct timespec))) control;
         union sockaddr_union server_addr;
         struct msghdr msghdr = {
                 .msg_iov = &iov,
index d40251331ce85b109ff8b78445d3cee2d277d6fd..5964e30bf1ad6fc5f1a558f9e17bc6ce555c6004 100644 (file)
@@ -28,10 +28,12 @@ static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool te
 
         r = link_config_get(ctx, dev, &link);
         if (r < 0) {
-                if (r == -ENOENT)
-                        return log_device_debug_errno(dev, r, "No matching link configuration found.");
                 if (r == -ENODEV)
                         return log_device_debug_errno(dev, r, "Link vanished while searching for configuration for it.");
+                if (r == -ENOENT) {
+                        log_device_debug_errno(dev, r, "No matching link configuration found, ignoring device.");
+                        return 0;
+                }
 
                 return log_device_error_errno(dev, r, "Failed to get link config: %m");
         }
index 11075c9b96387fcc0806243d5930261a6867f639..da239e36c17036088c5b4286c6a37215b35f76cf 100644 (file)
@@ -348,12 +348,14 @@ run_qemu() {
             [ "$ARCH" ] || ARCH=$(uname -m)
             case $ARCH in
                 ppc64*)
-                KERNEL_BIN="/boot/vmlinux-$KERNEL_VER"
-                CONSOLE=hvc0
-                ;;
+                    # Ubuntu ppc64* calls the kernel binary as vmlinux-*, RHEL/CentOS
+                    # uses the "standard" vmlinuz- prefix
+                    [[ -e "/boot/vmlinux-$KERNEL_VER" ]] && KERNEL_BIN="/boot/vmlinux-$KERNEL_VER" || KERNEL_BIN="/boot/vmlinuz-$KERNEL_VER"
+                    CONSOLE=hvc0
+                    ;;
                 *)
-                KERNEL_BIN="/boot/vmlinuz-$KERNEL_VER"
-                ;;
+                    KERNEL_BIN="/boot/vmlinuz-$KERNEL_VER"
+                    ;;
             esac
         fi
     fi
index 6f54e3f0d5027c78739017187b7a0d94e538189a..3e87bd40a93d25678259348867de17ed55de1e98 100644 (file)
@@ -38,6 +38,10 @@ Id=7
 Family=ipv6
 Blackhole=yes
 
+[NextHop]
+Id=8
+Gateway=fe80::222:4dff:ff:ff:ff:ff
+
 [NextHop]
 Gateway=192.168.5.2
 
index 09aae8067ad9f7ee7047a0e0deda7269b21e06b9..94b2e8730fd973842cebe8fe487bfb2da6d5c26c 100644 (file)
@@ -17,6 +17,10 @@ Destination=2001:1234:5:9fff:ff:ff:ff:ff/128
 [Route]
 Gateway=2001:1234:5:8fff:ff:ff:ff:ff
 
+[Route]
+Destination=2001:1234:5:afff:ff:ff:ff:ff/128
+Gateway=fe80::222:4dff:ff:ff:ff:ff
+
 [Route]
 Destination=149.10.124.64
 Scope=link
diff --git a/test/test-network/conf/networkd-manage-foreign-routes-no.conf b/test/test-network/conf/networkd-manage-foreign-routes-no.conf
new file mode 100644 (file)
index 0000000..c75b8b4
--- /dev/null
@@ -0,0 +1,2 @@
+[Network]
+ManageForeignRoutes=no
index 4279b612d0f52f5c78033b8a193d8245ae351572..4a2af0c50068bd06cb26ed80a0e7ad8452e131a1 100755 (executable)
@@ -16,6 +16,7 @@ from shutil import copytree
 
 network_unit_file_path='/run/systemd/network'
 networkd_runtime_directory='/run/systemd/netif'
+networkd_conf_dropin_path='/run/systemd/networkd.conf.d'
 networkd_ci_path='/run/networkd-ci'
 network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf'
 network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf'
@@ -263,6 +264,7 @@ def setUpModule():
     global running_units
 
     os.makedirs(network_unit_file_path, exist_ok=True)
+    os.makedirs(networkd_conf_dropin_path, exist_ok=True)
     os.makedirs(networkd_ci_path, exist_ok=True)
 
     shutil.rmtree(networkd_ci_path)
@@ -460,6 +462,17 @@ def remove_unit_from_networkd_path(units):
             if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))):
                 shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d'))
 
+def copy_networkd_conf_dropin(*dropins):
+    """Copy networkd.conf dropin files into the testbed."""
+    for dropin in dropins:
+        shutil.copy(os.path.join(networkd_ci_path, dropin), networkd_conf_dropin_path)
+
+def remove_networkd_conf_dropin(dropins):
+    """Remove previously copied networkd.conf dropin files from the testbed."""
+    for dropin in dropins:
+        if (os.path.exists(os.path.join(networkd_conf_dropin_path, dropin))):
+            os.remove(os.path.join(networkd_conf_dropin_path, dropin))
+
 def start_dnsmasq(additional_options='', ipv4_range='192.168.5.10,192.168.5.200', ipv6_range='2600::10,2600::20', lease_time='1h'):
     dnsmasq_command = f'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range={ipv6_range},{lease_time} --dhcp-range={ipv4_range},{lease_time} -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --port=0 ' + additional_options
     check_output(dnsmasq_command)
@@ -1858,6 +1871,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         'routing-policy-rule-reconfigure2.network',
     ]
 
+    networkd_conf_dropins = [
+        'networkd-manage-foreign-routes-no.conf',
+    ]
+
     routing_policy_rule_tables = ['7', '8', '9', '10', '1011']
     routes = [['blackhole', '202.54.1.2'], ['unreachable', '202.54.1.3'], ['prohibit', '202.54.1.4']]
 
@@ -1875,6 +1892,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         remove_routes(self.routes)
         remove_links(self.links)
         remove_unit_from_networkd_path(self.units)
+        remove_networkd_conf_dropin(self.networkd_conf_dropins)
         stop_networkd(show_logs=True)
         call('ip netns del ns99', stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 
@@ -2253,7 +2271,10 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'lookup 7')
         self.assertRegex(output, 'uidrange 100-200')
 
-    def test_route_static(self):
+    def _test_route_static(self, manage_foreign_routes):
+        if not manage_foreign_routes:
+            copy_networkd_conf_dropin('networkd-manage-foreign-routes-no.conf')
+
         copy_unit_to_networkd_unit_path('25-route-static.network', '12-dummy.netdev')
         start_networkd()
         self.wait_online(['dummy98:routable'])
@@ -2266,6 +2287,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         print(output)
         self.assertIn('2001:1234:5:8fff:ff:ff:ff:ff proto static', output)
         self.assertIn('2001:1234:5:8f63::1 proto kernel', output)
+        self.assertIn('2001:1234:5:afff:ff:ff:ff:ff via fe80:0:222:4dff:ff:ff:ff:ff proto static', output)
 
         print('### ip -6 route show default')
         output = check_output('ip -6 route show default')
@@ -2459,6 +2481,13 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
         print(output)
         self.assertEqual(output, '')
 
+        self.tearDown()
+
+    def test_route_static(self):
+        for manage_foreign_routes in [True, False]:
+            with self.subTest(manage_foreign_routes=manage_foreign_routes):
+                self._test_route_static(manage_foreign_routes)
+
     @expectedFailureIfRTA_VIAIsNotSupported()
     def test_route_via_ipv6(self):
         copy_unit_to_networkd_unit_path('25-route-via-ipv6.network', '12-dummy.netdev')
@@ -2907,6 +2936,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
             self.assertIn('id 3 dev veth99', output)
             self.assertIn('id 4 dev veth99', output)
             self.assertRegex(output, 'id 5 via 192.168.10.1 dev veth99 .*onlink')
+            self.assertIn('id 8 via fe80:0:222:4dff:ff:ff:ff:ff dev veth99', output)
             self.assertRegex(output, r'id [0-9]* via 192.168.5.2 dev veth99')
 
             output = check_output('ip nexthop list dev dummy98')
@@ -3614,7 +3644,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities):
 
         output = check_output('ip rule list table 100')
         print(output)
-        self.assertIn('0:      from all to 8.8.8.8 lookup 100', output)
+        self.assertIn('from all to 8.8.8.8 lookup 100', output)
 
 class NetworkdLLDPTests(unittest.TestCase, Utilities):
     links = ['veth99']